无作用域枚举是否仍然有用
Are unscoped enumerations still useful?
我在 C++11 标准中没有发现任何说不推荐使用无作用域枚举的措辞,但从实用的角度来看,我想知道它们是否仍然有用。我的团队中的很多人已经养成了将无作用域枚举转换为作用域枚举的习惯,但这引起了一些头痛:
class foo
{
public:
enum MyEnum { One, Two, Three };
};
他们将其转换为:
class foo
{
public:
enum class MyEnum { One, Two, Three };
};
这意味着当使用这些枚举器时,而不是foo::One
,它看起来像foo::MyEnum::One
。我一直在问以下最佳实践:
- 如果转换为作用域枚举,请将其移出类并移入全局作用域或命名空间作用域(以提高可用性并避免上述后一个用法示例(。
- 如果使枚举保持无作用域,请确保它位于命名空间/类/函数/等作用域中,以便它不会与其他名称冲突。
这两点之间的主要区别在于,对于 #1,我们不会将它们放在类中,否则会增加一些详细的间接性。
所有这些似乎都过于复杂,并且似乎将类中已有的枚举保留为无作用域枚举要简单得多。在两者之间做出决定的一般最佳实践方法是什么?
域枚举器不能隐式转换为其基础类型。 如果需要枚举值隐式转换为其基础类型,则不能使用作用域枚举器。
例如,当您与不受控制的 API 通信并且枚举值是位标志时,这很有用。 需要 uint32_t
或某些其他整型作为位标志的 API(您不控制(。
您可以覆盖 operator|
etc 以保持所有内容"类型",或者让它们生成底层类型 - 但enum class
的单个元素不能隐式转换为 uint32_t
。
我觉得无作用域enum
的另一个用途是替换#define FOO 32
样式宏。 我得到的不是文本替换,而是具有相同含义的令牌,并且我不必重写代码库。 如果有一组紧密分组的此类值,我最终可以更改期望使用enum
值传递此类#define
令牌的int
参数,并且现在键入了参数!
这允许逐步迁移到更好的代码库。
下一步可能是对这些值使用作用域枚举,但必须一次执行所有操作的开销可能意味着可能无法执行第一步。 完美是好的敌人。
另一方面,如果您的枚举实际上只是一组枚举值,并且它们在基础类型中的值并不重要,那么作用域枚举几乎总是比无作用域枚举更好。 它们可以防止意外转换为基础类型:如果基础类型中的值只是一个实现细节,则此类转换可能会导致 bug。
这是迄今为止我发现的最常见的enum
用例 - 一个可区分值的列表,其底层类型和值只是一个实现细节。
- 在提升multi_index容器中,是否定义了"default index"?
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 检查输入是否不是整数或数字
- 是否可以初始化不可复制类型的成员变量(或基类)
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 是否有任何情况下,具有已删除CTOR的课程可能有用
- std::unique_ptr<std::array<T,N是否有用例>>
- 移动const对象是否有有用的方案
- 仅在constexpr/编译时上下文中操作时,引用是否有用
- wchar_t对Windows API是否有用
- Sublime Text 2用作C IDE是否有用?[VS.视觉工作室]
- 是否可以进行编译,以使错误的std::vector访问调用退出程序,并显示有用的错误消息
- 虚拟基类是否是可行和/或有用的功能
- 我做了两个模板类,任何人都可以告诉我这些东西是否有用
- 将覆盖关键字和最终关键字与相同的成员函数一起使用是否有用
- 无作用域枚举是否仍然有用
- 递归是一件坏事吗?在递归似乎最有用的地方,是否有更清晰或更有效的方法来解决问题?
- 是否有用c++编写的Firefox 5插件示例?
- new 运算符 - 在C++中测试"new"的返回是否有用?