我不明白模板函数如何在 C++14 的 [namespace.memdef]/3 的示例中成为类 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

本文关键字:朋友 memdef 函数 明白 namespace C++14      更新时间:2023-10-16

考虑C++14中[namespace.membedef]/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)A::X::Y班的朋友。名称的查找不应该停止在namespace A吗?如何查找::f2?为什么hf2的治疗有差异?

它不必在命名空间A中。我认为混淆可能来自于[名称空间.内存定义]/3:中的这句话

如果friend声明中的名称两者都不是限定也不是模板id,并且声明是函数或详细说明的类型说明符时,确定实体是否先前已声明的查找不应考虑最内部之外的任何范围封闭命名空间。

所讨论的friend声明中的名称是f2<>。这是不合格的,但它模板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既不是限定的,也不是模板id,所以我们不查看最里面的封闭命名空间之外的内容。由于我们在那里找不到h的任何内容,所以我们应用了[名称空间.内存定义]/3:的第一句话

如果非本地类中的友元声明首先声明了类、函数、类模板或函数模板朋友是最里面的封闭命名空间的成员。

因此,该特定行声明了一个void A::h(int),它是A::X::Yfriend