The following simplified example compiles in gcc and Visual Studio, but fails in clang !?
namespace N
{
    struct A {};
    template <typename T>
    double operator+ (T a, double d) {return d;}
    template <typename T>
    double operator+ (double d, T a) {return d;}
}
void test()
{
    N::A a;
    double x;
    double y = a + x;
    double z = x + a;
}
As I see it, the templated operator+ in namespace N should be found by ADL.
Why does clang disagree ? Is it a bug in clang or in the other compilers ?
Here is the compilation error from clang 3.5.1 (tested on coliru), I don't understand what is the problem here...
10 : error: overloaded 'operator+' must have at least one parameter of class or enumeration type
double operator+ (double d, T a) {return d;}
^
18 : note: in instantiation of function template specialization 'N::operator+' requested here
double y = a + x;
^
7 : error: overloaded 'operator+' must have at least one parameter of class or enumeration type
double operator+ (T a, double d) {return d;}
^
19 : note: in instantiation of function template specialization 'N::operator+' requested here
double z = x + a;
^
2 errors generated.
Compilation failed
The example is simplified from real life code, of course. The intention is that any class defined inside namespace N has an overloaded operator+ with a double.
                        
This is caused by two different CWG issues: CWG issue 2052 and CWG issue 1391.
First, CWG 1391. On encountering
x + a, the usual name lookup finds, among other overloads,Template argument deduction is performed by match
Tto the type of the lhs of+, which isdouble, so this deducesTto bedouble. The second parameter's type contains no template parameter, so is not considered under current rules. To be sure,N::Acan't be converted to adouble, so the resulting specialization is not viable, but the current rules say that template argument deduction doesn't care about this; that will be handled in overload resolution.The proposed resolution to CWG 1391, among other things, adds a new paragraph to the standard:
In other words, if an argument (
ain our case) corresponding to a non-dependent parameter (double) cannot be converted to the parameter's type, deduction would simply fail. So in our case, post-CWG1391 template argument deduction will fail for this overload, and everything would be well.Clang implements the current rules, however, so deduction succeeds with
T = double, substitution occurs, and we encounter CWG 2052. Quoting the writeup from Richard Smith (a Clang dev):In this case, there's no conversion, so the deduced
operator+(double, double)is actually not viable, but non-viable candidates are not eliminated until you have built the candidate set, and here building the candidate set is causing a hard error.The proposed resolution to CWG 2052 will make this case SFINAE instead - also making the original code work. The problem is - Clang is implementing the current version of the standard here, too.