Почему код принимается clang, но отклоняется vc++?

clang 3.4 принимает следующий код; в то время как vc++ NOV 2013 CTP отклоняет его с ошибкой:

error C2668: 'AreEqual' : ambiguous call to overloaded function
template<class headT, class... tailTypes>
constexpr headT&& __GetFirst__(headT&& value, tailTypes&&...)
{
    return static_cast<headT&&>(value);
};

template<class T>
constexpr bool AreEqual(const T& a, const T& b)
{   
    return a == b;
}

template<class headT, class... tailTypes>
constexpr bool AreEqual(const headT& head_value, const tailTypes&... tail_values)
{
    return AreEqual(head_value, __GetFirst__(tail_values...))
           && AreEqual(tail_values...);
}

int main()
{
    AreEqual(1, 1, 2, 1);  
}

какой компилятор является правильным в соответствии со стандартом C++14?

Update: полное сообщение об ошибке:

error C2668: 'AreEqual' : ambiguous call to overloaded function
1>          d:\projects\ktl\test\main.cpp(20): could be 'bool AreEqual<headT,int>(const headT &,const int &)'
1>          with
1>          [
1>              headT=int
1>          ]
1>          d:\projects\ktl\test\main.cpp(8): or       'bool AreEqual<headT>(const T &,const T &)'
1>          with
1>          [
1>              headT=int
1>  ,            T=int
1>          ]
1>          while trying to match the argument list '(const int, const int)'
1>
1>Build FAILED.

1 ответов


поведение Clang (и GCC) является правильным. Вы можете прочитать §14.8.2.4 [temp.вычитать.частичное стандарта, как частичное упорядочение шаблонов функций делается, но пример, приведенный в Р8 это раздел непосредственно охватывает такая ситуация:

template<class... Args> void f(Args... args); // #1
template<class T1, class... Args> void f(T1 a1, Args... args); // #2
template<class T1, class T2> void f(T1 a1, T2 a2); // #3
f(); // calls #1
f(1, 2, 3); // calls #2
f(1, 2); // calls #3; non-variadic template #3 is more
         // specialized than the variadic templates #1 and #2