获取枚举中的所有值

时间:2015-06-08 12:43:30

标签: c++ enums

我的课程风格为Class1(见代码)。枚举和函数从枚举中获取所有值。值(FOO_1FOO_2等)因类与类以及值的数量(sizeof(Foos))而异。 我调用函数一次得到枚举的大小,保留内存,第二次调用我想得到*pFoos 216的所有值在示例代码中)。 有没有更好的方法然后使用包含其中所有值的数组(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
    }
};

3 个答案:

答案 0 :(得分:5)

免责声明:无耻的插件 - 我是作者。

C ++中可以使用反射枚举。我写了一个仅限标题的库,它捕获了一堆&#34;模式&#34;在编译时,并提供如下语法:

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]);

它在内部的作用是使用宏来生成您声明的值的数组,类似于您的问题,并使用一堆其他技巧来允许您自然地使用初始化程序。然后它在数组顶部提供迭代器和其他东西。

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

编辑 - 内部

这是一个内部功能的伪代码草图。我之所以给出一个&#34; sketch&#34;是因为在进行此操作时需要考虑一些问题。我会谈谈所有最重要的因素。

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

从概念上扩展到

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

这是通过使用可变参数宏和字符串化来完成的。处理字符串的方法不仅要处理\0,还要处理空格和等于终结符,这样就可以忽略_names中看到的字符串化常量中的初始值设定项。

类型fix_t是必需的,因为在数组初始值设定项中的赋值不是有效的C ++。该类型的作用是获取枚举的值,然后通过重载的赋值运算符忽略赋值,然后返回原始值。草图:

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

这使得即使存在初始值设定项,_values数组也可以声明。

当然,这些数组需要加上前缀,以便您可以拥有多个这样的枚举。他们还需要和#34; extern inline&#34;函数的链接,以便它们在多个编译单元之间共享。

答案 1 :(得分:3)

在c ++获得反射之前,你不会从你的枚举中获得任何数据!只是你无法从枚举中获得“所有”值。枚举只是一种命名空间,可以定义一些常量并可以自动枚举。根本不是。您没有文本表示,没有计数信息,没有文本信息的价值!

答案 2 :(得分:1)

  

是否有更好的方法使用包含其中所有值的数组(size_t arr[3] ={FOO_1 , FOO_X, FOO_BAR })?

如果您将问题标记为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};
    }
};

你可以这样使用它:

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

如果您不想在运行时创建向量,可以在声明为静态后创建向量:

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

我知道维护是一种负担,但由于无法迭代枚举的值,所有尝试迭代它们的代码也是一种负担。

也许在以下答案中,您可以找到一些有用的东西,以更好的方式迭代枚举: