I'm porting a piece of code which was written for Linux and compiled with gcc v4.8.2 (using -std=c++11) to Windows. Part of it is an overloaded operator<<
which MSVC++ 2013 doesn't agree with. A condensed example is below.
We've defined a custom stream class which supports the standard stream manipulator functions. For this reason we've overloaded operator<<
which accepts a function pointer as second argument.
If I define a templated overload of operator<< for . MSVC++ complains:
error C2676: binary '<<' : 'foobar' does not define this operator or a conversion to a type acceptable to the predefined operator
But if I specify the type of the second argument as std::ostream
instead of the templated std::basis_ostream<..,..>
the code works as expected.
At first I thought I had messed up the template arguments. However, if I define an arbitrary template function instead of an overload of operator<<
the code compiles fine. What's going on here?
Example
#include "stdafx.h"
#include <iostream>
#include <sstream>
#include <string>
struct foobar {
std::stringstream s_;
};
/* Causes compiler error C2676
template <typename CharT = char, typename Traits = std::char_traits<CharT> >
foobar& operator<<(foobar& foo, std::basic_ostream<CharT, Traits>& (*manip)(std::basic_ostream<CharT, Traits>&))
{
foo.s_ << manip;
return foo;
}
*/
/* works as intendend */
foobar& operator<<(foobar& foo, std::ostream& (*manip)(std::ostream&))
{
foo.s_ << manip;
return foo;
}
/* works too */
template <typename CharT = char, typename Traits = std::char_traits<CharT> >
foobar& qux(foobar& foo, std::basic_ostream<CharT, Traits>& (*manip)(std::basic_ostream<CharT, Traits>&))
{
foo.s_ << manip;
return foo;
}
int _tmain(int argc, _TCHAR* argv[])
{
foobar foo;
foo << std::endl;
qux(foo, std::endl);
return 0;
}
std::endl
isn't a function, it is a template function. You pass it to a particular signature, and it finds the overload. You pass it a function with a template of types, and it screws up? But only when you are doing operator overloading. – Yakk - Adam NevraumontCharT
andTraits
can never be deduced (becausestd::endl
is a function template), hence you could as well just use your second version ofoperator<<
. – dyp<<
of amanip
should deduce itsCharT
andTraits
fromstringstream
no? – Yakk - Adam Nevraumontdecltype(foobar::s_)
? – dyp