Cannot have typeof(std::endl) as template parameter?
c++, c++11, variadic-templates
Solution
`std::endl` is a template, not a function, and the compiler cannot resolve which `endl` to use.
Try:
append_to_stream(std::cout,
std::endl<char, std::char_traits<char>>,
std::endl<char, std::char_traits<char>>);
Or, MooingDuck's solution (corrected):
template<class e, class t, class a> //string version
std::basic_ostream<e, t>& (*get_endl(const std::basic_string<e, t, a>&))
(std::basic_ostream<e, t>& )
{ return std::endl<e,t>; }
template<class e, class t> //stream version
std::basic_ostream<e, t>& (*get_endl(const std::basic_ostream<e, t>&))
(std::basic_ostream<e, t>& )
{ return std::endl<e,t>; }
int main () {
std::ostream& stream = std::cout;
append_to_stream(stream,
get_endl(stream),
get_endl(stream));
}
Here is get_endl solution, simplified by C++11 `decltype` feature:
template<class e, class t, class a> //string version
auto get_endl(const std::basic_string<e, t, a>&)
-> decltype(&std::endl<e,t>)
{ return std::endl<e,t>; }
template<class e, class t> //stream version
auto get_endl(const std::basic_ostream<e,t>&)
-> decltype(&std::endl<e,t>)
{ return std::endl<e,t>; }
int main () {
std::ostream& stream = std::cout;
append_to_stream(stream,
get_endl(stream),
get_endl(stream));
}
Problem
So, I was trying to write a function like this: ``` void append_to_stream(std::ostream &stream) { } template <typename T, typename... Args> void append_to_stream(std::ostream &stream, T first, Args&&... rest) { stream << first; append_to_stream(stream, rest...); } ``` and call it like: ``` append_to_stream(stream, std::endl, std::endl); ``` But this doesn't work. I get an error that says 'too many arguments' to the function. I've narrowed it down to the point I know that the `std::endl` is guilty - probably because it's a function. I managed to 'solve' this by declaring a struct called `endl` and define the `<<operator` for it so that it simply calls `std::endl`. This works but doesn't feel particularly good. Is it not possible to accept std::endl as a template argument? The function works for other types. Edit: here's the error: ``` src/log/sinks/file_sink.cpp:62:21: error: too many arguments to function ‘void log::sinks::append_to_stream(std::string&, Args&& ...) [with Args = {}, std::string = std::basic_string<char>]’ ``` Update Trying to get the compiler to deduce the correct template arguments @MooingDuck suggested that a function of the following form could be used: ``` template<class e, class t, class a> basic_ostream<e,t>&(*)(basic_ostream<e,t>&os) get_endl(basic_string<e,t,a>& s) { return std::endl<e,t>; } ``` However, this doesn't compile. Error: ``` src/log/sinks/file_sink.cpp:42:28: error: expected unqualified-id before ‘)’ token src/log/sinks/file_sink.cpp:42:53: error: expected initializer before ‘get_endl’ ``` Any ideas why? For the sake of compiling this, I've added `using namespace std;`