循环枚举值
在枚举上索引循环有多糟糕——或者完全可以接受吗?
我定义了一个枚举。文字的值是默认值。分配的值没有任何意义,将来也不会有任何意义,将来添加的任何文字的值也不会有任何意义。它的定义只是为了限制允许的值并使事情更容易遵循。因此这些值总是从 0 开始并增加 1。
我可以像这样设置一个循环吗:
enum MyEnum
{
value1,
value2,
value3,
maxValue
}
for(MyEnum i = value1; i < maxValue; i = static_cast<MyEnum>(i+1)){}
How awful is it - or is it perfectly acceptable - to index a loop on an enumeration?
I have an enumeration defined. The values of the literals are default values. The assigned values do not have any significance, will not have any significance, and the values of any literals added in the future will also not have any significance. It's just defined to limit the allowed values and to make things easier to follow. Therefore the values will always start at 0 and increase by 1.
Can I set up a loop like so:
enum MyEnum
{
value1,
value2,
value3,
maxValue
}
for(MyEnum i = value1; i < maxValue; i = static_cast<MyEnum>(i+1)){}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
我不久前为这些情况编写了一个枚举迭代器
如果您有兴趣,这里是代码。如果您愿意,您可以通过提供
+
、<
、[]
等将其扩展为随机访问迭代器。像std::distance
这样的算法将通过为随机访问迭代器提供O(1)
时间复杂度来感谢您。I wrote an enum iterator a while ago for these cases
If you are interested, here is the code. If you like, you can extend it to be a random access iterator by providing
+
,<
,[]
and friends. Algorithms likestd::distance
will thank you by providingO(1)
time complexity for the then random-access iterator.就我而言,这很好。我确信某些地方的纯粹主义者会感到害怕,但就语言规范而言,该代码将正常工作,因此如果它能让您的生活更轻松,您应该随意使用它。
As far as I'm concerned, that's just fine. I'm sure some purist out there somewhere will freak out, but as far as the language spec is concerned, that code will work correctly, so you should feel free to go for it if it makes your life easier.
这样做可能会有所帮助。
It might be helpful to do this.
只要您不专门设置枚举值的值就可以。你的例子很好,但这可能很糟糕:
正如 7.2/1 中的标准所述:
That is fine as long as you don't specifically set the value of an enum value. Your example is fine, but this could be bad:
As the standard states in 7.2/1:
我不知道它有任何实际有用的具体用途,我认为这是糟糕的代码。
如果有人像许多图书馆那样放置这样的东西怎么办?
I don't know any specific use of this that is actually useful and I think is bad code.
What if one put things like this as seen in many libraries ?
这并不容易...
我发现的唯一解决方案是通过枚举实际实现一个类,然后使用宏来定义枚举...
基本思想是将值存储在 STL 容器中,静态存储在取决于
MyEnum
符号的模板类。这样你就得到了一个完美定义的迭代,甚至你甚至得到了一个无效状态(因为end()
)。我使用了
pair
的排序向量
,这样我就可以从日志中漂亮的打印和持久的序列化中受益(而且因为它比用于少量数据集的关联容器,占用更少的内存)。我还没有找到更好的方法,C++11 最终是否在枚举上进行迭代?
It's not easy...
The only solution I ever found was to actually implement a class over the enum, and then use a macro to define the enum...
The basic idea is to store the values in a STL container, stored statically in a template class depending on the
MyEnum
symbol. This way you get a perfectly well defined iteration, and you even get an invalid state for naught (because of theend()
).I used a sorted
vector
ofpair<Enum,std::string>
so that I could benefit from pretty printing in the logs and long lasting serialization (and because it's faster than an associative container for little sets of data and takes less memory).I didn't found a better way yet, does C++11 finally get iteration on enums or not ?
请记住,除非这被写入您工作的编码标准中,否则当维护程序员在 6 个月内到来并对枚举进行更改时,例如:
由于新的需求,您将解释为什么他们的合法更改破坏了应用程序。
要将值附加到名称,您可以使用映射:
如果名称不重要,您可以使用 C 样式数组:
或使用 std::vector 的类似方法。
另外,如果你说的是真的,并且
值总是从 0 开始并增加 1
那么我很困惑为什么这不起作用:Keep in mind that unless this is written into the coding standard where you work, when a maintenance programmer comes along in 6 months and makes a change to an enumeration like:
because of a new requirement, you'll get to explain why their legitimate change broke the application.
To attach values to names you could use a map:
If the names don't matter you could use a C-style array:
Or a comparable method using a std::vector.
Also, if what you say is true, and
the values will always start at 0 and increase by 1
then I'm confused as to why this wouldn't work:当我需要迭代时,我通常在枚举中定义开始和结束值,使用如下所示的特殊语法(用 doxygen 样式注释来澄清):
FT_ 可以帮助命名空间(以避免枚举之间的冲突)和双下划线帮助区分真实值和迭代哨兵。
旁注:
写这篇文章时,我开始担心用户标识符不允许使用双下划线(它是保留的实现,IIRC?),但我还没有遇到问题(经过 5-6 年的编码以这种风格)。这可能没问题,因为我总是将所有类型放在命名空间中,以避免污染和干扰全局命名空间。
I usually define begin and end values in my enums when I need iteration, with a special syntax like the following (with doxygen style comments to clarify):
FT_ is there to help with namespacing (to avoid clashes between enums) and the double underscores help distinguish between real values and iteration sentinels.
Sidenote:
Writing this I start worry about the double underscore not being allowed for user identifier (it's implementation reserved, IIRC?), but I'm yet to hit a problem (after 5-6 years of coding in this style). It might be ok since I always put all my types in a namespace to avoid polluting and interfering with the global namespace.
您可以使用 switch 语句包装循环体以防止出现非增量值。它可能非常慢,如 maxValue = 9999;情况,但这可能不是最糟糕的事情。我在我们的代码库中一直看到这种风格
You could wrap the loop body with a switch statement to protect against non-incremental values. It's potentially super slow, as in the maxValue = 9999; case, but it might not be the worst thing ever. I see this style here all the time in our code bases