我们在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 }; }
T
,U
和V
的声明性区域是模板声明 分别为#1
,#2
和#3
行。但名称A
,f
,g
和C
都是 属于同一个声明区域 - 即 namespace-bodyN
。
我不清楚为什么N
的身体是g
和C
的声明性区域。我以为是B
级的身体
有人可以澄清标准的含义吗?
答案 0 :(得分:4)
C
首先在g
中声明,因此[basic.scope.pdecl] /(7.2)适用
表格
的详细类型说明符类键 标识符
如果在 decl-specifier-seq 中使用 elaborated-type-specifier 或 在命名空间作用域中定义的函数的 parameter-declaration-clause ,[...]; 否则,除了作为朋友声明之外,标识符在包含声明的最小名称空间或块范围中声明。
(“否则......”部分仅适用于friend class C;
形式的声明;它使用“as”而不是“inside”)
因此,当C
被声明为N
的成员时,显然它的声明区域是N
的正文。事实上,你是can use C
outside B
。
g
根据[namespace.memdef] / 3
N
的成员
如果非本地类中的朋友声明首先声明[..] 功能模板朋友是最里面封闭的成员 命名空间。强>
因此g
的声明性区域也是N
的身体。
答案 1 :(得分:2)
由于g
是友方函数,因此其范围是命名空间范围,根据11.3
朋友部分:
如果和,可以在类的朋友声明中定义函数 只有当类是非本地类(9.8)时,函数名才是 不合格,并且该函数具有命名空间范围。 [例如:
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
部分的功能模板:
如果非本地类中的朋友声明首先声明一个类, 功能,类模板或功能模板 97 的朋友 是最里面的封闭命名空间的成员。[...]
和C
这将在3.3.2
声明部分
首先在一个声明中声明一个类的声明 elaborated-type-specifier如下:
并包含以下项目符号(强调我的):
表示
形式的详细类型说明符类密钥标识符
如果在decl-specifier-seq或中使用了elaborated-type-specifier 在命名空间作用域中定义的函数的parameter-declaration-clause, 标识符在名称空间中声明为类名 包含声明;