函数参数的声明区域

Declarative region of a function parameter

我们有来自 N4296::3.3.9/2 [basic.scope.temp] 的以下示例:

namespace N {
    template<class T> struct A { };                 // #1
    template<class U> void f(U) { }                 // #2
    struct B 
    {
        template<class V> friend int g(struct C*);  // #3
    };
}

The declarative regions of T, U and V are the template-declarations on lines #1, #2 and #3, respectively. But the names A, f, g and C all belong to the same declarative region — namely, the namespace-body of N.

我不清楚为什么 Ns body 是 gC 的声明区域。我还以为是 class Bs body.
有人可以阐明标准的含义吗?

因为 g 是一个友元函数,它的范围是命名空间范围,根据 11.3 Friends:

A function can be defined in a friend declaration of a class if and only if the class is a non-local class (9.8), the function name is unqualified, and the function has namespace scope. [ Example:

class M {
friend void f() { } // definition of global f, a friend of M,
// not the definition of a member function
};

—end example ]

我们可以看到这也适用于 7.3.1.2 部分的函数模板:

If a friend declaration in a non-local class first declares a class, function, class template or function template97 the friend is a member of the innermost enclosing namespace.[...]

并且对于 C 这在 3.3.2 部分中有说明 声明点:

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

    class-key identifier

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;

C 首先在 g 中声明,因此 [basic.scope.pdecl]/(7.2) 适用

for an elaborated-type-specifier of the form

         class-key identifier

if the elaborated-type-specifier is used in the decl-specifier-seq or parameter-declaration-clause of a function defined in namespace scope, […]; otherwise, except as a friend declaration, the identifier is declared in the smallest namespace or block scope that contains the declaration.

("otherwise …" 部分仅适用于 friend class C; 形式的声明;它使用 "as" 而不是 "inside")
因此,当 C 被声明为 N 的成员时,显然它的声明区域是 N 的主体。事实上,你 can use C outside B.

并且 g 根据 [namespace.memdef]/3

N 的成员

If a friend declaration in a non-local class first declares a [..] function template the friend is a member of the innermost enclosing namespace.

因此 g 的声明区域也是 N 的主体。