范围外的枚举仍然有用吗? [英] Are unscoped enumerations still useful?

查看:133
本文介绍了范围外的枚举仍然有用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我没有在C ++ 11标准中找到任何表明不推荐使用无范围枚举的枚举的措词,但是从实用的角度来看,我想知道它们是否仍然有用。我团队中的很多人已经习惯了将无作用域的枚举转换为作用域枚举,但这引起了一些麻烦:

I haven't found any wording in the C++11 standard that says unscoped enums are deprecated, but from a pragmatic perspective I'm wondering if they are still useful. A lot of people on my team have gotten in the habit of converting unscoped enums to scoped enums, but it's caused some headache:

class foo
{
public:
    enum MyEnum { One, Two, Three };
};

他们将其转换为:

class foo
{
public:
    enum class MyEnum { One, Two, Three };
};

这表示何时使用这些枚举器,而不是 foo :: One ,它看起来像 foo :: MyEnum :: One 。我一直在询问以下最佳做法:

Which means when these enumerators are used, instead of foo::One, it looks like foo::MyEnum::One. I've been asking the following best-practices:


  1. 如果您转换为作用域枚举,请将其移出类并移至全局范围或名称空间范围(以提高可用性并避免上面的后一个用法示例)。

  2. 如果使枚举范围不受限制,请确保它在名称空间/类/函数/ etc范围内,以便它不会与其他名称冲突。

两点之间的主要区别在于,对于#1,我们不将其放在类中,

The main difference between the two points is that for #1 we don't put them in classes, which otherwise adds some verbose indirection.

所有这些似乎都太复杂了,只将枚举保留在类中而不是作用域枚举似乎要简单得多。在这两者之间做出决定的一般最佳做法是什么?

All of this seems like over complication, and seems like it would be much simpler to just keep enumerations already in classes as unscoped enums. What's the general best-practice approach for deciding between the two?

推荐答案

作用域枚举器不能隐式转换为其基础类型。如果您需要枚举值隐式转换为其基础类型,则不能使用作用域枚举器。

Scoped enumerators cannot implicitly convert to their underlying type. If you need your enum values to implicitly convert to their underlying type, you cannot use a scoped enumerator.

当与API无法控制,并且枚举值是位标志。期望 uint32_t 或其他整数类型作为位标志的API(您无法控制)。

An example of when this is useful is when you are talking to an API out of your control, and your enum values are bit flags. The API (you don't control) that expects an uint32_t or some other integral type as a bit flag.

您可以覆盖 operator | 等,以使所有内容都保持类型,或让它们生成基础类型,但枚举类不能隐式转换为 uint32_t

You can override operator| etc in order to keep everything "in type", or have them generate the underlying type -- but a single element of your enum class cannot implicitly convert to uint32_t.

另一个不受限制的<$我发现有用的c $ c> enum 是替换 #define FOO 32 样式宏。我得到的是具有相同含义的令牌,而不是文本替换,并且不必重写代码库。如果将这些值紧密地组合在一起,那么我最终可以达到可以更改 int 参数的程度,而这些参数期望这样的 #define 令牌与 enum 值一起传递,并且现在键入参数!

Another use for unscoped enums I find useful is to replace #define FOO 32 style macros. Instead of textual substitution, I get a token that has the same meaning, and I don't have to rewrite the code base. If there are a tightly grouped set of such values, I can eventually reach the point where I can change the int arguments that are expecting such #define tokens to be passed with enum values, and the parameters are now typed!

下一步可能是对这些值使用作用域枚举,但是必须一次性执行所有操作的开销可能意味着可能不采取第一步。完美是善良的敌人。

The next step might be to use scoped enums for those values, but the overhead of having to do everything at once can mean that the first step may not be taken. The perfect is the enemy of the good.

另一方面,如果您的枚举实际上只是一组枚举值,并且它们在基础类型中的值并不重要,因此与未限定范围的枚举相比,范围枚举几乎总是一个更好的主意。它们可以防止意外转换为基础类型:如果基础类型中的值仅是实现细节,则这种转换可能会导致错误。

On the other hand, if your enums are really just a set of enumerated values, and their value in the underlying type is unimportant, then scoped enums are almost always a better idea than unscoped enums. They prevent accidental conversion to the underlying type: if the value in the underlying type is merely an implementation detail, such conversion can cause bugs.

这是迄今为止最常见的我在 enum s中找到用例-一组可区别的值,其基础类型和值仅是实现细节。

This is by far the most common use case I find for enums -- a list of distinguished values, whose underlying type and value is merely an implementation detail.

这篇关于范围外的枚举仍然有用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆