Я пытаюсь осмыслить специализацию шаблона и немного запутался (возможно, не понимаю, что такое typename на самом деле или чего ожидает компилятор)
Пример 1 (компилируется):
template <typename A, typename... Args>
class Example
{
public:
Example(){}
virtual ~Example(){}
};
template <typename A, typename... Args>
class Example<A, int, Args...>{
Example(){}
virtual ~Example(){}
};
Пример 2 (компилируется):
template <typename A, int, typename... Args>
class Example
{
public:
Example(){}
virtual ~Example(){}
};
template <typename A, typename... Args>
class Example<A, 2, Args...>{
Example(){}
virtual ~Example(){}
};
Пример 3 (сбой):
template <typename A, typename... Args>
class Example
{
public:
Example(){}
virtual ~Example(){}
};
template <typename A, typename... Args>
class Example<A, 2, Args...>{
Example(){}
virtual ~Example(){}
};
Ошибка:
ошибка: несоответствие типа / значения в аргументе 2 в списке параметров шаблона для «Пример класса шаблона
Вопросы:
Во-первых, я новичок в общем программировании и надеюсь, что задаю правильные вопросы. Терминология спецификации компилятора все еще немного чужда мне.
- Что случилось? Компилятор пытается рассматривать константу как имя типа?
- Если typename может быть специализирован как int, а int может быть специализирован как 2, почему типовое имя не может быть специализировано как 2?
- Что было бы «правильным» методом для специализации класса с помощью int или enum?
- Я задаю правильные вопросы?
Спасибо
ИЗМЕНИТЬ / Решение:
После того, как я понял, что происходит (из объяснения Якка), вот как выглядит мое окончательное решение. Я где-то читал одного из гуру C ++, что «Вы можете решить любую проблему, добавив еще один уровень абстракции». Теперь я знаю, что это значит: D
enum ETypes
{
UNKNOWN = 0,
INT = 1,
FLOAT = 2,
STRING = 3,
FUNC = 4,
};
// This is to use the ETypes as a type.
// Note that T is not a type, hence use it as RHS
template<ETypes T>
class ETypeName
{
public:
ETypes type = T;
};
// The example
template <typename A, typename... Args>
class Example
{
private:
Example(); // Hide the constructor as private
// to generate compilation error
virtual ~Example(){}
};
// LOOK! We can use the Enum to specialize the class.
template <>
class Example<ETypeName<ETypes::INT>>{
public:
ETypes mType;
Example():mType(ETypes::INT){}
virtual ~Example(){}
};
И в main ():
Example<ETypeName<ETypes::INT>> x;
// This can't happen. Private constructor. Not specialized yet
// Example<ETypeName<ETypes::FLOAT>> x1;