我有一个包含几个成员的枚举类。枚举的目标是在运行时对原始类型(例如int,long,float,...)进行编码,以便可以将此信息存储在数据库中。与此同时,也存在很多模仿原始类型的类。
问题:我想从这样的模板类创建一个对象,给定一个不是常量的枚举值。这是否有可能比在枚举值上创建长开关更清晰,更具可扩展性(或者与Dynamic mapping of enum value (int) to type的答案中提出的地图基本相同)?
这是我一直在尝试希望模板类型推断可以工作的东西,但它无法编译(可以在这里检查,例如:http://rextester.com/VSXR46052):
#include <iostream>
enum class Enum {
Int,
Long
};
template<Enum T>
struct EnumToPrimitiveType;
template<>
struct EnumToPrimitiveType<Enum::Int> {
using type = int;
};
template<>
struct EnumToPrimitiveType<Enum::Long> {
using type = long;
};
template<typename T>
class TemplatedClass
{
public:
TemplatedClass(T init): init{init} {}
void printSize() { std::cout << sizeof(init) << std::endl; }
private:
T init;
};
template<Enum T>
auto makeTemplatedClass(T enumValue) -> TemplatedClass<EnumToPrimitiveType<T>::type>
{
TemplatedClass<EnumToPrimitiveType<T>::type> ret(5);
return ret;
}
int main()
{
Enum value{Enum::Int};
auto tmp = makeTemplatedClass(value);
tmp.printSize();
}
编译错误:
source_file.cpp:36:27: error: expected ‘)’ before ‘enumValue’
auto makeTemplatedClass(T enumValue) -> TemplatedClass<EnumToPrimitiveType<T>::type>
^
source_file.cpp:36:6: warning: variable templates only available with -std=c++14 or -std=gnu++14
auto makeTemplatedClass(T enumValue) -> TemplatedClass<EnumToPrimitiveType<T>::type>
^
source_file.cpp:36:38: error: expected ‘;’ before ‘->’ token
auto makeTemplatedClass(T enumValue) -> TemplatedClass<EnumToPrimitiveType<T>::type>
^
source_file.cpp: In function ‘int main()’:
source_file.cpp:44:16: error: ‘A’ is not a member of ‘Enum’
Enum value{Enum::A};
^
source_file.cpp:45:34: error: missing template arguments before ‘(’ token
auto tmp = makeTemplatedClass(value);
^
答案 0 :(得分:2)
我看到的问题:
由于template<Enum T> auto makeTemplatedClass(T enumValue)
不是类型,因此您无法使用T
。您只需使用template<Enum T> auto makeTemplatedClass()
并以不同方式调用该函数。
您需要使用TemplatedClass<typenmae EnumToPrimitiveType<T>::type>
而非TemplatedClass<EnumToPrimitiveType<T>::type>
。这是必要的,因为type
是一个依赖类型。
除非是value
或const
,否则您无法使用constexpr
作为模板参数。
以下程序在我的桌面上编译和构建。
#include <iostream>
enum class Enum {
Int,
Long
};
template<Enum T>
struct EnumToPrimitiveType;
template<>
struct EnumToPrimitiveType<Enum::Int> {
using type = int;
};
template<>
struct EnumToPrimitiveType<Enum::Long> {
using type = long;
};
template<typename T>
class TemplatedClass
{
public:
TemplatedClass(T init): init{init} {}
void printSize() { std::cout << sizeof(init) << std::endl; }
private:
T init;
};
template<Enum T>
auto makeTemplatedClass() -> TemplatedClass<typename EnumToPrimitiveType<T>::type>
{
TemplatedClass<typename EnumToPrimitiveType<T>::type> ret(5);
return ret;
}
int main()
{
Enum const value{Enum::Int};
auto tmp = makeTemplatedClass<value>();
tmp.printSize();
}