универсальная и равномерная инициализация: от `double` до `int`

Visual Studio 2015, обновление 3. С++ 11\С++ 14.

Для int:

constexpr int ci1 {50};
constexpr int ci2 {500};

char c1 {ci1}; // OK
char c2 {ci2}; // compilation error

т.е. универсальная и равномерная инициализация может проверять значение в режиме компиляции (от int до char). Этот случай был упомянут Бьерном Страуструпом в его книге.

Я ожидал, что это верно для случая double to int, но это не работает для Visual Studio 2015 Update 3:

constexpr double cd {4.0};
int i1 {cd}; // compilation error

Сообщение об ошибке:

Преобразование C2397 из double в int требует сужающего преобразования.

Это правильное поведение (для моего второго примера кода) или, может быть, оно специфично для Visual Studio?


person Andrey Bushman    schedule 30.07.2016    source источник
comment
Пожалуйста, укажите ошибку компиляции в своем сообщении.   -  person Richard Critten    schedule 30.07.2016
comment
Плавающее число безоговорочно сужается, независимо от исходного значения. См. [dcl.init.list]/7.   -  person T.C.    schedule 30.07.2016
comment
Я добавил сообщение об ошибке.   -  person Andrey Bushman    schedule 30.07.2016
comment
@Т.С. Но почему? Для подобных примеров преобразование происходит без искажения исходного значения. Чем эта ситуация отличается от моего первого варианта кода?   -  person Andrey Bushman    schedule 30.07.2016


Ответы (2)


Преобразование из double в int сужает число, потому что double представляют собой рациональные числа. (0.5) Поскольку это не обязательно точно (1. может быть 1.000000001), преобразование приведет к потере информации.

Используйте явные приведения для таких преобразований, и все будет хорошо, или не используйте универсальную инициализацию.

person jonas_toth    schedule 30.07.2016

Преобразование double в int всегда считается сужением, поэтому Бьерн Страуструп создает в своей книге реализацию narrow_cast<> для такого приведения.

person DeepCoder    schedule 30.07.2016
comment
Но почему? Для подобных примеров преобразование происходит без искажения исходного значения. Чем эта ситуация отличается от моего первого варианта кода? - person Andrey Bushman; 30.07.2016
comment
@ Андрей Я считаю, что в некоторых реализациях теоретически это может включать искажение, поскольку стандарт AFAIK не требует, чтобы целые значения были точно представлены двойным - person Revolver_Ocelot; 30.07.2016