When using a scoped enum in a varargs context, it is defined to be passed as its underlying type, as answered in "Can I use enum class values as arguments to varargs functions?" As I understand it, this is the only circumstance in which a scoped enum will be converted implicitly, like an unscoped enum is.
Consider this program:
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);
}
The compiler (g++
version 6.3.0) is happy with the first print, of a Foo
, but complains when I pass 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++
version 4.8.2 didn't complain about this, but g++
6.3.0 does (and that's why it now concerns me). Both versions complain about the first print when there is a substantive mismatch, such as using %f
or %s
, or if I change Foo
to use a long
underlying type; that's why I enable -Wformat
.
I understand that warnings are not a standards-conformance issue, and I know how to change my code to address these (e.g. using the functions in answers to How can I output the value of an enum class in C++11?), but I also believe that warnings are unhelpful if they produce false positives. Is there any potential for actual harm in passing a scoped enum to a formatted I/O function when the underlying type of the enum matches the corresponding conversion specification in the format string?
From this scoped enumeration reference:
There are no implicit conversions from the values of a scoped enumerator to integral types, ...
[Emphasis mine]
That means no matter the base type, a scoped enumeration will not be implicitly converted to an int
(or any other integer type). You must explicitly do the conversion, with e.g. static_cast
(continued from previous quote):
... although
static_cast
may be used to obtain the numeric value of the enumerator.
Also, from this variadic argument reference:
bool
,char
,short
, and unscoped enumerations are converted toint
or wider integer types as in integer promotion
[Again emphasis mine]
And to answer your question if GCC is right in warning you: Yes it is right. What you're doing is not correct.