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?