在 C++ 中迭代枚举类的常用方法有哪些?

Gab*_*les 5 c++ enums enumeration enum-class

不幸的是,我发现迭代常规 s 的所有标准技术enum都不适用于enum classes,因为枚举类不会隐式转换为整数。

不是如何迭代枚举?,因为我询问的是 an enum class(即:强类型枚举),而他们询问的是常规enum(即:弱类型枚举)。

康桓瑋*_*康桓瑋 9

另一种替代方法是使用 C++20 范围来组成enum范围:

constexpr inline auto enum_range = [](auto front, auto back) {
  return std::views::iota(std::to_underlying(front), std::to_underlying(back) + 1) 
       | std::views::transform([](auto e) { return decltype(front)(e); }); 
};
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样迭代enum

enum class color { red, yellow, green, blue };
for (const auto e : enum_range(color::red, color::blue))
  // ...
Run Code Online (Sandbox Code Playgroud)

演示。


Gab*_*les 1

这是我能想到的最易读和最简单的方法,但我对其他人的示例解决方案持开放态度。

\n

我发现这种方法易于使用,类似于我的 C 方法(使其更便携且更易于识别),并且适合 C++。它使用-Wall -Wextra -Werror编译器构建选项进行编译。

\n
enum class MyErrorType \n{\n    SOMETHING_1 = 0,\n    SOMETHING_2,\n    SOMETHING_3,\n    SOMETHING_4,\n    SOMETHING_5,\n    /// Not a valid value; this is the number of members in this enum\n    _COUNT,\n    // helpers for iterating over the enum\n    begin = 0,\n    end = _COUNT,\n};\n\nfor (MyErrorType myErrorType = (MyErrorType)0; \n        myErrorType < MyErrorType::_COUNT;\n        myErrorType = static_cast<MyErrorType>((size_t)myErrorType + 1)) \n{\n    switch (myErrorType) \n    {\n        case MyErrorType::SOMETHING_1:\n            break;\n        case MyErrorType::SOMETHING_2:\n            break;\n        case MyErrorType::SOMETHING_3:\n            break;\n        case MyErrorType::SOMETHING_4:\n            break;\n        case MyErrorType::SOMETHING_5:\n            break;\n        case MyErrorType::_COUNT:\n            // This case will never be reached. It is included only so that when\n            // compiling with `-Wall -Wextra -Werror` build flags you get the\n            // added bonus of covering all switch cases (withOUT unnecessarily\n            // relying on a `default` case which would break this feature!), so\n            // if you ever add a new element to the enum class but forget to\n            // add it here to the switch case the compiler will THROW AN ERROR.\n            // This is an added safety benefit to force you to keep your enum\n            // and the switch statement in-sync! It\'s a technique commonly used\n            // in C as well.\n            break;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

阅读我对MyErrorType::_COUNT上述案例的评论!如果您正在使用编译器的-Wall -Wextra -Werror编译器选项,但不在 switch 语句中包含这种情况(因为这些构建选项要求您覆盖所有 switch 语句中的所有枚举情况!),编译器将抛出以下错误并停止!这是一个很好的安全功能,可确保您保持枚举定义和所有 switch 情况同步,处理所有 switch 语句中所有可能的枚举。这是 LLVM 的clang编译器( gcc的替代方案)抛出的编译器错误:

\n
\n
../my_file.cpp:11:16: error: enumeration value \xe2\x80\x98_COUNT\xe2\x80\x99 not handled in switch [-Werror=switch]\n   11 |         switch (myErrorType) {\n      |                ^\n
Run Code Online (Sandbox Code Playgroud)\n
\n

为了清楚起见,对上面代码的另一个微小改进是将beginend元素添加到您的枚举中,如下所示:

\n
../my_file.cpp:11:16: error: enumeration value \xe2\x80\x98_COUNT\xe2\x80\x99 not handled in switch [-Werror=switch]\n   11 |         switch (myErrorType) {\n      |                ^\n
Run Code Online (Sandbox Code Playgroud)\n

...这样您就可以按如下方式迭代枚举。对于所有必需的强制转换,循环的递增部分for仍然有点麻烦,但初始状态和结束条件检查现在至少更加清晰,因为它们使用了MyErrorType::beginand MyErrorType::end

\n
enum class MyErrorType \n{\n    SOMETHING_1 = 0,\n    SOMETHING_2,\n    SOMETHING_3,\n    SOMETHING_4,\n    SOMETHING_5,\n    /// Not a valid value; this is the number of members in this enum\n    _COUNT,\n    // helpers for iterating over the enum\n    begin = 0,\n    end = _COUNT,\n};\n
Run Code Online (Sandbox Code Playgroud)\n

有关的:

\n
    \n
  1. 迭代enums(而不是enum classes)的常用技术:如何迭代枚举?\n
      \n
    1. [我的答案]如何迭代枚举?
    2. \n
    \n
  2. \n
  3. 我对C++ 中enum classes(强类型枚举)和常规enums(弱类型枚举)之间的一些差异的回答:如何自动将强类型枚举转换为 int?
  4. \n
  5. -Wall -Wextra -Werror我关于和其他构建选项的一些个人笔记,来自我的eRCaGuy_hello_world存储库。
  6. \n
  7. \xe2\x80\x9cenum class\xe2\x80\x9d 的递增和递减
  8. \n
\n

其他关键字:C或C++中迭代enum或enum类的常用方式;在 C++ 中迭代枚举类的最佳方法;枚举类 C++ 迭代;C++ 迭代枚举类

\n