【发布时间】:2017-02-08 09:10:16
【问题描述】:
在可变参数上下文中使用作用域枚举时,它被定义为作为其基础类型传递,如“Can I use enum class values as arguments to varargs functions?”中所回答的那样据我了解,这是唯一会转换作用域枚举的情况隐含地,就像一个无范围的枚举一样。
考虑这个程序:
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 版)对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);
^
g++ 4.8.2 版没有抱怨这个,但g++ 6.3.0 有(这就是我现在担心的原因)。当存在实质性不匹配时,两个版本都会抱怨第一次打印,例如使用%f 或%s,或者如果我将Foo 更改为使用long 底层类型;这就是我启用-Wformat的原因。
我了解警告不是标准符合性问题,并且我知道如何更改我的代码来解决这些问题(例如,使用How can I output the value of an enum class in C++11? 的答案中的函数),但我也相信如果它们产生警告是无用的误报。当枚举的基础类型与格式字符串中的相应转换规范匹配时,将作用域枚举传递给格式化的 I/O 函数是否有任何潜在的实际危害?
【问题讨论】:
-
GCC 4.8 版可能没有抱怨,因为它没有完整的 C++11 实现,并且在 C++11 中引入了作用域枚举。
-
从您链接的问题中查看接受的答案:无范围枚举值是整数提升,但范围枚举(
enum class的)不是。 -
@cpplearner 即使我将
Bar更改为enum class : int,它也会抱怨不匹配,所以这只是答案的一部分。 -
@Toby 不,不是:
enum class表示没有隐式转换为int或基础类型或其他类型的新类型,这些转换仍然适用于普通enum。 -
@rubenvb,如果没有转换,那么这意味着只有在
va_arg()调用使用完全相同的类型时才能使用通过 varargs 传递的作用域 int?我想我现在明白了。感谢所有评论和回答的人!
标签: c++ enums gcc-warning enum-class