简体   繁体   English

Map 枚举值到 C++ 中的类型

[英]Map enum value to a type in C++

Is there any way to map enum values to types in C++, including C++11.有没有办法将 map 枚举值转换为 C++ 中的类型,包括 C++11。
I have the following enum type:我有以下枚举类型:

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

I want to map each value of this enum to a certain type.我想将此枚举的每个值 map 转换为某种类型。 I want to map AGE to int , MENOPAUSE to another enum type, BREAST to bool and so on.我想 map AGEintMENOPAUSE到另一个枚举类型, BREAST到 bool 等等。
So is it possible to create a function which returns a value of type which depends on the value of the attr variable?那么是否可以创建一个 function 返回一个取决于 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.

An idiomatic way to do it is using traits:一种惯用的方法是使用特征:

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;
};

// ...

Then you can define map_attr as a function template:然后您可以将map_attr定义为函数模板:

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

And use it as:并将其用作:

auto something = map_attr<AGE>();

It follows a minimal, working example:它遵循一个最小的工作示例:

#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, "!");
}

I tried out the approach in skypjack's answer using a vector<void*> , to gain a better understanding of it:我在skypjack 的回答中使用vector<void*>尝试了该方法,以更好地理解它:

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

Output: 0 0.5输出: 0 0.5

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

The problem I've discovered with it, however, is that you cannot put runtime-only enum values (eg if you had a vector<Types> ) in the <> when you go to use it.我与它发现的问题,然而,就是你不能把只运行时枚举值(例如,如果你有一个vector<Types> )在<>当你去使用它。 This severely limits its capabilities.这严重限制了它的能力。

My understanding is that this limitation is due to templating existing only for compile-time resolution.我的理解是,此限制是由于模板仅存在于编译时解析所致。


The inherent problem here is wanting dynamic typing whilest c++ is statically typed.这里的固有问题是想要动态类型,而 c++ 是静态类型。 So, unless you implement some kind of big switch statement/function to handle each type individually, a polymorphic class, or some other manual type conversion code, it is not possible to have dynamic typing like this resolved at runtime, only that which can be resolved at compile-time.因此,除非您实现某种大的switch语句/函数来单独处理每种类型、多态类或其他一些手动类型转换代码,否则不可能在运行时解析这样的动态类型,只有那些可以在编译时解决。 (These other solutions mentioned may be suitable for you if you're okay with somewhat slower code.) (如果您对较慢的代码感到满意,那么提到的这些其他解决方案可能适合您。)

I wrote a header-only lib called magic_params lib to solve exactly this problem, check it out here .我编写了一个名为magic_params lib 的仅标头库来解决这个问题,请在此处查看

Basically you define your mapping from enum to type and default value once and can call it's default value at compile time and set and get different values for every enum at runtime.基本上,您只需定义一次从枚举到类型和默认值的映射,就可以在编译时调用它的默认值,并在运行时为每个枚举设置和获取不同的值。

Example: given an enum like示例:给定一个类似的枚举

enum class Param
{
   one = 0,
   two,
   three
};

you can define your mapping with你可以定义你的映射

static constexpr auto settings = create(
       Add<Param::one, int>(99,Description{"first parameter"}), 
       Add<Param::two, std::string>("Default-String", Description("second parameter")),
       Add<Param::three, bool>(true, Description{"third parameter"}));

and call it like that:并这样称呼它:

constexpr auto value = MyMagicParams::getDefault<Param::two>();

std::cout << "Parameter 'two' has default value " << value;

auto myParams = MyMagicParams();
auto valueBefore = myParams.get<Param::one>();
myParams.set<Param::one>(3);
auto valueAfter = myParams.get<Param::one>();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM