2017-03-04 57 views
0

我有一个枚举类与几个成员。枚举的目标是在运行时对原始类型(例如int,long,float,...)进行编码,以便可以将这些信息存储在数据库中。同时也存在很多类模板来处理原始类型。将枚举值映射到C++中的模板参数

问题:我想从这样的模板类创建一个对象,给定一个不是常量的枚举值。这是否可能以更简洁和更具扩展性的方式创建enum值的长开关(或者与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); 
           ^

回答

2

问题,我看到:

  1. 不能使用template<Enum T> auto makeTemplatedClass(T enumValue)因为T不是一种类型。您只需使用template<Enum T> auto makeTemplatedClass()并以不同的方式调用该功能。

  2. 您需要使用TemplatedClass<typenmae EnumToPrimitiveType<T>::type>而不仅仅是TemplatedClass<EnumToPrimitiveType<T>::type>。这是必要的,因为type是一个从属类型。

  3. 不能使用value作为模板参数,除非它是一个constconstexpr

下面的程序编译和构建在我的桌面上。

#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(); 
} 
+0

谢谢,您的修复使它确实工作,但不是真正的解决方案,因为3。一个基本的要求是'value'不是'const' /'constexpr'。我希望通过'template auto makeTemplatedClass(T enumValue)',可以在不指定'value'作为模板参数的情况下调用这个函数,这样就可以自动推断它,但是看起来这不起作用。 – misev

+0

@misev,既然你知道你不能使用'value'作为模板参数,除非它是'const'或'constexpr',那么你应该回到绘图板并尝试提出一个可以处理值的解决方案只能在运行时才知道。目前我无法提出任何建议,因为我不清楚你真的想做什么。 –