Die Frage mag zu schwer zu beschreiben sein, aber hier ist ein minimales Beispiel:
#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;
}
( auch auf godbolt erhältlich )
Grundsätzlich haben wir eine Basisvorlagenklasse my_trait
mit zwei Typen (und einem Dummy-Typ für Spezialisierungszwecke) mit zwei Teilspezialisierungen:
- Wenn die beiden Typen gleich sind
- Wenn die beiden Typen die Instanziierung der
temped
Klassenvorlage für denselben Typ sind
Naiv hätten wir erwartet, dass die zweite Teilspezialisierung nicht mehrdeutig mit der ersten ist, da sie sich "spezialisierter" anfühlt und die abgeleiteten Typen für T
und U
auf die Basisvorlage stärker einschränkt . Die großen Compiler scheinen jedoch zuzustimmen, dass wir mit unseren Erwartungen falsch lagen: Warum wird es nicht als spezialisierter angesehen?