2012-02-26 33 views
20

我正在使用作用域枚举来枚举我正在实现的某个状态机中的状态。例如,让我们这样说:作用域枚举等价于“使用namespace X”吗?

enum class CatState 
{ 
    sleeping, 
    napping, 
    resting 
}; 

在我的cpp文件中,我定义了一个状态转移表,我想使用的东西相当于using namespace X这样我就不需要前缀与所有我的状态名称CatState::。换句话说,我想用sleeping而不是CatState::sleeping。我的转换表有很多列,所以避免使用CatState::前缀会使事情更加紧凑和可读。

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


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

+0

你真的需要一个'enum class',还是'enum'呢? – netcoder 2012-02-26 04:06:30

+0

它最初是一个普通的'enum',但我正在转换我的代码以使用C++ 11功能。我喜欢使用'enum class'来强化类型安全的想法。 – 2012-02-26 04:09:36

回答

11

那么,有没有办法避免必须一直键入CatState::

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

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

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

+1

+1谢谢。我在想象强大的枚举类似于命名空间,但将它看作是(某种程度上)类更有意义。 – 2012-02-26 04:02:03

8

你可能会考虑使用typedef缩短合格的名称:

typedef CatState C; 

或者,如果列是,他们可以很容易地生成一种方式重复的,你可以考虑使用宏来生成每个在表格中的行,这可以导致非常简洁(和更容易阅读)的代码。

+0

所以你是说没有相当于使用枚举的'namespace'?如果是这样的话,那么一个简短的typedef对我来说似乎是最好的解决方案。 – 2012-02-26 03:49:11

+0

不是我知道的,没有。您可能能够为每个枚举器使用using声明(例如'使用CatState :: sleeping;'等),但我不是100%确定的。如果代码是高度重复的,但我强烈推荐一个宏。 – 2012-02-26 03:51:45

+0

+1我最终使用了你的typedef建议,但是Nicol给了我的问题直接的答案。我希望我能接受这两个答案。 – 2012-02-26 04:04:22

2

Nicol的回答是正确的:该语言旨在让您总是限定范围的普查员(除了在enum { }范围内)。

然而,here is a technique我想出了在所选择的类中无法显示的“范围”枚举数。从技术上讲,这些统计员是无法比拟的,所以他们仍然会隐式转换为int。 (不像你说的那样是“强类型”)。尽管如此,在成语中,它们是在名称后面使用范围操作符来访问的,因此在语法上没有区别 - 因此它需要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 
}; 
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 

} 
+1

您的'_Enum'和其他'_ [A-Z] +'标识符导致未定义的行为,请参阅[有关下划线的规则](http://stackoverflow.com/a/228797/673852)。也就是说,所有以下划线开头的标识符以及大写字母或其他下划线总是保留用于任何用途。 '如果程序在保留的上下文中声明或定义了一个标识符,那么行为是不确定的。 – Ruslan 2016-01-04 19:57:03

+0

我想你不是来自Windows世界,否则你会知道MS违反了大部分结构标记的标准。我没有说,使用这个代码,因为它是你的个人项目。这些标识符是保留的,这样*普通*程序员就可以遵守规则,并且不会与系统开发者发生冲突。它们是为系统开发人员和像我这样的疯狂的屁股dickheads保留的,他们是做自己的东西的。我编写系统头文件,引导加载程序和操作系统内核,所以这些规则不适合我。比违反这个规则更糟糕的是使用标准的C函数,比如strcpy或asctime。 – Timo 2016-01-06 23:37:16