Ответ 1
Здесь немного другое воспроизведение, которое не основано на неполных типах:
template <auto> struct foo { static constexpr int value = 0; };
template <int I> struct foo<I> { static constexpr int value = 1; };
// ok on gcc, fires on clang which thinks foo<42L>::value is 1
static_assert(foo<42L>::value == 0);
Это лягушка. 42L
явно соответствует auto
, никаких вопросов нет. Но соответствует ли он int I
? Нет, из [temp.deduct.type]/19:
Если
P
имеет форму, содержащую<i>
, и если типi
отличается от типа соответствующего параметра шаблона, названного с помощью простого ID-шаблона-шаблона, вывод не выполняется. ЕслиP
имеет форму, содержащую[i]
, и если типi
не является целочисленным, вывод не выполняется. [Пример:template<int i> class A { /* ... */ }; template<short s> void f(A<s>); void k1() { A<1> a; f(a); // error: deduction fails for conversion from int to short f<1>(a); // OK } template<const short cs> class B { }; template<short s> void g(B<s>); void k2() { B<1> b; g(b); // OK: cv-qualifiers are ignored on template parameter types }
— end example ]
Чтобы увидеть, соответствует ли 42L
специализации, нам нужно вывести int I
из 42L
, и это не удалось. Следовательно, мы придерживаемся основной специализации. Clang не делает этого. Подано 43076.