Если честно, с вашими образцами я вижу немного неправильного.
Тем не менее, существует ряд случаев, когда компилятор, похоже, допускает «нарушения» стандартных правил преобразования ...:
Списки инициализаторов (§ 8.5.4)
Однако я заметил это в стандарте:
Для списков инициализаторов следующее не разрешено (§ 8.5.4, в 3. )
int ai[] = { 1, 2.0 }; // error narrowing
Под 6. далее приводится общий список примеров:
[Примечание: как указано выше, такие преобразования не допускаются на верхнем уровне при инициализации списка. — конец
примечание]
int x = 999; // x is not a constant expression
const int y = 999;
const int z = 99;
char c1 = x; // OK, though it might narrow (in this case, it does narrow)
char c2{x}; // error: might narrow
char c3{y}; // error: narrows (assuming char is 8 bits)
char c4{z}; // OK: no narrowing needed
unsigned char uc1 = {5}; // OK: no narrowing needed
unsigned char uc2 = {-1}; // error: narrows
unsigned int ui1 = {-1}; // error: narrows
signed int si1 =
{ (unsigned int)-1 }; // error: narrows
int ii = {2.0}; // error: narrows
float f1 { x }; // error: might narrow
float f2 { 7 }; // OK: 7 can be exactly represented as a float
int f(int);
int a[] = { 2, f(2), f(2.0) }; // OK: the double-to-int conversion is not at the top level
Интересно, что g ++ 4.6.1 с --std=c++0x -Wall -pedantic
ловит только одно из этих нарушений:
char c3{y}; // warning: overflow in implicit constant conversion [-Woverflow]
Внешние списки инициализаторов ...
Я не думаю, что усечение числа с плавающей точкой до int считается narrowing
.
Это просто четкое преобразование, очень похожее на
int i = 31;
i /= 4; // well defined loss of precision...
i /= 4.0; // equally well-defined conversion from floating point to int