2017-02-08 5 views
0

При использовании перечисления с областью действия в контексте varargs он определяется как его базовый тип, как указано в «Can I use enum class values as arguments to varargs functions?». Как я понимаю, это единственное обстоятельство, в котором скопированное перечисление будет преобразовано неявно, например неперечисленное перечисление.Правильно ли GCC предупреждать о несоответствии строки формата с областью перечисления?

Рассмотрим эту программу:

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?), но я также считаю, что предупреждения бесполезны, если они производят ложные позитивы. Существует ли какой-либо потенциал для фактического вреда при передаче области с перечнем в форматированную функцию ввода-вывода, когда базовый тип перечисления соответствует соответствующей спецификации преобразования в строке формата?

+1

GCC версия 4.8, вероятно, не жаловалась, потому что у нее не было полной реализации C++ 11, а расширенные перечисления были введены в C++ 11. –

+4

См. Принятый ответ из связанного с вами вопроса: значения неперечисленного числа перечислены как целочисленные, но ограниченные перечисления (элементы класса enum) - нет. – cpplearner

+1

@cpplearner Даже если я изменю 'Bar' на' enum class: int', он жалуется на несоответствие, так что это только часть ответа. –

ответ

4

this scoped enumeration reference От:

Там нет нет неявных преобразований из значений контекстного перечислителя к интегральному типу, ...

[выделен мной]

Это означает, что независимо от базового типа, облачное перечисление не будет им законно преобразован в int (или любой другой целочисленный тип). Вы должны явно выполнить преобразование, например. static_cast (продолжение с предыдущей цитаты):

... хотя static_cast может быть использован для получения числового значения счетчику.


Кроме того, из this variadic argument reference:

bool, char, short и незаданных перечислений преобразуются в int или более широких целочисленных типов, как в целочисленном продвижении

[Снова курсив мой]


И ответить на ваш вопрос, если НКУ прямо в предупреждаю: Да, это правильно. То, что вы делаете, неверно.

Смежные вопросы