C++ 0,int()和int{}之间有什么区别?
由于C++ 0,int()和int{}之间有什么区别?,c++,gcc,clang,zero,compile-time-constant,C++,Gcc,Clang,Zero,Compile Time Constant,由于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()
和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
- 传递到类模板时:
template<int N> struct X{}; X<0> x1; //ok X<int{}> x2; //ok (same as X<0>) X<int()> x3; //error
请参阅和消息 我发现语法模板结构X{}; x1//好啊 x2//ok(与X相同) xx3//错误
非常熟悉,因为我以前见过(可能使用过)类似的语法,比如在X
中,模板参数std::function
应该是函数类型(而不是int()
),不带参数,返回0
。但是我想知道规范中的哪一部分,在这个上下文中说,int
将被视为函数类型,而不是等同于int()
,后者总是int{}
0
int()
和int{}
都是计算值为零的整数类型的常量表达式prvalue,因此在任何需要计算值为零的整数类型的整数常量表达式prvalue的上下文中都可以与文本0
互换
两个表达式均满足5.19常数表达式[expr.const]中规定的常数表达式要求
关于X
,本标准规定int()
在此上下文中不解释为表达式:
14.3模板参数[临时参数]
在模板参数中,类型id和表达式之间的歧义被解析为类型id,而与相应模板参数的形式无关
关于指针转换:
4.10指针转换[conv.ptr]
空指针常量是一个整数类型的整数常量表达式(5.19),其计算结果为零
或类型为std::nullptr\u t
的PR值
根据以上段落,int()
和int{}
都是空指针常量表达式。这指向了一个(非常小的)编译器错误,尽管有一个开放的缺陷报告()可能会导致本段的更改:
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++工作草案标准N33 37。这基本上是一个“GRIP标准”,对吧?我也喜欢。这是一个非常好的问题——我的印象是,标准并不明确(但我仍在研究它)。@SteveJessop你认为最令人烦恼的解析适用于这里的任何案例吗?我看不到它,除了
X
。即使如此,我认为编译器首先会找到X
,因此知道它不是在寻找类型。关于X
:14.3[temp.arg]“在模板参数中,类型id和表达式之间的歧义会被解析为类型id,而不管相应模板参数的形式如何。”@SteveJessop Yes。这一点在我看来也有问题。C++通常试图避免语义信息来驱动解析。在X
的情况下,语法上下文允许类型声明,因此除非标准要求编译器考虑语义信息(模板参数不是类型参数),否则它是类型声明(和另一个最麻烦的解析实例。有关prvalue的定义,请参见3.10[basic.lval]这个定义包括literal0
。然后CWG的观点发生了变化,因为之前已经提出了哪些整数表达式是有效的空指针常量的问题。当时我们明确允许NPC使用false
。但不是1-1
,因为这早于constepr
,因此我们没有办法ress什么是“const够了”。@MSalters博士903中还有一个补充说明:在波特兰(2012年10月)会议上,有人提出了担忧