10
#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?

4
  • It'll work if you do print(1, 2, 3, std::endl<char, std::char_traits<char>>);, but you probably want a way to not have to write all that extra stuff. Commented Aug 5, 2021 at 11:26
  • 1
    Tricky... I probably would fall back to '\n' (instead of std::endl). Commented Aug 5, 2021 at 11:27
  • Like @Scheff'sCat says, use \n, print(1, 2, 3, '\n'); unless you absolutely must flush the stream too. Commented Aug 5, 2021 at 11:31
  • That’s not a template argument. Commented Aug 5, 2021 at 19:00

3 Answers 3

10

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.

Sign up to request clarification or add additional context in comments.

Comments

7

Here a way:

print(1, 2, 3, std::endl<char, std::char_traits<char>>); 

Consider using '\n' instead.

5 Comments

'\n' does not flush buffer, but std::endl does!. What if OP wants that! Also have a look: Can I take the address of a function defined in standard library?. Therefore, packing into a lambda is the better way.
You mostly only want a \n and if you also want to flush the buffer, do that explicitly. That is why I said "consider using" not "you should"
About taking address of the function, that's how "std::endl" works.
5

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

1 Comment

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.