我不明白模板函数如何成为 [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?为什么hf2的处理方式不同?

它不必在命名空间 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

考虑您在 hf2 之间复制的示例中的差异:

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::Yfriend