GCC是否正确警告格式字符串与范围枚举不匹配?

Tob*_*ght -1 c++ enums gcc-warning enum-class

当在varargs上下文中使用作用域枚举时,它被定义为作为其基础类型传递,如" 我可以使用枚举类值作为varargs函数的参数吗? "中所解释的那样.据我所知,这是唯一的情况,其中一个范围的枚举将被隐式转换,就像一个无范围的枚举.

考虑这个程序:

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);
}
Run Code Online (Sandbox Code Playgroud)

编译器(g++版本6.3.0)对a的第一个打印很满意Foo,但是当我传递时,抱怨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);
                                  ^
Run Code Online (Sandbox Code Playgroud)

g++版本4.8.2没有抱怨这个,但g++6.3.0确实(这就是为什么它现在关注我).当存在实质性不匹配时,两个版本都抱怨第一次打印,例如使用%f%s,或者如果我Foo改为使用long底层类型; 这就是我启用的原因-Wformat.

我知道警告不是标准一致性问题,我知道如何更改我的代码以解决这些问题(例如,在如何使用C++ 11中输出枚举类的值的答案中使用函数),但是我也相信,如果它们产生误报,那么警告是无益的.当枚举的基础类型与格式字符串中的相应转换规范匹配时,是否存在将范围枚举传递给格式化I/O函数的实际损害?

Som*_*ude 5

这个范围的枚举引用:

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

[强调我的]

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

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


另外,从这个可变参数参考:

bool,char,short,和无作用域枚举被转换成int或更宽整数类型,如整数促进

[再次强调我的]


如果海湾合作委员会正确警告你,那就回答你的问题:是的,这是正确的.你做的不正确.