<分区>
下面的程序可以编译,我觉得很奇怪。
void f(class s);
using u = s; // ok, but why?
s
是函数参数列表中类的前向声明,在我看来它不应该在函数范围之外可见。
basic.scope.param似乎很明显我会找到这条规则,但我无法解决。措辞可能在 dcl.dcl 中的某处, 但我不确定去哪里找。
什么规则涵盖了这一点?可选地,解释为什么存在此规则会很好。
<分区>
下面的程序可以编译,我觉得很奇怪。
void f(class s);
using u = s; // ok, but why?
s
是函数参数列表中类的前向声明,在我看来它不应该在函数范围之外可见。
basic.scope.param似乎很明显我会找到这条规则,但我无法解决。措辞可能在 dcl.dcl 中的某处, 但我不确定去哪里找。
什么规则涵盖了这一点?可选地,解释为什么存在此规则会很好。
最佳答案
首先,这条规则并不是特别新。它几乎从 C++ 诞生之初就存在了。至于C++20,是这样写的:
[basic.scope.pdecl]
7 The point of declaration of a class first declared in an elaborated-type-specifier is as follows:
- ...
- for an elaborated-type-specifier of the form
if the elaborated-type-specifier is used in the decl-specifier-seq or parameter-declaration-clause of a function defined in namespace scope, the identifier is declared as a class-name in the namespace that contains the declaration; otherwise, except as a friend declaration, the identifier is declared in the smallest namespace or block scope that contains the declaration.class-key identifier
但你正在寻找最新的最伟大的草稿头。您找不到它是因为草案已将 P1787 合并进来。它更改了规范性措辞并将其移动,目的是解决一些突出的措辞问题并在存在模块的世界中改进标准的方法。
今天,相关部分驻留在
[dcl.type.elab]
3 Otherwise, an elaborated-type-specifier E shall not have an attribute-specifier-seq. If E contains an identifier but no nested-name-specifier and (unqualified) lookup for the identifier finds nothing, E shall not be introduced by the enum keyword and declares the identifier as a class-name. The target scope of E is the nearest enclosing namespace or block scope.
本质上,它与 C++20 措辞的含义相同。它将类名引入到最近的封闭范围中,就像通过前向声明一样。
至于为什么会有这个规则。好吧......它在最新的C中不存在。这给外行人带来了一些相当模糊的问题。考虑这个简单的程序:
void func(struct foo*);
struct foo { int bar; };
int main() {
struct foo f;
func(&f);
}
void func(struct foo* pf) {
pf->bar = 0;
}
它产生一个 slew of diagnostics ,坦率地说这似乎不合理。恕我直言,这是 C 的一个缺点,这反过来又足以让 C++ 以它的方式做事。使用 C++ 编译器编译完全相同的程序,它是 well formed。
关于c++ - 在函数参数列表中向前声明的类型如何在函数范围外可见?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67944631/