我希望编译器发出如下警告:
“香蕉不是一种颜色。”
据我所知,在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;
}
答案 0 :(得分:16)
C ++ 11使用enum
:
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;
}
此代码将完全按照您的意愿失败:
test.cc:18:17:错误:无法将'(Fruit)0'从'Fruit'转换为 '颜色'
注意:enum class
不会导致Green
和Banana
再次出现在封闭的命名空间中,因此您必须明确写入Color::
和Fruit::
现在,但你也得到了类型安全。
我认为在C ++ 03中对此的警告没有多大意义,它基本上只会变成噪音。
人们经常使用enum
作为编译时常量,即使对于比特字段这样的事情也是如此。要使警告有意义,您必须抓住enum { foo=0xf }; int c = foo;
之类的内容,并且许多代码库分散在int
/ enum
次转换中。 (允许这样做会破坏任何更强类型检查的要点)。
更糟糕的是,enum
几乎用于任何类型的元编程上下文,其中匿名enum
不仅可以定期与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;
}
但它们也被递归地用作本地存储:
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 };
};
为了引入一种在C ++中enum class
的当前状态添加类型安全性的非破坏性方法,需要enum
的原因之一。现有代码会发出很多警告,因为像这样的事情,警告旁边就会没用。
即使在您展示的相当简单的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;
}
虽然这在这里是合法的,但它并没有多大的意义,但是像这样的东西仍然使用相当规律和有意义的“bit-twiddling”C代码。这个例子的重点是,通过允许一个int
&lt; - &gt; enum
转换任何地方,它实际上意味着严格关于enum
的类型后来变得毫无意义。在一般情况下,您无法检测是否发生了这种转换(可能是在不同的翻译单元中)。
enum class
是最好的方式,可以干净地引入这种严格性,而不会对现有代码产生负面影响。
答案 1 :(得分:6)
在C ++ 11(新的C ++标准)中,您可以使用enum class
创建强类型枚举。请参阅Wikipedia article on C++11。
示例:
enum class Color { Green };
enum class Fruit { Banana };
// Put your main here - it would now fail