在枚举类别上迭代:它有效,但是它是否符合标准?

发布于 2025-02-13 03:35:43 字数 1063 浏览 0 评论 0原文

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

for (const auto& e : MyEnumClass() )
{
  // ...
} 

,以使基于范围的For-Forop工作,我必须定义操作员++和 *,以及开始(肌cl)和结束(肌cl)。

尽管这有效,但我找不到这是否是合法的方法。是根据C ++标准吗?我了解操作员并开始/结束,但是MyenumClass()的真正含义是什么?

我希望有人可以为此提供一些启示。

问候, Bertwim

#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;
   }
}

编译和运行:(编译器为GCC 11.3.0)
[519] cpptest&gt; g ++ main.cpp&amp;&amp; ./a.out
0
1
2
3

In the c++ code below+output, the following is used to iterate over the values of an enum class, say MyEnumClass: (the enum class has contiguous values)

for (const auto& e : MyEnumClass() )
{
  // ...
} 

In order for the range-based for-loop to work, I had to define the operators ++ and *, as well as begin(MyEnumClass) and end(MyEnumClass).

Although this works, I have not been able to find if it is a legitimate approach. Is it according to the C++ standard? The operators and begin/end I understand, but what is really the meaning here of MyEnumClass()?

I hope there is somebody who can shed some light on this.

Regards,
Bertwim

#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;
   }
}

Compilation and run: (compiler is gcc 11.3.0)
[519] cpptest> g++ main.cpp && ./a.out
0
1
2
3

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

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

发布评论

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

评论(1

伴梦长久 2025-02-20 03:35:43

很好。您只需要确保定义的附加功能与枚举完全相同的名称空间,以便可以通过参数依赖性查找找到它们。

您还使用无符号而不是int在其中一个铸件中犯了一个小错误。可以通过用C ++ 23's std :: to_underlying 也可以在C ++ 23之前轻松实现。

另外,在“范围”循环中使用const auto&amp;,而不是auto有点奇怪。 运算符*正在返回副词,因此,无论如何,该引用都将被绑定到临时性,从而使参考零件可能误导。

myenumclass()在范围循环的范围表达中只是一个myenumclass prvalue,它是价值initialized的,这意味着在此处为零initialized,这意味着此处初始化为<<<<<<代码> static_cast&lt; myenumclass&gt;(0),这意味着此处初始化为myenumclass ::开始。因此,代替myenumclass()您可以写myenumclass :: begin,它实际上读取更清晰。

这种方法的问题在于类型myenumclass现在代表单个枚举值以及一系列枚举值。那会很快令人困惑。最好用适当的迭代器编写专门代表枚举范围的课程。

It is perfectly fine. You only need to make sure that the additional functions you defined are placed in exactly the same namespace as the enumeration, so that they can be found via argument-dependent lookup.

You also made a minor mistake by using unsigned instead of int in one of the casts. This mistake can be avoided by replacing the static_cast's with C++23's std::to_underlying, which can also easily be implemented before C++23.

Also, using const auto& instead of just auto in the range-for loop is a bit weird. operator* is returning by-value, so the reference will anyway be bound to a temporary, making the reference part potentially misleading.

MyEnumClass() in the range-expression of the range-for loop is simply a MyEnumClass prvalue which is value-initialized, meaning here zero-initialized, meaning here initialized to static_cast<MyEnumClass>(0), meaning here initialized to MyEnumClass::BEGIN. So instead of MyEnumClass() you could have written MyEnumClass::BEGIN, which actually reads clearer.

The problem with this approach is that the type MyEnumClass now represents a single enumeration value as well as a range of enumeration values. That can get confusing quickly. It would be preferable to write a class with proper iterators which specifically represents the enumeration range.

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