#include <iostream>
template<typename... Args>
void print(Args const&... args)
{
(std::cout << ... << args);
}
int main()
{
std::cout << 1 << 2 << 3 << std::endl; // ok
print(1, 2, 3); // ok
print(1, 2, 3, std::endl); // error! How to make it work?
}
See online demo
How to pass a function template as a template argument?
Templates can be template parameters. In this case, they are called template parameters. The container adaptors std::stack, std::queue, and std::priority_queue use per default a std::deque to hold their arguments, but you can use a different container.
A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
You will have the same issue with other io manipulators that typically are functions that take the stream as parameter, when they are templates. Though you can wrap them in a non-template callable:
#include <iostream>
template<typename... Args>
void print(Args const&... args)
{
(std::cout << ... << args);
}
int main()
{
std::cout << 1 << 2 << 3 << std::endl; // ok
print(1, 2, 3); // ok
print(1, 2, 3, [](std::ostream& o) -> std::ostream&{
o << std::endl;
return o;
}); // no error!
}
Output:
123
123123
The syntax is rather heavy so you might want to use a helper type, though I'll leave it to you to write that (just joking, I don't think it is trivial, but I might give it a try later ;). After pondering about it for a while, I am almost certain that there are only the two alternatives: Instantiate the function (see other answer), or wrap the call inside a lambda, unless you want to write a wrapper for each single io manipulator of course.
Here a way:
print(1, 2, 3, std::endl<char, std::char_traits<char>>);
Consider using '\n'
instead.
You cannot take address of most standard functions (see can-i-take-the-address-of-a-function-defined-in-standard-library).
Fortunately, io-manipulator is part of the exception (See Addressable_functions).
std::endl
is a template function, so you would have to select the correct overload.
using print_manip_t = std::ostream& (*) (std::ostream&);
print(1, 2, 3, print_manip_t{std::endl});
print(1, 2, 3, static_cast<print_manip_t>(std::endl));
print(1, 2, 3, static_cast<std::ostream& (*) (std::ostream&)>(std::endl));
else you have to specify which one you want
print(1, 2, 3, std::endl<char, std::char_traits<char>>);
or wrap it
print(1, 2, 3, [](std::ostream& o) -> std::ostream&{ return o << std::endl; });
Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With