问题 为什么列表初始化允许从double转换为float值?


列表初始化( {...} 语法)不允许缩小转换。例如,尝试列表初始化 int i 同 3.14f 保存编译错误,因为从浮点值到整数的转换正在缩小:

<source>:11:32: error: narrowing conversion of '3.1400001e+0f' from 'float' to 'int' inside { } [-Wnarrowing]
     int i{3.14f};
                ^

话虽如此,为什么有可能构建一个 float f 同 3.14,这是类型 double? (转换自 double 至 float 被认为是缩小的。)执行以下操作:

float f{3.14};

不保留编译错误。


5705
2018-01-07 20:20


起源

你确定允许从double到float的转换吗? extern double y; struct X { float f; } x{y}; 给我带来的错误。 - Fanael


答案:


在被视为缩小转换的列表中,适合目标类型的常量表达式是一个例外。因此,虽然通常double to float正在缩小,但当你的double实际上是一个文字时,这是允许的。

http://coliru.stacked-crooked.com/a/6949f04fa4a8df17


从我手边的草稿(我认为接近C ++ 14):

8.5.4列表初始化
  (7.2)缩小转换是隐式转换......
  ...从long double到double或float,或从double到float,除非source是常量   表达式和转换后的实际值在可以表示的值范围内   (即使它无法准确表示),


13
2018-01-07 20:24



使用int值初始化char时也是如此。 - Sid S
@MárioFeroldi:它 是 被认为是一个常数表达:) pi然而,事实并非如此。 - GManNickG
@MárioFeroldi稍微澄清了这个例子。 - GManNickG
哇,所以失去精确度 是 允许。 3.14是无限二进制分数,所以 (float) 3.14 != 3.14。 - Arne Vogel
@ArneVogel:是的。您可以想象,对于不适合其目标的浮点值存在单独的转换错误 - 如果存在这样的事情,那么这个缩小转换规则可能只是简单地引用该规则。但是,这个规则并不存在,实际上大多数开发人员实际上并不关心他们的文字是否完全代表;我相信这是该规则例外的动机。 - GManNickG