Почему частичная специализация шаблона класса для соответствующего класса шаблона неоднозначна с другой частичной специализацией без соответствия шаблона? - PullRequest
8 голосов
/ 20 ноября 2019

Вопрос может быть слишком сложным для описания предложения в названии, но вот минимальный пример:

#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;    
}

( также доступно на Godbolt )

По сути, у нас есть базовый шаблонный класс my_trait, принимающий два типа (и фиктивный тип для целей специализации) с двумя частичными специализациями:

  • Когда два типа одинаковы
  • Когда два типа являются экземплярами шаблона класса temped для одного и того же типа

Наивно, мы ожидали бы, что вторая частичная специализация не будет неоднозначной с первой, как кажется«более специализированный», накладывая больше ограничений на выводимые типы для T и U на базовом шаблоне. Тем не менее, основные компиляторы, похоже, согласны с тем, что мы ошиблись с нашими ожиданиями: почему он не считается более специализированным?

Ответы [ 2 ]

0 голосов
/ 21 ноября 2019

@ теперь удаленный ответ супер получил это в основном правильно. std::enable_if_t<...> не является void в частичном порядке;как зависимый тип в принципе может быть чем-то совершенно произвольным. Он фактически считается совершенно уникальным типом для целей частичного упорядочения.

В результате этого несоответствия вычет при частичном упорядочении не выполняется в обоих направлениях, а специализации неоднозначны.

0 голосов
/ 20 ноября 2019

это потому, что

std::enable_if_t<std::is_same_v<temped<int>, temped<int>> 

преобразуется в void, и тогда у вас есть

my_trait<temped<int>, temped<int>, void>::value 

, который неоднозначно определен как true или false. Если вы измените тип enable_if на, скажем, bool, то все будет нормально скомпилировано

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...