2014-12-05 79 views
4

我还没有在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. 如果您转换为范围的枚举,将其移出的类和成全局范围或命名空间范围(以提高可用性,并避免上述后者使用示例)。
  2. 如果你保持enum unscoped,确保它在namespace/class/function/etc范围内,这样它就不会与其他名称发生冲突。

两点之间的主要区别在于#1我们不把它们放在类中,否则会增加一些冗长的间接性。

所有这些看起来都像是过于复杂化,并且似乎将枚举已经存在于类中作为unscoped枚举要简单得多。决定两者之间的一般最佳实践方法是什么?

+2

切换到'enum class'的好处是您可以阅读关于为何添加它的所有内容;切换到'enum class'的缺点就是你上面写的所有东西。但是,这并不能告诉我们从头开始编写代码时要做什么。 – 2014-12-05 16:40:24

+1

第二次使用有什么问题? – Daniel 2014-12-05 16:40:48

+1

@Daniel冗长。这就像使用2个嵌套命名空间来处理对象,只有1个就足够了。 – 2014-12-05 16:41:27

回答

5

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

时,这是非常有用的一个例子是,当你说话的API在你的控制,你的枚举值是位标志。 API(你不控制)期望uint32_t或其他整数类型作为位标志。

您可以覆盖operator|等,以“型”,以确保一切,或让他们产生的基本类型 - 但你enum class不能隐式转换为uint32_t一个元素。

另一种用于无标记的enum s我发现有用的是替换#define FOO 32样式的宏。代替文本替换,我得到一个具有相同含义的标记,而且我不必重写代码库。如果有紧紧地组合组这样的价值观,我可以最终达到的地步,我可以改变int论点,期待这样的#define令牌与enum值过去了,如今的参数类型!

这使得朝着更好的代码基地逐步迁移。

下一步可能是使用范围的枚举这些值,但不得不做的一切,在一次的开销可能意味着第一步可以不考虑。完美是善的敌人。


在另一方面,如果你的枚举其实只是一组枚举值,以及它们在基础类型的值是不重要的,则作用域枚举几乎总是比未范围枚举一个更好的主意。它们可以防止意外转换为基础类型:如果基础类型中的值仅仅是实现细节,则此类转换可能导致错误。

这是迄今为止我发现的最常见的用例enum s - 一个区分值的列表,其基础类型和值仅仅是一个实现细节。