C++ 14中的§5.19/ 3定义了一个整型常量表达式和一个转换后的常量表达式:
一个积分常量表达式是整体的或无作用域枚举类型的表达式,隐式转换为prvalue,其中所述转换后的表达式是一个核心常量表达式.[注意:这些表达式可以用作数组边界(8.3.4,5.3.4),比特字段长度(9.6),如果基础类型不固定(7.2),则作为枚举器初始化器,以及作为比对(7.6). 2).-end note] 转换后的常量类型表达式
T
是一个表达式,隐式转换为类型的prvalueT
,其中转换后的表达式是核心常量表达式,隐式转换序列仅包含用户定义的转换,左值到右值转换( 4.1),积分促销(4.5)和积分转换(4.7),而不是缩小转换(8.5.4).[注意:这些表达式可以在new
表达式(5.3.4)中使用,如case
表达式(6.4.2),如果基础类型是固定的(7.2),作为枚举器初始化器,作为数组边界(8.3.4),以及作为整数或枚举非类型模板参数(14.3). - 尾注]
也许我错过了一些东西,但我的第一印象是每个积分常量表达式都是转换后的常量表达式.
编辑
而且我也相信这一段中有错误:
代替:
A converted constant expression of type T is an expression, implicitly converted to a prvalue of type T, ...
它应该是:
A converted constant expression of type T is an expression, implicitly converted to a prvalue of an integral type, ...
此更改允许以下代码进行编译:
#includestruct A { operator int() { return 5; } } a; int main() { int b[a]{ 0, 1, 2, 3, 4 }; std::cout << b[4] << '\n'; }
其中a
在声明int b[a]{ 0, 1, 2, 3, 4};
是一个转换后的常量表达式类型的A
,隐式转换为整数类型(的prvalue int
),其中所转换的表达式5
是一个核心常量表达式,并且隐式转换序列仅包含一个用户定义的转换.
这两个定义都是必需的,因为你可以用一个而不是另一个来做.不,并非每个整数常量表达式都是转换常量表达式.对于明显的示例,转换的常量表达式禁止缩小转换,但是整数常量表达式不会.
因此我不能这样做:
enum x : char { a = 1024 };
但是,如果枚举的初始化程序允许使用整数常量表达式而不是转换后的常量表达式,那么就是允许的.
作为维恩图,我会画出这样的情况:
因此,两者之间存在相当多的重叠(可能超过此图所暗示的),但每个都至少允许一些事情,而另一个则没有.我已经给出了每个方向上一个项目的示例,但没有尝试详尽地列出差异.
我并不完全相信用户定义的转换被禁止用于整数常量表达式(并且快速测试表明我现在使用的编译器允许它们).这会给我最初写这个答案的情况,这更像是这样的: