С использованием {}
инициализатор в C++11
инициализировать bool b = {2}
выдает следующее предупреждающее сообщение:
warning: narrowing conversion of ‘2’ from ‘int’ to ‘bool’ inside { } [-Wnarrowing]
Однако, используя старый стиль bool b = 2
не имеет такой проблемы. В чем причина этого?
Обновление: я скомпилировал код, используя g++ -std=c++11
и это дало мне предупреждение. Если я добавлю опцию -pedantic-errors
предупреждение становится ошибкой.
Сужение типа данных в списке инициализации делает вашу программу на С ++ 11 плохо сформированной, в этой ситуации компилятор может либо выдавать предупреждение, либо продолжать работу.
Интересно, что вы можете изменить его на bool b = {1}
и я не предполагаю предупреждения, потому что значение bool гарантированно преобразуется в 0 и 1 в целочисленных типах.
Вот стандартная цитата, подтверждающая ошибку.
Сужающее преобразование — это неявное преобразование
— от типа с плавающей точкой к целочисленному типу, или
— от long double до double или float, или от double до float, за исключением случаев, когда источником является постоянное выражение, а фактическое значение после преобразования находится в диапазоне значений, которые могут быть представлены (даже если они не могут быть представлены точно), или
— от целочисленного типа или перечислимого типа с незаданной областью до типа с плавающей запятой, за исключением случаев, когда источником является константное выражение, а фактическое значение после преобразования будет соответствовать целевому типу и будет выдавать исходное значение при преобразовании обратно в исходный тип, или же
— от целочисленного типа или типа перечисления с незаданной областью до целочисленного типа, который не может представлять все значения исходного типа, за исключением случаев, когда источником является константное выражение, а фактическое значение после преобразования будет соответствовать целевому типу и будет создавать исходное значение при преобразовании обратно в исходный тип.
Как указано выше, такие преобразования не допускаются на верхнем уровне при инициализации списка.
Это выглядит как:
bool b = {2} ;
действительно сужение конверсии если мы посмотрим на проект стандарта C ++ раздел 8.5.4
Список инициализация параграф 7 говорит:
Сужающее преобразование — это неявное преобразование
и включите следующую пулю (акцент мой):
из целочисленного типа или типа перечисления с незаданной областью к целочисленному типу
который не может представлять все значения исходного типа, Кроме
где источник является константным выражением, значение которого после интеграла
рекламные акции будут соответствовать целевому типу.
bool
не может представлять ценность 2
так что это сужающееся преобразование в самом строгом смысле. Что имеет смысл весь смысл {}
инициализация должна предотвратить неявные преобразования и увеличить тип безопасности. Который Старый стиль на что вы ссылаетесь здесь, опирается на:
bool b = 2
который зависит от раздела 4.12
Булевы преобразования который говорит:
[…] Нулевое значение, нулевое значение указателя или нулевое значение указателя члена
конвертируется в ложь; любое другое значение преобразуется в true. […]
Конечно, вся предпосылка, что {2}
будет сужение конверсии опирается на предположение, что значение правда а также ложный является 1
а также 0
, что, насколько я могу судить, не гарантируется в стандарте. Хотя это подразумевается единственное, что стандарт обещает в преобразования но если мы собираемся использовать буквальный нам не нужно полагаться на это предположение, у нас есть два совершенно хороших логические литералы за это true
а также false
это то, что вы должны использовать.
Для полноты картины это сужение конверсии является плохо формируется, это требует диагностики, так что либо предупреждение или ошибка приемлемо если мы посмотрим на абзац 3, это говорит:
Инициализация списка объекта или ссылки типа T определяется как
следующим образом:
и включите следующую пулю (акцент мой):
В противном случае, если список инициализатора имеет единственный элемент типа E и либо T не является ссылочным типом, либо его ссылочный тип связан со ссылкой на E, объект или ссылка инициализируются из этого элемента; если для преобразования элемента в T требуется сужающее преобразование (см. ниже), программа является некорректной.
и включает в себя следующий пример:
[ Example:
int x1 {2}; // OK
int x2 {2.0}; // error: narrowing
—end example ]