这是this问题的后续。
在评论和答案中不止一次地说
void{}
既不是有效的类型 ID,也不是有效的表达式。
很好,很有道理,仅此而已。
然后我浏览了工作草案的[7.1.7.4.1/2](占位符类型推导)。
据说:
[...]
- 对于使用包含占位符类型的返回类型声明的函数中出现的非丢弃语句,return
是声明的返回类型,T
是e
语句的操作数。如果return
语句没有操作数,则return
是e
;void{}
[...]
那么,
void{}
(概念上)合法吗?decltype(void{})
也应该有效。void()
而不是void{}
?
嗯,说实话,我很确定我没有足够的能力指出工作草案中的错误,所以真正的问题是:我的推理有什么问题?
上面的项目符号中提到的
void{}
到底是什么以及为什么它在本例中是合法的表达方式?
对我来说,这听起来像是有人把以前的标准与新标准合并在一起。
之前标准是这么说的:(C++14 N4140, 7.1.6.4.7 [dcl.spec.auto]):
当函数中出现 [...]
语句时 使用包含占位符类型、推导的返回类型或变量类型的返回类型进行声明 由其初始值设定项的类型确定。在return
没有操作数的情况下,初始化器是 被认为是return
。void()
新标准允许使用
if constexpr
语句,因此需要更改语言以反映这一点。 if constexpr
引出了潜在的 discarded return
语句的概念(如果 return
位于 constexpr if 的 not-taken 分支中,那么它将被丢弃,并且从其他 return 语句推断出返回类型,if任何)。
新的措辞可能应该是这样的:
对于函数中出现的未丢弃的 return 语句 使用包含占位符类型的返回类型声明,
是 声明的返回类型,T
是e
语句的操作数。如果 return 语句没有操作数,则return
为T
,推导出的返回类型为auto
void
在现代 C++ 中,
void()
和 void{}
之间没有区别。两者都是合法的。
[expr.type.conv] p2 中的当前措辞指出:
否则,如果类型为 cv
并且初始化器为void
或()
(包扩展后,如果有),则表达式是{}
类型的纯右值,不执行初始化。void
历史上,曾经存在差异,但 CWG 第 2351 期
void{}
已使 void{}
作为缺陷报告有效,这意味着它追溯适用于 C++11 和更新的标准。