Сужающие преобразования при инициализации объектов универсальными инициализаторами
Почему при инициализации объекта обычным присваиванием не константного выражения, не наблюдается сужающее преобразование:
int n{ 5 };
double d1 = n; //ок
а если инициализировать универсальным инициализатором:
double d1{n};
//error: conversion from 'int' to 'double'
// requires a narrowing conversion
то тут компилятор выдает ошибку о сужающем преобразовании? Как на это влияет, если инициализатор n является константным выражением?:
constexpr int k{ 5 };
double d{ k }; //ok
Ответы (1 шт):
Это
int n{5};
double d1 = n; //copy-initialization
обычная инициализация копией (copy initialization). При необходимости преобразования из одного типа в другой применяются неявные преобразования, но никаких проверок того, что целевой тип сможет вместить преобразуемое значение не производится.
Это
int n{5};
double d1{n}; // list-initialization
list initialization. Такая форма инициализации запрещает сужающие преобразования (narrowing conversions).
К сужающим преобразованиям в частности относится преобразование целочисленного типа в тип с плавающей точкой, за исключением случая, когда преобразуемое выражение есть константное выражение, вместимое целевым типом, и обратное преобразование к исходному типу даёт первоначальное значение.
A narrowing conversion is an implicit conversion
...
from an integer type or unscoped enumeration type to a floating-point type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type
...
Итак, в первом варианте list-initialization мы наблюдаем преобразование неконстантного целочисленного выражения в тип с плавающей точкой. Такое преобразование считается сужающим.
Во втором варианте list-initialization мы наблюдаем преобразование константного целочисленного выражения в тип с плавающей точкой. Причём исходное значение представимо целевым типом, и обратное преобразование из целевого в исходный тип даёт первоначальное значение. Такое преобразование сужающим не считается.