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);
}
コンパイラ (g++
バージョン 6.3.0) は、 a の最初の出力に満足していますが、 aFoo
を渡すと不平を言い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
orを使用するなどの実質的な不一致がある場合、または基になる型を使用する%s
ように変更した場合、両方のバージョンが最初の印刷について文句を言います。それが私が有効にする理由です。Foo
long
-Wformat
警告は標準準拠の問題ではないことを理解しており、これらに対処するためにコードを変更する方法を知っています (たとえば、How can I output the value of an enum class in C++11?への回答で関数を使用します)。また、誤検知が発生する場合、警告は役に立たないと思います。列挙型の基になる型がフォーマット文字列の対応する変換仕様と一致する場合、スコープ付き列挙型をフォーマットされた I/O 関数に渡すと、実際に害が及ぶ可能性はありますか?