4

§ 8.5.4/7 中的标准解释了缩小转换是什么:

缩小转换是隐式转换

— 从浮点类型到整数类型,或

— 从 long double 到 double 或 float,或从 double 到 float,除非源是常量表达式并且转换后的实际值在可以表示的值范围内(即使不能精确表示),或

— 从整数类型或无作用域枚举类型到浮点类型,除非源是常量表达式并且转换后的实际值将适合目标类型并且在转换回原始类型时将产生原始值,或者

— 从整数类型或无作用域枚举类型到不能表示原始类型的所有值的整数类型,除非源是常量表达式并且转换后的实际值将适合目标类型并生成原始值当转换回原始类型时。

然后它在某些列表初始化上下文中禁止此类转换,并给出示例:

[注意:如上所述,列表初始化中的顶级不允许此类转换。— 尾注] [ 示例:

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

—结束示例]

示例说明的所有 7 个错误都是由 clang 3.2/3.3 报告的-std=c++11,例如

error: non-constant-expression cannot be narrowed from type 'int' to 'char' in initializer list [-Wc++11-narrowing]

gcc 4.7.2/4.8.1 没有将它们报告为错误,但在每种情况下都会给出类似的警告,例如

warning: narrowing conversion of ‘x’ from ‘int’ to ‘char’ inside { } [-Wnarrowing]

(所以 gcc 似乎知道合规性要求,但默认选择容忍不合规性。)

我不明白的是这个例子如何:

unsigned int ui1 = {-1};    // error: narrows

有资格作为一个例子。(对称的si1例子也是如此。)显然,唯一可以作为例子的词是上面给出的缩小转换定义中的第四项也是最后一项。但是如果是这样,那么除了源是常量表达式并且转换后的实际值将适合目标类型并且在转换回原始类型时会产生原始值之外,为什么示例不会通过限定符转义 ?肯定-1有一个整数常量,如果unsigned来回转换,仍然会产生int -1?

我错过了什么?

4

1 回答 1

6

当然 -1 有一个整数常量,如果转换为无符号并返回,仍然会产生 int -1?

这是错误的。如果你将 -1 转换为unsigned你得到UINT_MAX. 这很好,因为总是定义转换为无符号类型。但是,仅当值适合目标类型时,标准才定义UINT_MAX不适合int并且转换为有符号类型。

于 2013-07-09T15:01:57.933 回答