【发布时间】:2015-09-29 15:47:10
【问题描述】:
根据clang、gcc 和vs2013,函数Outer::f不是类Outer::Inner的朋友。
struct Outer {
void f() {}
class Inner {
friend void f();
static const int i = 0;
};
};
void f() { int i = Outer::Inner::i; }
从 [namespace.memdef]/3 我希望函数 Outer::f 成为 Outer::Inner 的朋友,而不是 ::f,因为朋友声明不是 first它的命名空间包含名称 f。
[namespace,memdef]/3(重点是我的):
在命名空间中首先声明的每个名称都是该命名空间的成员 命名空间。如果非本地类中的朋友声明first 声明一个类、函数、类模板或函数 模板97好友是innermost的成员 封闭的命名空间。朋友声明本身并不 对非限定查找 (3.4.1) 或限定查找可见的名称 (3.4.3)。 [注意:朋友的名字将在其 如果在命名空间范围内提供了匹配的声明,则命名空间 (在授予友谊的类定义之前或之后)。 — end note ] 如果调用友元函数或函数模板,其 名称可以通过考虑函数的名称查找找到 与函数类型相关的命名空间和类 论据(3.4.2)。如果朋友声明中的名字既不是 限定也不是模板ID,并且声明是函数或 详细类型说明符,查找以确定实体是否 已事先声明不得考虑任何范围之外的 最里面的封闭命名空间。
【问题讨论】:
-
引用的文字说“......确定实体是否先前已声明的查找不应考虑任何范围外部最里面的封闭命名空间”。这里的问题是“外部”应该是什么意思?它是否应该与“except”或“besides”同义(在这种情况下,上面的段落意味着查找是在最里面的命名空间中执行的并且没有其他地方)?但在这种情况下,如果我没记错的话,它应该说“outside of”......或者“outside”应该指的是围绕最里面的更大的包络命名空间?
-
在后一种情况下,“外部”不会从查找中消除
struct Outer。 -
我假设查找是在最里面的命名空间中执行的,而不是其他任何地方,对于句子中明确说明的情况:
If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.,在这种情况下,最里面的封闭命名空间是全局命名空间。 -
你为什么会得出这个结论?我在标准文本中没有看到任何明确的支持。这段话唯一说的是
[namespace.memdef]/3friend void h(int);声明中的示例中说明的内容。它说A::h is a friend, ::h not considered。引用的段落解释了为什么不考虑::h:因为::h是在::范围outside 的A范围内声明的。在您的示例中,struct Outer范围不在::范围之外。 -
对我来说很清楚。标准示例中最里面的命名空间是命名空间
A,而在上面的示例中,最里面的命名空间是全局命名空间。正如您所说,Outer范围不在全局范围之外。因此,在朋友声明中开始的查找会找到名称Outer::f,然后它应该是结识的函数,而不是::f。
标签: c++ language-lawyer c++14 friend