将枚举值映射到C ++中的类型

时间:2017-01-01 11:57:14

标签: c++ c++11 enums metaprogramming template-meta-programming

有没有办法将枚举值映射到C ++中的类型,包括C ++ 11 我有以下枚举类型:

enum ATTRIBUTE{AGE=0, MENOPAUSE, TUMOR_SIZE, INV_NODES, NODE_CAPS,
               DEG_MALIG, BREAST, BREAST_QUAD, IRRADIAT, CLASS};

我想将此枚举的每个值映射到某种类型。我想将AGE映射到int,将MENOPAUSE映射到另一个枚举类型,将BREAST映射到bool,依此类推。
那么是否可以创建一个返回类型值的函数,该值取决于attr变量的值?

//Like that:
auto value = map_attr(ATTRIBUTE attr);
//Here the type of the value variable should be int if the attr variable is AGE, bool for BREAST and so on.

2 个答案:

答案 0 :(得分:10)

这种惯用方法是使用特征:

enum ATTRIBUTE{ AGE=0, MENOPAUSE, TUMOR_SIZE, INV_NODES, NODE_CAPS, DEG_MALIG, BREAST, BREAST_QUAD, IRRADIAT, CLASS };

template<ATTRIBUTE> struct Map;

template<> struct Map<AGE> {
    using type = int;
    static constexpr type value = 42;
};

template<> struct Map<MENOPAUSE> {
    using type = AnotherEnumType;
    static constexpr type value = AnotherEnumType::AnotherEnumValue;
};

// ...

然后您可以将map_attr定义为函数模板:

template<ATTRIBUTE A>
typename Map<A>::type map_attr() { return Map<A>::value; }

并将其用作:

auto something = map_attr<AGE>();

它遵循一个最小的工作示例:

#include<type_traits>

enum ATTRIBUTE{ AGE=0, MENOPAUSE };

template<ATTRIBUTE> struct Map;

template<> struct Map<AGE> {
    using type = int;
    static constexpr type value = 42;
};

template<> struct Map<MENOPAUSE> {
    using type = double;
    static constexpr type value = 0.;
};

template<ATTRIBUTE A>
typename Map<A>::type map_attr() { return Map<A>::value; }

int main() {
    static_assert(std::is_same<decltype(map_attr<AGE>()), int>::value, "!");
    static_assert(std::is_same<decltype(map_attr<MENOPAUSE>()), double>::value, "!");
}

答案 1 :(得分:0)

我使用 vector<void*> 尝试了 skypjack's answer 中的方法,以更好地理解它:

#include <iostream>
#include <vector>

using namespace std;

enum Types
{
    Int,
    Double
};

//Use struct instead of class for auto-public.
template<Types> struct TypesMap;

template<> struct TypesMap<Int>
{
    using type = int;
};

template<> struct TypesMap<Double>
{
    using type = double;
};

int main() {
    std::vector<void*> Test;
    
    //Note: Memory leak here, but just as an example.
    Test.push_back(new TypesMap<Int>::type(0.5));
    Test.push_back(new TypesMap<Double>::type(0.5));
    
    std::cout << *((TypesMap<Int>::type*)Test[0]) << " " << *((TypesMap<Double>::type*)Test[1]);
    
    return 0;
}

输出:0 0.5

在这里试试:https://ideone.com/0bN1IP

然而,我发现它的问题是您不能将仅限运行时的枚举值(例如,如果您有 vector<Types>)放在 <>当你去使用它时。这严重限制了它的能力。

我的理解是,此限制是由于模板存在仅用于编译时解析。


这里的固有问题是想要动态类型,而 c++ 是静态类型。因此,除非您实现某种大 switch 语句/函数来单独处理每种类型、多态类或其他一些手动类型转换代码,否则不可能在运行时解析这样的动态类型,只有可以在编译时解决的问题。 (如果您可以接受较慢的代码,那么提到的这些其他解决方案可能适合您。)