Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
347 views
in Technique[技术] by (71.8m points)

c++ - 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:

#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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Updates!

Since the question is general and in C++17 you can do it better, I would like to give two approaches.

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. This is because the compiler discards the false statement in the if constexpr at compile time.

#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)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...