Определить, является ли тип вектором перечисления - PullRequest
0 голосов
/ 29 марта 2020

Я получаю сообщение об ошибке:

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

в следующем коде:

#include <iostream>
#include <type_traits>
#include <vector>

enum class MyEnum
{
    aaa,
    bbb,
};

template<class T>
struct is_vector_enum
{
    using type = T ;
    constexpr static bool value = false;
};

template<class T, class std::enable_if<std::is_enum<T>::value>::type* = nullptr>  // Error ....
struct is_vector_enum<std::vector<T>>
{
    using type = std::vector<T> ;
    constexpr static bool value = true;
};


int main()
{
    std::cout << "is_vector_enum: " << is_vector_enum<std::vector<MyEnum>>::value << std::endl;
}

Цель состоит в том, чтобы определить, является ли тип вектором перечисления.

Как мне исправить этот код?

Ответы [ 2 ]

4 голосов
/ 29 марта 2020

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

template<class T>
struct is_vector_enum

, а у вашей специализации 2:

template<class T, class std::enable_if<std::is_enum<T>::value>::type* = nullptr>
struct is_vector_enum<std::vector<T>>

Типичный способ сделать это в C ++ 17 - предоставить фиктивного второго параметр шаблона для основного, который по умолчанию равен void, чтобы затем позволить вам выполнить SFINAE во втором параметре:

template <class T, class Enable=void>
struct is_vector_enum { /* ... */ };

template <class T>
struct is_vector_enum<std::vector<T>, std::enable_if_t<std::is_enum_v<T>>> { /* ... */ };

Другой способ сделать это полностью:

template <typename T, std::enable_if_t<std::is_enum_v<T>, int> = 0>
std::true_type impl(std::vector<T> const&);

template <typename T>
std::false_type impl(T const&);

template <typename U>
using is_vector_enum = decltype(impl(std::declval<T>()));

Обратите внимание, что функции impl здесь не определены и не предназначены для вызова.

1 голос
/ 29 марта 2020

Специализациям разрешено иметь количество шаблонных параметров, отличное от основного. На самом деле это случается довольно часто. Однако, как показывает ошибка, вам не разрешено давать какие-либо аргументы по умолчанию.

Кроме того, я предпочитаю простоту, когда это возможно.

template <typename T>
struct is_vector_enum : std::false_type { };

template <typename T>
struct is_vector_enum<std::vector<T>> : std::is_enum<T> { };
...