繁体   English   中英

从枚举中获取所有值

[英]Getting all values from an enum

我有Class1风格的Class1 (参见代码)。 枚举和函数从枚举中获取所有值。 值( FOO_1FOO_2等)因类别而异,以及值的数量( sizeof(Foos) )。 我调用该函数一旦获取的sizeof枚举,保留存储器以及与所述第二呼叫我想获得的所有值以*pFoos216中的示例代码)。 有没有更好的方法然后使用包含其中所有值的数组( 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
    }
};

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

C ++中可以使用反射枚举。 我编写了一个仅限头文件库,它在编译时捕获了一堆“模式”,并为您提供如下语法:

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

编辑 - 内部

这是一个内部功能的伪代码草图。 我只给出一个“草图”的原因是因为在进行此操作时需要考虑许多问题。 我会触及所有最重要的元素。

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看到的字符串化常量中的初始值_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数组也可以声明。

当然,这些数组需要加上前缀,以便您可以拥有多个这样的枚举。 它们还需要与函数的“extern inline”链接相同,以便它们在多个编译单元之间共享。

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

有没有更好的方法然后使用包含其中所有值的数组(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};

现场演示

我知道这是一个维护的负担,但由于没有办法迭代枚举的值,所有试图迭代它们的代码也是一个负担。

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

暂无
暂无

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

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