gpt4 book ai didi

c++ - 如果枚举标签与类型不匹配,编译器是否应该发出警告?

转载 作者:可可西里 更新时间:2023-11-01 15:39:16 24 4
gpt4 key购买 nike

我希望编译器给出这样的警告:

“香蕉不是一种颜色。”

我知道在 switch 语句的上下文中,标签被提升为 int,编译器对 0 很满意并且不关心它是“Green”还是“Banana”。

我希望 GCC 的 -Wconversion 可以解决问题。

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;
}

最佳答案

强类型枚举:

C++11 引入了强类型 enum s,使用 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: error: could not convert '(Fruit)0' from 'Fruit' to 'Color'

备注:enum class不会导致 GreenBanana不再位于封闭的命名空间中,因此您必须显式编写 Color::Fruit::现在,但您获得了类型安全。


C++03中warning的问题

我认为在 C++03 中对此发出警告没有多大意义,它基本上只会变成噪音。

人们使用 enum s 经常用作编译时常量,即使对于位域之类的东西也是如此。为了使警告有意义,您必须捕获类似 enum { foo=0xf }; int c = foo; 的内容许多代码库都散布着 int/enum转换。 (允许这样做会破坏任何更强大的类型检查的意义)。

更糟糕的是 enum s 用于几乎所有类型的元编程上下文,其中匿名 enum s 不仅可以与 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 };
};

这是为什么 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;
}

虽然这在这里是合法的,但意义不大,但类似的东西在“bit-twiddling”C 代码中仍然经常和有意义地使用。这个例子的重点是通过允许一个 int <-> enum conversion anywhere 它实际上意味着对 enum 的类型严格后来变得毫无意义。在一般情况下,您无法检测到是否发生了这种转换(它可能在不同的翻译单元中)。

enum class是迄今为止干净地引入这种严格性而不会对现有代码产生不利影响的最好方法。

关于c++ - 如果枚举标签与类型不匹配,编译器是否应该发出警告?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8166279/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com