0,int()和int {}之间有什么区别?

时间:2013-10-01 16:59:28

标签: 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 *p = 0;     //ok
    int *q = int(); //error - by clang only
    int *r = int{}; //error - by gcc and clang both
    

    查看GCCClang条消息。我怀疑这是两个编译器中的错误,因为我希望它们在这种情况下可以互换,但我很高兴被证明是错误的。 : - )

  • 传递给课程模板时:

    template<int N> struct X{};
    
    X<0>      x1; //ok
    X<int{}>  x2; //ok (same as X<0>)
    X<int()>  x3; //error  
    

    查看GCCClang条消息。

    我发现语法X<int()>非常熟悉,就像我之前看到的(并且可能已经使用过)类似的语法,例如在std::function<int()>中,模板参数int()应该是函数类型(而不是0)不带参数并返回int。但我想知道规范的一部分,在此上下文中int()将被视为函数 type ,并且不等同于int{},它总是{{1} }}

1 个答案:

答案 0 :(得分:5)

表达式int()int{}都是整数类型的常量表达式prvalues,它们的计算结果为零,因此可以在需要整数常量表达式的任何上下文中与文字0互换整数类型的prvalue,其值为零。

两个表达式都满足 5.19 Constant Expressions [expr.const] 中指定的常量表达式的要求。

关于X<int()>,该标准指定int()在此上下文中不被解释为表达式:

  

14.3模板参数[temp.arg]

     

template-argument 中, type-id 表达式之间的歧义被解析为 type-id ,无论相应的模板参数的形式如何。

关于指针转换:

  

4.10指针转换[conv.ptr]

     

空指针常量是整数类型的整数常量表达式(5.19)prvalue,其值为零   或std::nullptr_t类型的prvalue。

基于上面的段落,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 ++工作草案标准N3337。