【问题标题】:Map enum value to template argument in C++将枚举值映射到 C++ 中的模板参数
【发布时间】:2017-07-24 09:58:14
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

    我看到的问题:

    1. 您不能使用 template&lt;Enum T&gt; auto makeTemplatedClass(T enumValue),因为 T 不是类型。您只需使用 template&lt;Enum T&gt; auto makeTemplatedClass() 并以不同的方式调用该函数。

    2. 您需要使用TemplatedClass&lt;typename EnumToPrimitiveType&lt;T&gt;::type&gt; 而不仅仅是TemplatedClass&lt;EnumToPrimitiveType&lt;T&gt;::type&gt;。这是必要的,因为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();
    }
    

    【讨论】:

    • 谢谢,您的修复使它确实有效,但不是真正的解决方案,因为 3. 不幸的是;一个基本要求是value 不是const/constexpr。我希望使用template&lt;Enum T&gt; auto makeTemplatedClass(T enumValue) 可以在不指定value 作为模板参数的情况下调用此函数,以便自动推断它,但似乎这不起作用。
    • @misev,既然你知道你不能使用value 作为模板参数,除非它是constconstexpr,你应该回到绘图板上尝试想出一种解决方案,可以使用只能在运行时知道的值。我目前无法提出任何建议,因为我不清楚您真正想要做什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-09
    相关资源
    最近更新 更多