This is a case of Argument-Dependent-Lookup (ADL). When looking for a potential match for a function call, the compiler first checks the namespace where function's
arguments are declared. The definition of the stream operator in this case is:
|
std::ostream& operator(std::ostream& os, /*some value here*/);
|
Since ostream is defined in the std namespace, the compiler first checks std, and finds the following defined for ostream: (notice that std::string is not here)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
ostream& operator<< (bool val);
ostream& operator<< (short val);
ostream& operator<< (unsigned short val);
ostream& operator<< (int val);
ostream& operator<< (unsigned int val);
ostream& operator<< (long val);
ostream& operator<< (unsigned long val);
ostream& operator<< (float val);
ostream& operator<< (double val);
ostream& operator<< (long double val);
ostream& operator<< (void* val);
ostream& operator<< (streambuf* sb );
ostream& operator<< (ostream& (*pf)(ostream&));
ostream& operator<< (ios& (*pf)(ios&));
ostream& operator<< (ios_base& (*pf)(ios_base&));
|
The compiler checks each name for a match (each of these match the function name) and, if no exact match is found, it tries to find a conversion. Because operator int() is defined, the compiler is able to make a conversion and finishes its search, and does not find your other conversion operator.
Have you tried commenting out operator int() and trying to compile?
As an aside, the common way to implement printing of a user-defined type, write your own << operator for that class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
class String {
char* m_String;
// whatever private implementation ....
public:
const char* c_str() const
{
return m_String
}
};
std::ostream& operator<<(std::ostream& os, const String& str)
{
os << str.c_str();
return os;
}
|