对于作用域枚举,相当于“使用名称空间X”?

时间:2012-02-26 03:39:15

标签: c++ enums c++11

我正在使用作用域枚举来枚举我正在实现的某个状态机中的状态。例如,让我们说:

enum class CatState
{
    sleeping,
    napping,
    resting
};

在我定义状态转换表的cpp文件中,我想使用等同于using namespace X的东西,这样我就不需要在CatState::前添加所有州名。换句话说,我想使用sleeping代替CatState::sleeping。我的转换表有很多列,因此避免使用CatState::前缀会使事情变得更紧凑和可读。

那么,有没有办法避免一直输入CatState::


是的,是的,我已经意识到using namespace的陷阱。如果有一个强类型枚举的等价物,我保证只在我的cpp实现文件的有限范围内使用它,而不是邪恶。

5 个答案:

答案 0 :(得分:15)

  

那么,有没有办法避免一直输入CatState::

没有。正如没有必要为静态类成员键入ClassName::一样。你不能说using typename ClassName然后进入内部。强类型enum s也是如此。

您当然不能使用enum class语法,只需使用常规enum。但是你失去了强烈的打字。

应该注意的是,对于弱类型枚举使用ALL_CAPS的原因之一是避免名称冲突。一旦我们有完整的作用域和强类型,枚举的名称是唯一标识的,不能与其他名称冲突。能够将这些名称带入命名空间范围将重新引入此问题。因此,您可能希望再次使用ALL_CAPS来帮助消除名称歧义。

答案 1 :(得分:15)

因此简短的答案是“否”,但是幸运的是,这将在最近完成的C ++ 20功能集中改变。根据此accepted proposal,您将可以执行以下操作:

enum class CatState
{
    sleeping,
    napping,
    resting
};

std::string getPurr(CatState state)
{
    switch (state)
    {
        using enum CatState;
        // our states are accessible without the scope operator from now on

        case sleeping:      return {};      // instead of "case CatState::sleeping:"
        case napping:       return "purr";
        case resting:       return "purrrrrr";
    }
}

答案 2 :(得分:8)

您可以考虑使用typedef来缩短限定名称:

typedef CatState C;

或者,如果列的重复方式可以轻松生成,您可以考虑使用宏来生成表中的每一行,这样可以生成非常简洁(也更容易阅读)的代码。

答案 3 :(得分:2)

Nicol的回答是正确的:该语言旨在让您始终限定范围内的枚举数(enum { }范围本身除外)。

然而,here is a technique我提出了在所选类中未对比的“范围”枚举器。从技术上讲,枚举数是无范围的,因此它们仍然会隐式转换为int。 (并不像你所说的那样“强类型”。)然而,在成语中,在真正的enum名称之后使用范围运算符访问它们,所以语法上没有区别 - 因此它需要C + 11。

#define IMPORTABLE_ENUM( TYPENAME, ... ) \
\
struct import_ ## TYPENAME { \
    enum TYPENAME { \
        __VA_ARGS__ \
    }; \
}; \
\
typedef import_ ## TYPENAME :: TYPENAME TYPENAME;

// usage:
IMPORTABLE_ENUM ( duck, huey, dewey, louie )

duck d = duck::dewey; // can't use unscoped enumerators here

struct duck_madness : private import_duck { // but inside a derived class
    duck who_did_it() { return huey; } // qualification is unnecessary
};

答案 4 :(得分:2)

我也很想有这种可能性,我觉得这个限制非常烦人。通常最好让程序员决定他想要使用哪些功能。无论是显式范围还是更方便的方式。如果你限制程序员,他将放弃整个功能,以方便或发明丑陋的变通方法,如下面的基于模板的类型安全枚举。在没有优化的情况下编译时会有一些开销。

template<class _Enum>
class type_safe_enum
{
private:
    _Enum m_EnumValue;
    operator int();
public:
    inline operator _Enum() const { return m_EnumValue; }
    inline void operator =(_Enum x) { m_EnumValue = x; }
};

enum _MY_ENUM
{
    Value1,
    Value2
};

enum _MY_ENUM2
{
    Value3,
    Value4
};

typedef type_safe_enum<_MY_ENUM> MY_ENUM;

void TestMyEnum()
{
    MY_ENUM myEnum;
    int x;

    myEnum = Value1; // ok
    // myEnum = Value3; // compilation error
    // myEnum = 0; // compilation error
    // x = myEnum; // compilation error

}