我不明白模板函数如何成为 [namespace.memdef]/3 in C++14 示例中 class A::X::Y 的友元
I don't understand how the template function gets to be a friend of the class A::X::Y in the example in [namespace.memdef]/3 in C++14
考虑 C++14 中 [namespace.memdef]/3 示例中的以下代码:
// Assume f and g have not yet been declared.
void h(int);
template <class T> void f2(T);
namespace A {
class X {
friend void f(X); // A::f(X) is a friend
class Y {
friend void g(); // A::g is a friend
friend void h(int); // A::h is a friend
// ::h not considered
friend void f2<>(int); // ::f2<>(int) is a friend
};
};
// A::f, A::g and A::h are not visible here
X x;
void g() { f(x); } // definition of A::g
void f(X) { /* ... */} // definition of A::f
void h(int) { /* ... */ } // definition of A::h
// A::f, A::g and A::h are visible here and known to be friends
}
using A::x;
void h() {
A::f(x);
//A::X::f(x); // error: f is not a member of A::X
//A::X::Y::g(); // error: g is not a member of A::X::Y
}
我不明白为什么 ::f2<>(int)
是 class A::X::Y
的朋友。名称的查找不应该在 namespace A
处停止吗?怎么允许找到::f2
?为什么h
和f2
的处理方式不同?
它不必在命名空间 A
中。我认为混淆可能来自 [namespace.memdef]/3:
这句话
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.
有问题的 friend
声明中的名称是 f2<>
。那是不合格的,但它是一个template-id。因此,限制查找命名空间 A
的子句根本不适用。我们对 f2
进行标准的非限定查找以查找 ::f2
。
考虑您在 h
和 f2
之间复制的示例中的差异:
friend void h(int); // A::h is a friend
// ::h not considered
friend void f2<>(int); // ::f2<>(int) is a friend
那里 h
既不是合格的也不是 template-id,所以我们不会在最里面的封闭命名空间之外查看。由于我们在那里找不到 h
的任何内容,因此我们应用 [namespace.memdef]/3 的第一句:
If a friend declaration in a non-local class first declares a class, function, class template or function template
the friend is a member of the innermost enclosing namespace.
因此该特定行声明了一个 void A::h(int)
,它是 A::X::Y
的 friend
。
考虑 C++14 中 [namespace.memdef]/3 示例中的以下代码:
// Assume f and g have not yet been declared.
void h(int);
template <class T> void f2(T);
namespace A {
class X {
friend void f(X); // A::f(X) is a friend
class Y {
friend void g(); // A::g is a friend
friend void h(int); // A::h is a friend
// ::h not considered
friend void f2<>(int); // ::f2<>(int) is a friend
};
};
// A::f, A::g and A::h are not visible here
X x;
void g() { f(x); } // definition of A::g
void f(X) { /* ... */} // definition of A::f
void h(int) { /* ... */ } // definition of A::h
// A::f, A::g and A::h are visible here and known to be friends
}
using A::x;
void h() {
A::f(x);
//A::X::f(x); // error: f is not a member of A::X
//A::X::Y::g(); // error: g is not a member of A::X::Y
}
我不明白为什么 ::f2<>(int)
是 class A::X::Y
的朋友。名称的查找不应该在 namespace A
处停止吗?怎么允许找到::f2
?为什么h
和f2
的处理方式不同?
它不必在命名空间 A
中。我认为混淆可能来自 [namespace.memdef]/3:
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.
有问题的 friend
声明中的名称是 f2<>
。那是不合格的,但它是一个template-id。因此,限制查找命名空间 A
的子句根本不适用。我们对 f2
进行标准的非限定查找以查找 ::f2
。
考虑您在 h
和 f2
之间复制的示例中的差异:
friend void h(int); // A::h is a friend
// ::h not considered
friend void f2<>(int); // ::f2<>(int) is a friend
那里 h
既不是合格的也不是 template-id,所以我们不会在最里面的封闭命名空间之外查看。由于我们在那里找不到 h
的任何内容,因此我们应用 [namespace.memdef]/3 的第一句:
If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace.
因此该特定行声明了一个 void A::h(int)
,它是 A::X::Y
的 friend
。