Несколько объявлений структуры шаблона, используемых для получения enum, описывающих тип шаблона

#c #templates #traits

#c #шаблоны #Трейты

Вопрос:

У меня есть следующий перечислитель:

 enum class VariableType
{
    Basic,
    Vector2,
    Vector3,
    Vector4
};
 

и 3 шаблона векторного класса: Vector2, Vector3 и Vector4.

Я ищу функцию, используемую для инициализации переменных VariableType с помощью, передавая тип данных в параметре шаблона.

Например:

 auto type1 = GetVariableType<float>::type; // type1 = VariableType::Basic
auto type2 = GetVariableType<Vector2<float> >::type; // type1 = VariableType::Vector2
 

Мне пришла в голову идея определить GetVariableType дважды, с разными шаблонами, но код не компилируется, когда я пишу второе определение ( std::enable_if_t::value>).

 template<typename T, typename = std::enable_if_t<IsBasicType<T>::value>>
struct GetVariableType
{
    static const VariableType type = VariableType::Basic;
};

template<typename T, typename = std::enable_if_t<IsVector2Type<T>::value>>
struct GetVariableType
{
    static const VariableType type = VariableType::Vector2;
};
 

Есть какие-нибудь идеи, как я должен различать определения?

Ответ №1:

Не уверен, но мне кажется, что вы ищете что-то вроде

 template<typename T>
struct GetVariableType
 { static constexpr VariableType type = VariableType::Basic; };

template<typename T>
struct GetVariableType<Vector2<T>>
 { static constexpr VariableType type = VariableType::Vector2; };

template<typename T>
struct GetVariableType<Vector3<T>>
 { static constexpr VariableType type = VariableType::Vector3; };

template<typename T>
struct GetVariableType<Vector4<T>>
 { static constexpr VariableType type = VariableType::Vector4; };
 

просто используя специализацию шаблона.

Предложение не по теме: избегайте указания имени type переменной.

В стандартной библиотеке type-traits идентификатор type обычно используется для определения (через a using или a typedef ) типа, а не переменной.

Ответ №2:

Если вы хотите, чтобы это работало с переменными (как следует из названия вашего шаблона) вместо типов, тогда вы можете сделать:

 template<typename T> VariableType GetVariableType (T) {return VariableType::Basic; };
template<typename T> VariableType GetVariableType (Vector2 <T>) { return VariableType::Vector2; };
template<typename T> VariableType GetVariableType (Vector3 <T>) { return VariableType::Vector3; };
template<typename T> VariableType GetVariableType (Vector4 <T>) { return VariableType::Vector4; };
 

И тогда вы можете сделать (например):

 float f = 0;
auto type1 = GetVariableType (f);
std::cout << (int) type1 << 'n';

Vector2 <float> v2;
auto type2 = GetVariableType (v2);
std::cout << (int) type2 << 'n';
 

Выходной сигнал:

 0
1
 

Живая демонстрация