[英]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.我也不明白为什么这不起作用以及我能做些什么来帮助它。
Since the question is general and in C++17 you can do it better, I would like to give two approaches.由于这个问题很普遍,而且在 C++17 中你可以做得更好,我想给出两种方法。
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 ) (见在线直播)
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.