La pregunta puede ser demasiado difícil de describir en una oración del título, pero aquí hay un ejemplo mínimo:
#include <iostream>
#include <type_traits>
template <class T, class U, class Enabler>
struct my_trait : std::false_type
{};
template <class T, class U>
struct my_trait<T, U,
std::enable_if_t<std::is_same<T, U>::value>> : std::true_type
{};
template <class T>
class temped
{};
template <class T>
struct my_trait<temped<T>, temped<T>, void> : std::false_type
{};
template <class T, class U>
using trait_t = my_trait<T, U, void>;
int main()
{
std::cout << std::boolalpha;
std::cout << trait_t<int, float>::value << std::endl; // false
std::cout << trait_t<int, int>::value << std::endl; // true
// Compilation error: Ambiguous
//std::cout << trait_t<temped<int>, temped<int>>::value << std::endl;
return 0;
}
( también disponible en godbolt )
Básicamente, tenemos una clase de plantilla base que my_trait
toma dos tipos (y un tipo ficticio para fines de especialización), con dos especializaciones parciales:
- Cuando los dos tipos son iguales
- Cuando los dos tipos son instanciación de la
temped
plantilla de clase para el mismo tipo
Ingenuamente, hubiéramos esperado que la segunda especialización parcial no fuera ambigua con la primera, ya que se siente "más especializada", poniendo más restricción en los tipos deducidos para T
y U
en la plantilla base. Sin embargo, los principales compiladores parecen estar de acuerdo en que estábamos equivocados con nuestras expectativas: ¿por qué no se considera más especializado?