Подтвердить что ты не робот

Сужение преобразования от беззнакового до двойного

static_assert(sizeof(unsigned) == 4, ":(");
static_assert(sizeof(double) == 8 ,":(");
unsigned u{42};
double x{u};

g++ 4.7.1 жалуется на этот код:

warning: narrowing conversion of 'u' from 'unsigned int' to 'double' inside { }

Почему это сужение? Разве не все unsigned прекрасно представлены как double?

4b9b3361

Ответ 1

Почему это сужение?

Поскольку определение включает (с моим упором):

С++ 11 8.5.4/7 Сужение преобразования - это неявное преобразование [...] из целочисленного типа [...] в тип с плавающей запятой, , за исключением случаев, когда источник является постоянным выражением, а фактическое значение после преобразования будет соответствовать целевому типу и будет выведите исходное значение при преобразовании обратно в исходный тип.

u не является постоянным выражением, поэтому оно сужает преобразование того, могут ли быть представлены все возможные значения типа источника в целевом типе.

Разве не все unsigned прекрасно представлены как double?

Эта реализация определена. В общем случае 32-разрядных unsigned и double с 52-битной мантиссой это так; но некоторые реализации имеют более крупные unsigned и/или меньшие double представления, поэтому код, который зависит от этого предположения, не переносится.

Ответ 2

Предупреждение, которое у вас есть, потому что вы инициализируете x с непостоянным выражением

Ilyas-iMac:TestC++11 sandye51$ cat main.cpp                   
int main()
{
    static_assert(sizeof(unsigned) == 4, ":(");
    static_assert(sizeof(double) == 8 ,":(");
    constexpr unsigned u{42};
    double x{u};

    return 0;
}Ilyas-iMac:TestC++11 sandye51$ gcc -o main main.cpp -std=c++11
Ilyas-iMac:TestC++11 sandye51$ 

Как вы можете видеть, код выше работает без каких-либо предупреждений или ошибок

Ответ 3

(Попробуйте:) double имеет ровно 52 бита значащих (двоичных) цифр (в соответствии с стандартом ieee), тогда как unsigned int может иметь хорошие 64 бита в некоторой другой системе. Таким образом, фактическая ширина unsigned int в вашей системе может не иметь значения для этой проверки.