将枚举值映射到C ++中的模板参数

时间:2017-03-04 07:17:15

标签: c++ c++11 templates enums

我有一个包含几个成员的枚举类。枚举的目标是在运行时对原始类型(例如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);
                                  ^

1 个答案:

答案 0 :(得分: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. 除非是valueconst,否则您无法使用constexpr作为模板参数。

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

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