是否有任何众所周知的迭代枚举值的范例?

发布于 2024-08-02 02:52:48 字数 721 浏览 6 评论 0原文

我有一些 C++ 代码,其中声明了以下枚举:

enum Some 
{
   Some_Alpha = 0,
   Some_Beta,
   Some_Gamma,
   Some_Total
};
int array[Some_Total];

Alpha、Beta 和 Gamma 的值是连续的,我很乐意使用以下循环来迭代它们:

for ( int someNo = (int)Some_Alpha; someNo < (int)Some_Total; ++someNo ) {}

这个循环没问题,直到我决定更改例如,枚举中的声明将 Beta 设为第一个值,将 Alpha 设为第二个值。 这会使循环标头无效,因为现在我必须从 Beta 迭代到 Total。 那么,迭代枚举的最佳实践是什么? 我想迭代所有值,而不是每次都更改循环标题。 我可以想到一个解决方案:

enum Some 
{
   Some_Start = -1,
   Some_Alpha,
   ...
   Some_Total
};
int array[Some_Total];

从 (Start + 1) 迭代到 Total,但它看起来很难看,而且我从未见过有人在代码中这样做。 是否有任何众所周知的迭代枚举的范例,或者我只需要修复枚举值的顺序? (让我们假设,我确实有一些很棒的理由来更改枚举值的顺序)...

I have some C++ code, in which the following enum is declared:

enum Some 
{
   Some_Alpha = 0,
   Some_Beta,
   Some_Gamma,
   Some_Total
};
int array[Some_Total];

The values of Alpha, Beta and Gamma are sequential, and I gladly use the following cycle to iterate through them:

for ( int someNo = (int)Some_Alpha; someNo < (int)Some_Total; ++someNo ) {}

This cycle is ok, until I decide to change the order of the declarations in the enum, say, making Beta the first value and Alpha - the second one. That invalidates the cycle header, because now I have to iterate from Beta to Total.
So, what are the best practices of iterating through enum? I want to iterate through all the values without changing the cycle headers every time. I can think of one solution:

enum Some 
{
   Some_Start = -1,
   Some_Alpha,
   ...
   Some_Total
};
int array[Some_Total];

and iterate from (Start + 1) to Total, but it seems ugly and I have never seen someone doing it in the code. Is there any well-known paradigm for iterating through the enum, or I just have to fix the order of the enum values? (let's pretend, I really have some awesome reasons for changing the order of the enum values)...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

内心旳酸楚 2024-08-09 02:52:48

您可以为enum定义一个operator++()。 这样做的优点是它使用了众所周知的标准增量运算符范例。 :)

根据您的枚举是否连续,您可以将它们视为 int 或使用开关:

Some& operator++(Some& obj)
{
# if YOUR_ENUMS_ARE_CONTIGUOUS
  int i = obj;
  if( ++i > Some_Total ) i = Some_Alpha;
  return obj = static_cast<Some>(i);
# else 
  switch(obj)
  {
    case Some_Alpha : obj = Some_Beta;  break;
    case Some_Beta  : obj = Some_Gamma; break;
    case Some_Gamma : obj = Some_Total; break;
    case Some_Total : obj = Some_Alpha; break;
    default: assert(false); // changed enum but forgot to change operator
  }
  return obj;
# endif
}

请注意,如果 operator++() 是定义后,用户可能也会期望有一个operator--()

You can define an operator++() for your enum. This has the advantage that it uses the well-known paradigm of the standard incrementation operators. :)

Depending on whether your enums are contiguous, you can treat them as int or use a switch:

Some& operator++(Some& obj)
{
# if YOUR_ENUMS_ARE_CONTIGUOUS
  int i = obj;
  if( ++i > Some_Total ) i = Some_Alpha;
  return obj = static_cast<Some>(i);
# else 
  switch(obj)
  {
    case Some_Alpha : obj = Some_Beta;  break;
    case Some_Beta  : obj = Some_Gamma; break;
    case Some_Gamma : obj = Some_Total; break;
    case Some_Total : obj = Some_Alpha; break;
    default: assert(false); // changed enum but forgot to change operator
  }
  return obj;
# endif
}

Note that, if operator++() is defined, users will probably expect an operator--(), too.

淡淡離愁欲言轉身 2024-08-09 02:52:48

不,没有办法做到这一点,因为不能保证有人没有编写过如下代码:

enum Some 
{
   Some_Alpha = 0,
   Some_Beta,
   Some_Gamma = 42,
   Some_Delta, 
  Some_Total
};

No, there is no way of doing this because there is no guarantee that someone hasn't written code like:

enum Some 
{
   Some_Alpha = 0,
   Some_Beta,
   Some_Gamma = 42,
   Some_Delta, 
  Some_Total
};
请别遗忘我 2024-08-09 02:52:48

您可以使用静态类成员。

这篇文章中的示例及其源代码

You can use static class members.

Examples in this article with its source code.

变身佩奇 2024-08-09 02:52:48

在 C++11(可能更早)中,您可以使用以下 hack 来使 Some 可迭代:(

Some operator++(Some& s) {
    return s = (Some )(std::underlying_type<Some>::type(x) + 1); 
}
Some operator*(Some s) {
    return s;
} 
Some begin(Some s) {
    return Some_Alpha;

Some end(Some s) {
    return Some_Gamma;
}

int main() { 
    // the parenthesis here instantiate the enum
    for(const auto& s : Some()) { 
        // etc. etc.
    }
    return 0;
}

这个答案无耻地改编自 此处。)

In C++11 (and probably earlier), you could use the following hack, to make Some iterable:

Some operator++(Some& s) {
    return s = (Some )(std::underlying_type<Some>::type(x) + 1); 
}
Some operator*(Some s) {
    return s;
} 
Some begin(Some s) {
    return Some_Alpha;

Some end(Some s) {
    return Some_Gamma;
}

int main() { 
    // the parenthesis here instantiate the enum
    for(const auto& s : Some()) { 
        // etc. etc.
    }
    return 0;
}

(This answer was shamelessly adapted from here.)

神经暖 2024-08-09 02:52:48
enum Some
{
   Some_first_ = 0,
   Some_Alpha = Some_first_,
....
   Some_last_
};

这样做你可以首先授予& 最后一个永远不会改变顺序

enum Some
{
   Some_first_ = 0,
   Some_Alpha = Some_first_,
....
   Some_last_
};

Doing such you can grant first & last never changes order

玩心态 2024-08-09 02:52:48

如果不使用任何赋值,则保证枚举是连续的,从 0 作为第一个枚举开始。
其他。

您能做的最好的事情就是按照您在枚举定义中想要的顺序保留它们,并使用 for 循环循环遍历它们。

If you do not use any assignments, the enums are guaranteed to be sequential starting with 0 as the first.
thers.

The best thing you can do is keep them in the order you want in your enum definition, and cycle through them with the for loop.

护你周全 2024-08-09 02:52:48

我将所有枚举放在它们自己的命名空间中。 示例:

namespace Foo {
enum Enum {
    First=0, // must be sequential
    Second,
    Third,
    End // must be last
};
}

在代码中:

for (int i=Foo::First; i!=Foo::End; i++) {
// do stuff
}

这是因为 C++ 允许这样的东西(未在编译器中测试):

enum Foo {
Alpha = 1
};

enum Bar {
Beta = 2
};

Foo foo = Beta;

这显然是错误的。

I place all Enums in their own namespace. Example:

namespace Foo {
enum Enum {
    First=0, // must be sequential
    Second,
    Third,
    End // must be last
};
}

In code:

for (int i=Foo::First; i!=Foo::End; i++) {
// do stuff
}

This is because C++ allows stuff like this (not tested in a compiler):

enum Foo {
Alpha = 1
};

enum Bar {
Beta = 2
};

Foo foo = Beta;

Which is clearly wrong.

月下客 2024-08-09 02:52:48

在 C# 应用程序中,我有一个图标,用户可以单击该图标来更改列表的排序顺序。 这是枚举:

private enum sortByValues
{
    Date,
    Distance,
    Time,
    Speed,
    Name,
    LastOne
 }

 private sortByValues sortByValue = sortByValues.Date;

请注意,值“LastOne”不会向用户显示(或者更确切地说,不会显示适当的图标),而是用作表示枚举结尾的标记。

然后,当用户单击图标来更改排序顺序时,我只需增加 sortByValue 并检查它是否到达末尾。 如果有,我将其重置为第一个枚举值:

sortByValue++;

if (sortByValue is sortByValues.LastOne) sortByValue = sortByValues.Date;

In a C# app, I have an icon that the user can click to change the sort order of a list. Here is the enum:

private enum sortByValues
{
    Date,
    Distance,
    Time,
    Speed,
    Name,
    LastOne
 }

 private sortByValues sortByValue = sortByValues.Date;

Note the value "LastOne" is not shown to the user (or, rather, an appropriate icon isn't) but used as a marker to denote the end of the enum.

Then when the user clicks the icon to change the sort order I simply increment sortByValue and check if it's reached the end. If it has, I reset it to the first enum value:

sortByValue++;

if (sortByValue is sortByValues.LastOne) sortByValue = sortByValues.Date;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文