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

What's the difference between void() and void{}?

本文关键字:void 什么 区别      更新时间:2023-10-16

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

int main() {
    // this one works
    decltype(void())* ptr1;
    // this one does not
    decltype(void{})* ptr2;
}

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

#include <iostream>
using namespace std;
template <class T>
void f(T t) {
    cout << __PRETTY_FUNCTION__ << endl;
}
int main() {
    decltype(void())* ptr;
    f(ptr);
}

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

[expr.type.conv]

2 表达式 T() ,其中 T 是非数组完整对象类型或(可能符合 cv 的(void类型的简单类型说明符或类型名说明符,创建指定类型的 prvalue,其值是通过值初始化 (8.5( 生成的类型 T 的对象;对于void()情况不进行初始化。[...]

:注: void一个简单的类型说明符

3 类似地,简单类型说明符或类型名说明符后跟大括号的初始化列表使用指定的大括号初始化列表创建指定类型的直接列表初始化 (8.5.4( 的临时对象,其值是作为 prvalue 的临时对象。

感谢 Keith Thompson 指出临时对象是在/3 中创建的,而值是在/2 中创建的

当我们看一下[基本类型]/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 表达式(。

因此,decltype(void())产生void.