简体   繁体   English

如何使用可变参数模板打印出函数的参数?

[英]How do I print out the arguments of a function using a variadic template?

This example uses a common variadic template and function.这个例子使用了一个通用的可变参数模板和函数。 I want to print out the arguments passed to f :我想打印出传递给f的参数:

#include <iostream>

template <typename T>
void print(T t) 
{
    std::cout << t << std::endl;
}

template <typename...T>
void f(T &&...args) 
{
    print(args...);
    f(args...);
}

int main() 
{
    f(2, 1, 4, 3, 5);
}

But I am getting the following errors:但我收到以下错误:

Compilation finished with errors:<br>
source.cpp: In instantiation of '`void f(T ...)` [with `T = {int, int, int, int, int}`]':<br>
source.cpp:16:20: required from here <br>
source.cpp:10:4: error: no matching function for call to '`print(int&, int&, int&, int&, int&)`'<br>
source.cpp:10:4: note: candidate is:<br>
source.cpp:4:6: note: `template<class T> void print(T)`<br>
source.cpp:4:6: note: template argument deduction/substitution failed: 
source.cpp:10:4: note: candidate expects 1 argument, 5 provided

This is actually my first time using variadic functions and I do not exactly understand how to use them well.这实际上是我第一次使用可变参数函数,我并不完全了解如何很好地使用它们。

I also do not get why this isn't working and what I can do to help it.我也不明白为什么这不起作用以及我能做些什么来帮助它。

Updates! 更新!

Since the question is general and in C++17 you can do it better, I would like to give two approaches.由于这个问题很普遍,而且在 C++17 中你可以做得更好,我想给出两种方法。

Solution - I解决方案-我

Using fold expression , this could be simply使用折叠表达式,这可能很简单

#include <iostream>
#include <utility>  // std::forward

template<typename ...Args>
constexpr void print(Args&&... args) noexcept
{
   ((std::cout << std::forward<Args>(args) << " "), ...);
}

int main()
{
   print("foo", 10, 20.8, 'c', 4.04f);
}

output:输出:

foo 10 20.8 c 4.04 

( See Live Online ) 见在线直播


Solution - II解决方案——二

With the help of if constexpr , now we can avoid providing base case/ 0-argument case to recursive variadic template function .if constexpr的帮助下,现在我们可以避免向递归可变参数模板函数提供 base case/0-argument case。 This is because the compiler discards the false statement in the if constexpr at compile time.这是因为编译器在编译时丢弃了if constexpr中的 false 语句。

#include <iostream>
#include <utility>  // std::forward

template <typename T, typename...Ts>
constexpr void print(T&& first, Ts&&... rest) noexcept
{
   if constexpr (sizeof...(Ts) == 0)
   {
      std::cout << first;               // for only 1-arguments
   }
   else
   {
      std::cout << first << " ";        // print the 1 argument
      print(std::forward<Ts>(rest)...); // pass the rest further
   }
}

int main()
{
   print("foo", 10, 20.8, 'c', 4.04f);
}

output输出

foo 10 20.8 c 4.04

( See Live Online ) 见在线直播

There you go.你去吧。 You had several mistakes in your code, you can see the comments between the lines below:您的代码中有几个错误,您可以在下面的行之间看到注释:

#include <iostream>

template <typename T>
void print(T t) {
   std::cout << t << std::endl;
}

// Base case, no args
void f() {}

// Split the parameter pack.
// We want the first argument, so we can print it.
// And the rest so we can forward it to the next call to f
template <typename T, typename...Ts>
void f(T &&first, Ts&&... rest) {
    // print it
    print(std::forward<T>(first));
    // Forward the rest.
    f(std::forward<Ts>(rest)...);
}

int main() {
    f(2, 1, 4, 3, 5);
}

Note that using rvalue refs here makes no sense.请注意,在这里使用 rvalue refs 是没有意义的。 You're not storing the parameters anywhere, so simply passing them by const reference should do it.您没有将参数存储在任何地方,因此只需通过 const 引用传递它们就可以了。 That way you'd also avoid using std::forward just to keep the (useless) perfect forwarding.这样你也可以避免使用std::forward来保持(无用的)完美转发。

Therefore, you could rewrite f as follows:因此,您可以按如下方式重写f

template <typename T, typename...Ts>
void f(const T &first, const Ts&... rest) {
    print(first);
    f(rest...);
}

You're recursing infinitely.你无限递归。 You need to remove one element from the pack each time:每次都需要从包中删除一个元素:

void print() { }                            // 0-argument overload

template <typename Head, typename ...Tail>
void print(Head const & h, Tail const &... t)         // 1+-argument overload
{
    std::cout << h;
    print(t...);
}

You can wrap your function call up with the printing:你可以用打印来包装你的函数调用:

template <typename ...Args>
void print_and_f(Args &&... args)
{
    print(args...);
    f(std::forward<Args>(args)...);
}

Usage:用法:

print_and_f(1, 2, 3);  // calls "f(1, 2, 3)" eventually.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将元组扩展为可变参数模板函数的参数? - How do I expand a tuple into variadic template function's arguments? 如何在0可变参数上专门化可变参数模板类? - How do I specialise a variadic template class on 0 variadic arguments? 如何在没有 arguments 的 function 中迭代/获取 static 成员? - How do I iterate over/get static members from the variadic template types in a function with no arguments? 如何 enable_if 具有可变参数模板参数的类? - How do I enable_if a class with variadic template arguments? 如何使用可变参数 arguments 使这个模板专业化成为 class 的朋友? - How do I make this template specialization with variadic arguments a friend of a class? 没有参数的可变参数模板函数 - Variadic template function with no arguments 使用可变参数 arguments 的模板 function 特化 - template function specialization using variadic arguments 如何反转可变参数模板函数的参数顺序? - How to reverse the order of arguments of a variadic template function? 为使用数组、向量、结构等传递给可变参数函数或可变参数模板函数的所有参数指定一种类型? - Specifying one type for all arguments passed to variadic function or variadic template function w/out using array, vector, structs, etc? 没有模板参数的可变参数模板函数 - Variadic template function with no template arguments
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM