在下面的 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
完全没问题。您只需确保您定义的附加函数放置在与枚举完全相同的命名空间中,以便可以通过依赖于参数的查找找到它们。
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现在表示单个枚举值以及一系列枚举值。这很快就会让人感到困惑。最好编写一个具有适当迭代器的类,该迭代器专门表示枚举范围。