Reputation: 16080
I have stumbled upon an error for which I cannot grasp the reason.
I think it basically gets down to this error:
error: no matching function for call to ‘std::basic_ostream<char>::operator<<(const std::basic_string<char>&)’
I looked into specification on www.cplusplus.com and indeed it says there is no definition for std::ostream::operator<<
with std::string
as an argument.
My question is, what happens when one writes std_ostream_instance << std_fancy_string;
. I believe it is one of the most common invocations ( e.g. std::out << std::string("Hello world!")
) next to const char*
.
The error originates from these lines:
template<typename T>
void Log::_log(const T& msg)
{ _sink->operator<<( msg ); }
_sink
is defied as std::ostream*
There are some wrapping functions around but it breaks here.
I think I could work around by writing
template<>
void Log::_log<std::string>(const std::string& msg) {
_sink->operator<<( msg.c_str() );
}
since there is ostream& operator<< (ostream& out, const unsigned char* s );
defined by default.
I just see no reason why it is not guessed automatically since it clearly works in simple use like cout << any_std_string
.
Not sure if this is relevant but I want to be able to pass down through my log functions anything than can be handled by std::ostream
. I used explicit non-templated declarations but decided to move to template for log(const T& anything_to_log)
to refacator it. It seemed plain stupid to have 5+ overloads. I get the error when I try compiling something like Log::log( std::string("test case") )
.
It looks like something stupid-simple but I cannot get it on my own. Tried to google and search stack to no avail.
With regards, luk32.
PS. I checked the work-around and it works. Why it's not implicitly done ?
Upvotes: 3
Views: 9987
Reputation: 19767
The std::string
version is not a member function, so can't be called as a member of _sink
. Try it this way to pick up both member and non-member versions (in fact it is unlikely you will need the member versions at all anyway):
#include <iostream>
#include <string>
int main()
{
std::ostream * os = &std::cout;
std::string s = "Hello\n";
// This will not work
// os->operator<<(s);
(*os) << s;
return 0;
}
Or better yet would be to store _sink
as a reference, and output exactly as you normally would to cout
.
Upvotes: 5
Reputation: 24439
operator <<
overloads are not members of ostream
. They are freestanding functions, for example
ostream& operator << ( ostream& out, const basic_string<T>& bs );
Try
template<typename T>
void Log::_log(const T& msg)
{ *_sink << msg; }
Upvotes: 9