未查封的枚举是否仍然有用?

时间:2014-12-05 16:38:11

标签: c++ c++11 enums

我还没有在C ++ 11标准中找到任何措辞,说明未编写的枚举被弃用,但从务实的角度来看,我不知道它们是否仍然有用。我的团队中有很多人养成了将未编写的enum转换为scoped enums的习惯,但它引起了一些麻烦:

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范围内,这样它就不会与其他名称冲突。
  3. 这两点之间的主要区别在于,对于#1,我们不会将它们放在类中,否则会增加一些冗长的间接性。

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

1 个答案:

答案 0 :(得分:5)

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

这有用的一个示例是当您与控件中的API通信时,您的枚举值是位标志。需要uint32_t或其他整数类型作为位标志的API(您无法控制)。

您可以覆盖operator|等,以便将所有内容保存在“类型”中,或者让它们生成基础类型 - 但enum class的单个元素无法隐式转换为uint32_t }。

我觉得有用的无范围enum的另一个用途是替换#define FOO 32样式宏。我获得了一个具有相同含义的令牌,而不是文本替换,我不必重写代码库。如果存在一组紧密排列的此类值,我最终可以达到可以更改int参数的点,这些参数期望这些#define标记与enum值一起传递,并且现在输入参数!

这允许逐步迁移到更好的代码库。

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


另一方面,如果你的枚举实际上只是一组枚举值,并且它们在底层类型中的值是不重要的,那么范围内的枚举几乎总是比未经过编码的枚举更好。它们可以防止意外转换为基础类型:如果基础类型中的值仅仅是实现细节,则此类转换可能会导致错误。

这是我为enum找到的最常见的用例 - 一组可分辨值,其基础类型和值仅仅是一个实现细节。