Использование decltype в частичной специализации шаблона - PullRequest
0 голосов
/ 27 сентября 2018

Со следующим шаблоном и специализацией:

template<typename T, typename = void>
struct A {
    void operator()() {
        std::cout << "primary" << std::endl;
    }
};

template<typename T>
struct A<T, decltype(T().f())> {
    void operator()() {
        std::cout << "specialization" << std::endl;
    }
};

используется следующим образом:

struct X {
    bool f() { return false; }
};

int main()
{
    A<X>()();
    return 0;
}

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

template<typename T>
struct A<T, typename std::enable_if<std::is_object<decltype(T().f())>::value>::type> {
    void operator()() {
        std::cout << "specialization" << std::endl;
    }
};

специализация выбирается.Почему в исходном примере не выбрана специализация?

1 Ответ

0 голосов
/ 27 сентября 2018

Вы создали:

A<X>

, который использует параметр шаблона по умолчанию, чтобы стать:

A<X,void>

Однако ваша специализация:

template<typename T>
struct A<T, decltype(T().f())>

Что для параметра шаблона X становится:

struct A<X, decltype(X().f())>

Что является:

struct A<X, bool>

Итак, ваша специализация не является правильным выбором, потому что A<X,bool> не специализируется A<X,void>.


Если вы хотите, чтобы ваша специализация работала для всех правильно сформированных экземпляров T().f(), вы можете использовать C ++ 17's std::void_t

std::void_t оценивается как void для любых правильно сформированных параметров шаблона, переданных ему.

template<typename T>
struct A<T, std::void_t<decltype(T().f())>> {
    void operator()() {
        std::cout << "specialization" << std::endl;
    }
};
...