Q:

ISO C++ standard conformant result of the following code

#include <iostream>

template< typename U >
struct base {
    template< typename T >
    base const & operator<<( T x ) const {
        std::cout << sizeof( x ) << std::flush;
        return *this;
    }
};

template< typename U >
struct derived : public base< U > {
    using base<U>::operator<<;

    derived const & operator<<( float const & x ) const {
        std::cout << "derived" << std::flush;
        return *this;
    }
};

int main() {
    unsigned char c( 3 );
    derived< double > d;
    d << c;
    d.operator<<( c );
    return 0;
}

Can you please explain the rules involved to obtain a correct answer of the above code (overloading and overriding in connection with templates, integral promotion, ...)? Is it valid? If the rules are too lengthy please provide literature pointers. The latest compilers disagree about the correct result. gcc-4.6 and icpc-12.1.0 claim "11" is the correct answer but VS2010 refuses to compile d << c; due to ambiguities but accepts d.operator<<( c );. The latter outputs 1 iirc. So who's right and who's wrong?

A:

"11" is the correct output.
For both expressions both the derived operator<< and base operator<< are candidates. Then the candidates are compared based on the implicit conversion sequences they require. Because the base operator<< is a template function where the type T has been deduced to match the argument it comes up as the better match in both cases.
The exact rules are pretty long. You can find the details in section 13.3 Overload resolution of the current C++ draft standard, n3337 linked to in this list of the working group's papers.
If you're asking why MSVC doesn't compile the one statement, I'm not exactly sure, but a function call is ambiguous when there are multiple computed ICSs that are not better than each other (as defined in 13.3.3). MSVC seems to be computing the wrong ICS for at least one of the overloads in the case of d << c, but the diagnostic doesn't give any more details:
error C2666: 'derived<U>::operator <<' : 2 overloads have similar conversions
      with
      [
          U=double
      ]
      ConsoleApplication1.cpp(24): could be 'const derived<U> &derived<U>::operator <<(const float &) const'
      with
      [
          U=double
      ]
      ConsoleApplication1.cpp(14): or       'const base<U> &base<U>::operator <<<unsigned char>(T) const'
      with
      [
          U=double,
          T=unsigned char
      ]
      while trying to match the argument list '(derived<U>, unsigned char)'
      with
      [
          U=double
      ]

