基本上,我想知道为什么编译器会拒绝ptr2
声明:
int main() {
// this one works
decltype(void())* ptr1;
// this one does not
decltype(void{})* ptr2;
}
如果您认为ptr1
是函数指针,请查看this code:
#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*]
。
答案 0 :(得分:11)
[expr.type.conv]
2表达式{{1}},其中
T()
是简单类型说明符或 typename-specifier ,用于非数组完整对象type或(可能是 cv -qualified)T
类型,创建一个指定类型的prvalue,其值是value-initializing(8.5)类型为{{1}的对象生成的值}};没有为void
情况进行初始化。 [...]
N.B。 T
简单类型说明符。
3同样,简单类型说明符或 typename-specifier 后跟 braced-init-list 会创建一个临时对象指定的类型direct-list-initialized(8.5.4)与指定的 braced-init-list ,其值是临时对象作为prvalue。
感谢Keith Thompson指出在/ 3中创建了临时对象,而在/ 2中创建了值。
当我们看一下[basic.types] / 5
未完全定义的对象类型和
void()
类型是不完整类型(3.9.1)。对象不应被定义为具有不完整的类型。
现在很清楚,void
是不允许的,因为它会创建一个(临时)对象。 void
但是“仅”会创建(pr)值。我不认为这两种情况的实现(行为)存在差异,但不同的语言规则适用于它们。其中一条规则禁止创建void{}
类型的对象,因此错误。
广告void()
:void
采用表达式decltype(void())
。在[dcl.type.simple] / 4中,decltype(e)
的适用定义是:
否则,
的类型e
是decltype(e)
(因为decltype(e)
产生一个prvalue而不是 id-expression )。
因此,e
会产生void()
。