由于int()
和int{}
是等于的常量表达式0
,我认为它们是等效的并且可以互换,因此编译器必须同等对待它们。例如,
int a[0]; //error: zero-sized array not allowed in ISO C++
int b[int()]; //error: zero-sized array not allowed in ISO C++
int c[int{}]; //error: zero-sized array not allowed in ISO C++
但是似乎有些极端情况下它们是不可互换的。
初始化指针时:
int *p = 0; //ok
int *q = int(); //error - by clang only
int *r = int{}; //error - by gcc and clang both
请参阅GCC和Clang消息。我怀疑这是两个编译器中的错误,因为我希望它们在这种情况下可以互换,但是我很高兴被证明是错误的。:-)
传递给类模板时:
template<int N> struct X{};
X<0> x1; //ok
X<int{}> x2; //ok (same as X<0>)
X<int()> x3; //error
我发现语法X<int()>
非常熟悉,就像我之前看到(并可能使用过)类似的语法一样,例如在中std::function<int()>
,模板参数应该int()
是不带参数且返回的函数类型(而不是0
)int
。但是我想知道规范的这一部分说在这种情况下int()
应被视为函数类型,并不int{}
总是与之等效0
。
表达式int()
和和int{}
都是整数类型的常量表达式prvalue,其值为零,因此0
在需要整数类型的整数常量表达式prvalue且值为零的任何上下文中都可以与文字互换。
这两个表达式均满足5.19常量表达式[expr.const]中指定的常量表达式的要求。
关于X<int()>
,该标准指定int()
在这种情况下不会被解释为表达式:
14.3模板参数[temp.arg]
在模板参数中,类型ID和表达式之间的歧义被解析为类型ID,而不管对应的模板参数的形式如何。
关于指针转换:
4.10指针转换[conv.ptr]
空指针常量是整数类型的整型常量表达式(5.19)prvalue,其值为零或type的prvalue
std::nullptr_t
。
根据上面的段落,int()
和int{}
均为空指针常量表达式。尽管存在一个未完成的缺陷报告(903),这可能会导致本段的更改,这表明(非常次要)编译器错误:
CWG之间有一个强烈的共识,即仅文字0应该被视为空指针常量,而不是当前指定的任何任意零值常量表达式。
以下措词处理表达式的值int()
:
8.5初始化程序[dcl.init]
零初始化类型T的对象或引用意味着:
[省略的条款不适用]
—如果T是标量类型(3.9),则将对象设置为值0(零),将其作为整数常量表达式,转换为T
[...]
值初始化类型T的对象意味着:
—如果T是具有用户提供的构造函数(12.1)的(可能是cv限定的)类类型(第9条),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化格式错误) );
[省略的条款不适用]
—否则,该对象将被初始化为零。
一个其初始值设定项是一个空括号集合(即())的对象,应进行值初始化。
对于int{}
:
8.5.4列表初始化[dcl.init.list]
对象或类型T的引用的列表初始化定义如下:
—如果初始化列表中没有元素,并且T是具有默认构造函数的类类型,则该对象将被值初始化。
[省略的条款不适用]
—否则,如果初始化列表中没有元素,则该对象将被值初始化。
所有引用均来自C ++ Working Draft Standard N3337。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句