Template type deduction for stream manipulators
c++, iostream, manipulators, templates
Solution
`endl` is a manipulator, i.e. it's an unresolved function type. There are several overloads, and the type deduction is unable to decide which one you want.
More specificly, here's what `endl` looks like (in GNU libc++):
/**
* @brief Write a newline and flush the stream.
*
* This manipulator is often mistakenly used when a simple newline is
* desired, leading to poor buffering performance. See
* http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt11ch25s02.html
* for more on this subject.
*/
template<typename _CharT, typename _Traits>
inline basic_ostream<_CharT, _Traits>&
endl(basic_ostream<_CharT, _Traits>& __os)
{ return flush(__os.put(__os.widen('\n'))); }
Updated So, the problem is, the compiler cannot deduce which instance of `endl` you would be passing (it's an unresolved overload). You might work around this by doing a `static_cast<ostream&(*)(ostream&)>(endl)` instead.
Of course, that's not convenient. Here's a simple fix: http://liveworkspace.org/code/2F2VHe$1
#include <iostream>
using std::cout;
using std::endl;
class Foo : public std::ostream
{
public:
template<typename T>
Foo& operator<<(T&& t) {
cout << std::forward<T>(t);
return *this;
}
typedef std::ostream& (manip)(std::ostream&);
Foo& operator<<(manip& m) {
cout << m;
return *this;
}
};
int main() {
Foo foo;
foo << "Hello World"; // perfectly fine
foo << endl; // everything is fine
return 0;
}
Problem
I'm unsure as to whether this code will not compile. The example code I'm working with: ``` #include <iostream> using std::cout; using std::endl; class Foo { public: template<typename T> Foo& operator<<(const T& t) { cout << t; return *this; } }; int main() { Foo foo; foo << "Hello World"; // perfectly fine foo << endl; // shit hits the fan return 0; } ``` This is the error: ``` test.cpp:19:12: error: no match for ‘operator<<’ in ‘foo << std::endl’ test.cpp:19:12: note: candidates are: test.cpp:10:14: note: template<class T> Foo& Foo::operator<<(const T&) test.cpp:10:14: note: template argument deduction/substitution failed: test.cpp:19:12: note: couldn't deduce template parameter ‘T’ ``` I'm confused as to why it cannot substitute the function type of `endl` (`ostream& (*)(ostream&)`) for `T`, where it clearly is fine with doing it when you specify `cout << endl;` I find it additionally puzzling that this fixes the problem [ edited ] ``` Foo& operator<<(ostream& (*f)(ostream&)) { cout << f; return *this; } ``` In case the question isn't clear, I'm asking why it could not deduce the template in the first place.