Как я могу частично специализировать шаблон класса для значений перечислений? - PullRequest
2 голосов
/ 18 июня 2019

можно специализировать шаблоны на основе значений перечисления

#include <type_traits>

template<typename T, typename = void>
struct Specialize
{
};

template<typename T>
struct Specialize<T, typename std::enable_if<std::is_enum<T>::value>::type>
{
    void convert() { }
};

enum E
{
};

int main()
{
    Specialize<E> spec;
    spec.convert();
}

// My doubt: is below code valid? if not how to achieve this?

enum E
{
    E1,
    E2
};

int main()
{
    Specialize<E, E1> spec;
    spec.convert();
}

Это дополнительный вопрос к ответу на вопрос ниже.

Как я могу частично специализировать шаблон класса для ВСЕХ перечислений?

Я скопировал и вставил код из ответа на вопрос, указанный выше.

Я получаю следующую ошибку с моими изменениями.

error: type/value mismatch at argument 2 in template parameter list for _template<class T, class>

Ответы [ 2 ]

4 голосов
/ 18 июня 2019

// Мое сомнение: приведенный ниже код действителен?

Specialize<E, E1> spec;

Краткий ответ: №

Длинный ответ.

Вы определили Specialized как шаблон struct, получив два типа параметры шаблона

template<typename T, typename = void>
struct Specialize
{
};

E - это тип, но E1 - это значение .

если нет, как этого добиться?

Если вы хотите, чтобы ваш struct / class получил в качестве параметров шаблона,тип и значение этого типа, что позволяет специализацию struct / class, если (если и только если) тип является перечислением, вы должны добавить typename = void в качестве третьего параметра шаблона

template<typename T, T Val, typename = void>
struct Specialize
{
};

template<typename T, T Val>
struct Specialize<T, Val, typename std::enable_if<std::is_enum<T>::value>::type>
{
    void convert() { }
};

Начиная с C ++ 17, вы также можете использовать auto в качестве типа для значения шаблона и удалить первый параметр шаблона

template<auto Val, typename = void>
struct Specialize
{
};

template<auto Val>
struct Specialize<Val, std::enable_if_t<std::is_enum_v<decltype(Val)>>>
{
    void convert() { }
};

- EDIT -

ОП спрашивает

как бы мы определили функцию "преобразовать" вне структуры / класса?

К сожалению, я не вижу пути,в этом случае, чтобы избежать повторения std::enable_ifTition

template <typename T, T Val>
struct Specialize<T, Val,
   typename std::enable_if<std::is_enum<T>::value>::type>
 { void convert(); };

template <typename T, T Val>
void Specialize<T, Val,
   typename std::enable_if<std::is_enum<T>::value>::type>::convert ()
 { };
2 голосов
/ 18 июня 2019

Ваш компилятор сообщает, что Specialize<E, E1> spec; недействительно.

Вы можете использовать std::integral_constant для переноса значения в тип.

template<typename T, T V>
struct Specialize<std::integral_constant<T, V>, typename std::enable_if<std::is_enum<T>::value>::type>
{
    void convert() { }
};

int main()
{
    Specialize<std::integral_constant<E, E1>> spec;
    spec.convert();
}
...