简体   繁体   English

从枚举中获取所有值

[英]Getting all values from an enum

I have classes in the style of Class1 (see code). 我有Class1风格的Class1 (参见代码)。 An enum and a function to get all the values from the enum. 枚举和函数从枚举中获取所有值。 The values ( FOO_1 , FOO_2 etc) differ from Class to Class as well as the number of values ( sizeof(Foos) ). 值( FOO_1FOO_2等)因类别而异,以及值的数量( sizeof(Foos) )。 I call the function once to get the sizeof the enum, reserve memory and with the second call I want to get all the values to *pFoos ( 2 , 1 , 6 in the sample code). 我调用该函数一旦获取的sizeof枚举,保留存储器以及与所述第二呼叫我想获得的所有值以*pFoos216中的示例代码)。 Is there a better way then using an array with all the values in it ( size_t arr[3] ={FOO_1 , FOO_X, FOO_BAR } )? 有没有更好的方法然后使用包含其中所有值的数组( size_t arr[3] ={FOO_1 , FOO_X, FOO_BAR } )?

class Class1{
    enum Foos{
        FOO_1 = 2,
        FOO_X = 1,
        FOO_BAR = 6
    }
};

Class1::GetFoos(size_t* pFoos, size_t* pSize)
{
    size_t len = sizeof(Foos);
    if (len > *pSize)
    {   //Call function once to get the size
        *pSize= len ;
        return -1;
    }
    for(size_t i = 0; i< *pSize; i++)
    {
       //copy all enum values to pFoos
    }
};

Disclaimer: shameless plug – I am the author. 免责声明:无耻插件 - 我是作者。

Reflective enums are possible in C++. C ++中可以使用反射枚举。 I wrote a header-only library that captures a bunch of "patterns" at compile time and gives you syntax like this: 我编写了一个仅限头文件库,它在编译时捕获了一堆“模式”,并为您提供如下语法:

ENUM(Class1, int, FOO_1 = 2, FOO_X = 1, FOO_BAR = 6)

size_t count = Class1::_size;

for (size_t index = 0; index < Class1::_size; ++index)
    do_anything(Class1::_values()[index]);

What it does internally is use the macro to generate an array of the values that you have declared, kind of like in your question, and use a bunch of other tricks to allow you to use initializers naturally. 它在内部的作用是使用宏来生成您声明的值的数组,类似于您的问题,并使用一堆其他技巧来允许您自然地使用初始化程序。 It then provides iterators and other things on top of the array. 然后它在数组顶部提供迭代器和其他东西。

Here is a link: https://github.com/aantron/better-enums 这是一个链接: https//github.com/aantron/better-enums

EDIT – internals 编辑 - 内部

Here is a pseudocode sketch of what it does internally. 这是一个内部功能的伪代码草图。 The reason I am only giving a "sketch" is because there are a bunch of issues to consider when doing this portably. 我只给出一个“草图”的原因是因为在进行此操作时需要考虑许多问题。 I will touch on all the most important elements. 我会触及所有最重要的元素。

ENUM(Class1, int, FOO_1 = 2, FOO_X = 1, FOO_BAR = 6)

notionally expands to 从概念上扩展到

struct Class1 {
    enum _enumerated { FOO_1 = 2, FOO_X = 1, FOO_BAR = 6 };

    // Fairly obvious methods for how to iterate over _values and
    // _names go here. Iterators are simply pointers into _values
    // and _names below.

    static size_t _size = sizeof(_values) / sizeof(int);

    int _value;
};

int _values[] = {(fix_t<Class1>)Class1::FOO_1 = 2,
                 (fix_t<Class1>)Class1::FOO_X = 1,
                 (fix_t<Class1>)Class1::FOO_BAR = 6};
const char *_names[] = {"FOO_1 = 2", "FOO_X = 1", "FOO_BAR = 6"};

This is done by using variadic macros and stringization. 这是通过使用可变参数宏和字符串化来完成的。 The methods that deal with strings treat not only \\0 , but also space and equals as terminators, which allows them to ignore the initializers in the stringized constants that you see in _names . 处理字符串的方法不仅处理\\0 ,还处理空格和等于终结符,这允许它们忽略在_names看到的字符串化常量中的初始值_names

The type fix_t is necessary because having assignments inside an array initializer is not valid C++. 类型fix_t是必需的,因为在数组初始值设定项中的赋值不是有效的C ++。 What that type does is take on the value of the enum, then ignore the assignment by an overloaded assignment operator, and then return the original value. 该类型的作用是获取枚举的值,然后通过重载的赋值运算符忽略赋值,然后返回原始值。 A sketch: 草图:

template <typename Enum>
struct fix_t {
    Enum _value;

    fix_t(Enum value) : _value(value) { }
    const fix_t& operator =(int anything) const { return *this; }
    operator Enum() const { return _value; }
};

This makes the _values array possible declare even in the presence of initializers. 这使得即使存在初始化器, _values数组也可以声明。

Of course, these arrays need to be prefixed so that you can have more than one enum like this. 当然,这些数组需要加上前缀,以便您可以拥有多个这样的枚举。 They also need to have the same as "extern inline" linkage for functions, so that they are shared between multiple compilation units. 它们还需要与函数的“extern inline”链接相同,以便它们在多个编译单元之间共享。

Until c++ will get reflection you will not get any data from your enum! 在c ++获得反射之前,你不会从你的枚举中获得任何数据! Simply you can not get "all" values from an enum. 只是你无法从枚举中获得“所有”值。 A enum is simply a kind of namespace where some constants can be defined and may be enumerated automatically. 枚举只是一种命名空间,可以定义一些常量并可以自动枚举。 Not more at all. 根本不是。 You have no text representation, no count information, no value to text information! 您没有文字表示,没有计数信息,没有文本信息的价值!

Is there a better way then using an array with all the values in it (size_t arr[3] ={FOO_1 , FOO_X, FOO_BAR })? 有没有更好的方法然后使用包含其中所有值的数组(size_t arr[3] ={FOO_1 , FOO_X, FOO_BAR })?

If you're tagging the question as C++ I advise you to give up with the C way of doing things, so the better way to do this in C++ is using a std::vector : 如果您将问题标记为C ++我建议您放弃使用C语言做事,那么在C ++中更好的方法是使用std::vector

class Class1{
    enum Foos{
        FOO_1 = 2,
        FOO_X = 1,
        FOO_BAR = 6
    };
public:
    std::vector<int> GetFoos()
    {
        // return all enum values
        return {FOO_1, FOO_X, FOO_BAR};
    }
};

You can use it this way: 你可以这样使用它:

Class1 c1;
auto foos = c1.GetFoos();
std::cout << "I have " << c1.size() << " foos:\n";
for (const auto &foo : foos) std::cout << foo << '\n';

If you don't want to create the vector at runtime, you can create it once declaring it static: 如果您不想在运行时创建向量,则可以在将其声明为静态后创建它:

class Alpha{
    enum Alphas{
        BETA = 0b101010,
        GAMMA = 0x20,
        EPSILON = 050
    };
    static const std::vector<int> m_alphas;
public:
    const std::vector<int> &GetAlphas()
    {
        return m_alphas;
    }
};

// https://isocpp.org/wiki/faq/ctors#explicit-define-static-data-mems
const std::vector<int> Alpha::m_alphas = {BETA, GAMMA, EPSILON};

Live demo 现场演示

I know that is a burden to maintain but since there's no way to iterate the values of an enum, all the code that tries to iterate them is a burden as well. 我知道这是一个维护的负担,但由于没有办法迭代枚举的值,所有试图迭代它们的代码也是一个负担。

Maybe in the following answer you can find something useful to iterate enums in a better way for your goals: 也许在以下答案中,您可以找到一些有用的东西,以更好的方式为您的目标迭代枚举:

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

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