-1

在可变参数上下文中使用作用域枚举时,它被定义为作为其基础类型传递,如“我可以使用枚举类值作为可变参数函数的参数吗? ”范围内的枚举将被隐式转换,就像无范围的枚举一样。

考虑这个程序:

enum Foo : char { F };
enum class Bar : char { B };

#include <cstdio>
int main()
{
    return !std::printf("%c\n", Foo::F)
        +  !std::printf("%c\n", Bar::B);
}

编译器(g++版本 6.3.0)对 a 的第一次打印很满意Foo,但是当我通过 a 时会抱怨Bar

0.cpp: In function ‘int main()’:
0.cpp:10:34: warning: format ‘%c’ expects argument of type ‘int’, but argument 2 has type ‘Bar’ [-Wformat=]
         +  !printf("%c\n", Bar::B);
                                  ^

g++版本 4.8.2 没有抱怨这一点,但g++6.3.0 确实如此(这就是我现在担心的原因)。当存在实质性不匹配时,两个版本都会抱怨第一次打印,例如使用%for %s,或者如果我更改Foo为使用long基础类型;这就是我启用-Wformat.

我知道警告不是标准一致性问题,并且我知道如何更改我的代码来解决这些问题(例如,在How can I output the value of an enum class in C++11? 的答案中使用函数),但是我还认为,如果警告会产生误报,则它们将无济于事。当枚举的基础类型与格式字符串中的相应转换规范匹配时,将作用域枚举传递给格式化的 I/O 函数是否有任何潜在的实际危害?

4

1 回答 1

5

这个范围枚举参考

没有从作用域枚举器的值到整数类型的隐式转换,...

[强调我的]

这意味着无论基类型如何,作用域枚举都不会隐式转换为int(或任何其他整数类型)。您必须明确地进行转换,例如static_cast(接上一个引用):

...虽然static_cast可用于获取枚举数的数值。


此外,从这个可变参数参考

bool, char, short, 和无作用域的枚举被转换为int或更宽的整数类型,就像在整数提升中一样

[再次强调我的]


并回答您的问题,如果 GCC 正确地警告您:是的,它是正确的。你在做什么是不正确的。

于 2017-02-08T09:37:42.157 回答