On 5 April 2012 01:16, Sam Varshavchik wrote: > If I feed the following to gcc 4.6.3: > > #include <sstream> > > class Y : public std::ostringstream { > > public: > using std::ostringstream::operator<<; > }; > > Y y; > > template<typename x> void cast(const x &z) > { > (std::ostringstream &)y << z; > } > > template<typename x> void inherit(const x &z) > { > y << z; > } > > int int_type; > char char_array[10]; > > I get the following results: In all cases the candidate functions are the overloaded ostream::operator<<(T) member functions and the non-member operator<<(ostream&, T) functions. > cast(int_type); // This compiles The best viable function selected by overload resolution is the member ostream::operator<<(int), which is found in the ostringstream's ostream base class. > inherit(int_type); // This compiles The best function is the member Y::operator<<(int), which is declared in Y by the using declaration. > cast(char_array); // This compiles Welcome to Clause 13 ;-) The best function is the non-member operator<<(ostream&, const char*) which requires an implicit conversion from ostringstream& to ostream& for the first argument and array-to-pointer conversion for the second argument. > inherit(char_array); // Failure, gcc complains about an ambiguous overload. Of all the overloads only two are viable, i.e. it has the right number of arguments (they all do) and there is an implicit conversion sequence for all the function arguments that allows the function to be called. The member Y::operator<<(const void*) declared by the using declaration requires no conversion for the first argument (the implicit *this argument) and array-to-pointer conversion then const char* to const void* pointer conversion. The non-member operator<<(ostream&, const char*) requires two conversions, from Y& to ostream& and array-to-pointer conversion. Overload resolution tries to order the overloads based on the conversion sequences to find the best viable function. The implicit conversion sequences for the member function (M) are: ICS1(M): Y& -> Y& and ICS2(M): const char[10] -> const char* -> const void* The implicit conversion sequences for the non-member function (N) are: ICS1(N) Y& -> ostream& ICS2(N) const char[10] -> const char* ICS1(M) is netter than ICS1(N) but ICS2(N) is better than ICS2(M) The rules in [over.match.best] say the functions are ambiguous, because there is no function for which all its conversion sequences are no worse than the other function. Note that in GCC's output those two functions don't give a reason why they can't be called (unlike e.g. ostream::operator<<(int) which says "no known conversion for argument 1 from ‘const char [10]’ to ‘int’"). That's because they are viable, but neither is a better match than the other, so they're ambiguous.