迭代枚举类:它可以工作,但它符合标准吗?

Ber*_*est 8 c++ enums loops

在下面的 C++ 代码+输出中,以下内容用于迭代枚举类的值,例如 MyEnumClass:(枚举类具有连续值)

for (const auto& e : MyEnumClass() )
{
  // ...
} 
Run Code Online (Sandbox Code Playgroud)

为了使基于范围的 for 循环正常工作,我必须定义运算符 ++ 和 *,以及 begin(MyEnumClass) 和 end(MyEnumClass)。

尽管这有效,但我无法确定这是否是合法的方法。是否符合C++标准?我理解运算符和开始/结束,但是 MyEnumClass() 这里的真正含义是什么?

我希望有人可以阐明这一点。

问候, 伯特维姆

#include <iostream>

enum class MyEnumClass : int
{
   BEGIN,

   ONE=BEGIN, TWO, THREE, FOUR, // consecutive values!

   END
};

auto begin( MyEnumClass )
{
   return MyEnumClass::BEGIN;
}

auto end( MyEnumClass )
{
   return MyEnumClass::END;
}

MyEnumClass operator++( MyEnumClass& p )
{
   return p = static_cast<MyEnumClass>( static_cast<unsigned>( p ) + 1 );
}

MyEnumClass operator*( MyEnumClass p )
{
   return p;
}


int main( int, char*[] )
{
   for (const auto& e : MyEnumClass() )
   {
      std::cout << static_cast<int>( e ) << std::endl;
   }
}
Run Code Online (Sandbox Code Playgroud)

编译运行:(编译器为gcc 11.3.0)
[519] cpptest> g++ main.cpp && ./a.out
0
1
2
3

use*_*522 4

完全没问题。您只需确保您定义的附加函数放置在与枚举完全相同的命名空间中,以便可以通过依赖于参数的查找找到它们。

unsigned您还犯了一个小错误,在其中int一个演员表中使用了 not 。static_cast这个错误可以通过将's 替换为 C++23's来避免std::to_underlying,这在 C++23 之前也可以轻松实现。

另外,使用const auto&而不是仅auto在 range-for 循环中使用有点奇怪。operator*按值返回,因此引用无论如何都会绑定到临时值,从而使引用部分可能产生误导。

MyEnumClass()range-for 循环的范围表达式中只是一个MyEnumClass纯右值,它是值初始化的,这意味着这里初始化为零,意味着这里初始化为static_cast<MyEnumClass>(0),意味着这里初始化为MyEnumClass::BEGIN。所以MyEnumClass()你可以写成MyEnumClass::BEGIN,实际上读起来更清晰。

这种方法的问题在于,该类型MyEnumClass现在表示单个枚举值以及一系列枚举值。这很快就会让人感到困惑。最好编写一个具有适当迭代器的类,该迭代器专门表示枚举范围。