我希望编译器发出如下警告:
"香蕉不是一种颜色."
据我所知,在switch语句的上下文中,标签被提升为int,编译器对0感到满意,并不关心它是"Green"还是"Banana".
我希望 - GCC的转换可以解决这个问题.
enum Color
{
Green = 0
};
enum Fruit
{
Banana = 0
};
int main()
{
Color c = Green;
switch (c)
{
case Banana:
std::cerr << "Banana" << std::endl;
break;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Fle*_*exo 16
C++ 11引入了强类型enums,使用enum class:
#include <iostream>
enum class Color
{
Green = 0
};
enum class Fruit
{
Banana = 0
};
int main() {
Color c = Color::Green;
switch (c)
{
case Fruit::Banana:
std::cerr << "Banana" << std::endl;
break;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此代码将完全按照您的意愿失败:
test.cc:18:17:错误:无法将'(Fruit)0'从'Fruit'转换为'Color'
注意:enum class不会导致Green和Banana进入封闭的命名空间,所以你必须明确地写Color::,Fruit::现在,但你也得到类型安全.
我不认为C++ 03中对此的警告会有很大意义,它基本上只会变成噪音.
人们enum经常使用s作为编译时常量,即使对于比特字段这样的事情也是如此.为了使警告有意义,你必须抓住类似的东西enum { foo=0xf }; int c = foo;,许多代码库都分散在int/ enum转换中.(允许这会破坏任何更强类型检查的要点).
更糟糕的是enum,几乎在任何类型的元编程上下文中都会使用它,其中匿名enums不仅可以int定期与类型自由交替使用:
template <int I>
struct is_odd {
enum { value = !(I % 2) };
};
template <int I>
struct foo {
static void bar() { /* I is true */ }
};
template <>
struct foo<0> {
static void bar() { /* I is false */ }
};
int main() {
foo<is_odd<201>::value>::bar();
int i = is_odd<200>::value;
}
Run Code Online (Sandbox Code Playgroud)
但它们也被递归地用作本地存储:
template <int N>
struct factorial {
enum {
// This enum is *not* compatible with the one in N-1
value = N * factorial<N - 1>::value
};
};
template <>
struct factorial<0> {
enum { value = 1 };
};
Run Code Online (Sandbox Code Playgroud)
这是为什么enum class需要引入一种enum在C++ 当前状态下添加类型安全性的非破坏性方法的部分原因.现有代码会发出如此多的警告,由于这样的事情,警告旁边是无用的.
即使在您展示的相当简单的switch语句示例中,这样的内容也是合法的:
#include <iostream>
enum Color { Green = 0x1, Red = 0x2 };
enum Fruit { Banana = 0x3 };
int main() {
int v = Green|Red;
Color c = Color(v);
switch (c) {
case Banana:
std::cerr << "Banana" << std::endl;
break;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
虽然这在这里是合法的,但它并没有太大的意义,但是像这样的东西仍然使用相当规律和有意义的"bit-twiddling"C代码.这个例子的要点是,通过在任何地方允许一个int< - > enum转换,它实际上意味着对enum后面的类型的严格限制变得毫无意义.在一般情况下,您无法检测是否发生了这种转换(它可能位于不同的翻译单元中).
enum class 到目前为止,这是彻底引入这种严格性的最好方法,而不会对现有代码产生负面影响.
在C++ 11(新的C++标准)中,您可以使用它enum class来创建强类型枚举.请参阅有关C++ 11的维基百科文章.
例:
enum class Color { Green };
enum class Fruit { Banana };
// Put your main here - it would now fail
Run Code Online (Sandbox Code Playgroud)