void()和void {}之间有什么区别?

cat*_*dle 9 c++ c++11

基本上,我想知道为什么编译器拒绝ptr2声明:

int main() {
    // this one works
    decltype(void())* ptr1;

    // this one does not
    decltype(void{})* ptr2;
}
Run Code Online (Sandbox Code Playgroud)

如果您认为这是一个函数指针,请查看此代码ptr1:

#include <iostream>
using namespace std;

template <class T>
void f(T t) {
    cout << __PRETTY_FUNCTION__ << endl;
}

int main() {
    decltype(void())* ptr;
    f(ptr);
}
Run Code Online (Sandbox Code Playgroud)

输出是void f(T) [with T = void*].

dyp*_*dyp 11

[expr.type.conv]

2表达式T(),其中是非数组完整对象类型或(可能是cv -qualified)类型Tsimple-type-specifiertypename-specifier,它创建一个指定类型的prvalue,其值是由value产生的值 -初始化(8.5)类型的对象; 没有为该情况进行初始化.[...]voidTvoid()

NB void 一个简单类型说明符.

3同样地,一个简单型说明符类型名称说明符后跟一个支撑-INIT列表创建具有指定的指定类型的直接清单初始化(8.5.4)的一个临时对象支撑-INIT列表,并且其value是临时对象作为prvalue.

感谢Keith Thompson指出在/ 3中创建了一个临时对象,而在/ 2中创建了一个.

当我们看一下[basic.types]/5

未完全定义的对象类型和void类型是不完整类型(3.9.1).不应将对象定义为具有不完整类型.

现在很明显void{}不允许这样做,因为它会创建一个(临时)对象.void()但是"仅"会创建(pr)值.我不认为这两种情况的实现(行为)存在差异,但不同的语言规则适用于它们.其中一条规则禁止创建类型的对象void,因此错误.


广告decltype(void()):decltype(e)表达e.在[dcl.type.simple]/4中,适用的定义decltype(e)是:

否则,decltype(e)是的类型e

(因为void()产生一个prvalue而不是id-expression).

因此,decltype(void())收益率void.

  • `void {}`会创建一个类型为`void`的临时对象.没有类型为"void",临时或其他类型的对象. (3认同)