Reputation: 15284
class Test {
public:
operator string() {
return string{"TEST!"};
}
};
int main() {
cout << Test{};
}
I was expecting the Test object will be implicit converted to a string and output, but it gives me error:
error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
This explicit conversion works:
cout << string{Test{}};
I got it working by casting to const char*
:
class Test {
public:
operator const char*() {
return "TEST!";
}
};
Then output:
cout << Test{}; //Yay it works.
I am assuming the cout << string
is already an implicit conversion from string
to char *
and if I use casting to string, it will not perform a two level conversion from Test to string to char *
. After directly casting to const char*
, it works. (Please correct if the assumption is wrong)
TO PROVE THE ASSUMPTION IS RIGHT
class Test {
public:
operator string() {
return string{"TEST!"};
}
};
ostream& operator<< (ostream& os, string s){
os << s;
return os;
}
This will perform a direct type deduction from Test to string
and output string. and after I tried, it works!
cout << Test{}; //YAY WORKS! OUTPUT "TEST!"
Something special about cout << string
is explained by Borgleader
. Assumption is partially correct and partially wrong.
Upvotes: 1
Views: 1080
Reputation: 15916
The explicit
keyword means you have to explicitly do the conversion yourself like std::string(Test{})
. It disables implicit conversions.
cout << string{Test{}}; // <-- this is explicit, you've got implicit and explicit confused
The rule is, during template argument deduction, no user defined conversion is attemped. However, as you've noted if you only have a conversion operator to int it compiles. That is because that overload is not a function template. Take a look at the reference page, and you will see:
basic_ostream& operator<<( int value );
This is a non-templated overload so the compiler will look for user defined conversions.
Upvotes: 4
Reputation: 109119
The operator<<
overload that takes an std::string
(or std::basic_string
) is a function template. User defined conversions are not considered during template argument deduction, so the compiler doesn't think the string
overload is a match.
To avoid the error, define an overload basic_ostream& operator<<(basic_ostream&, Test&)
for your class.
Upvotes: 2