我不明白模板函数如何在C++ 14的[namespace.memdef]/3中的示例中成为类A :: X :: Y的朋友

Leo*_*eon 2 c++ templates friend language-lawyer 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
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么::f2<>(int)是班上的朋友A::X::Y.不应该查找名称停止namespace A?如何才能找到::f2?为什么会出现在治疗的差异hf2

Bar*_*rry 6

它不必在命名空间中A.我认为混淆可能来自[namespace.memdef]/3中的这句话:

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

有关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
Run Code Online (Sandbox Code Playgroud)

h是没有资格也没有一个模板id,所以我们不看最内层的命名空间之外.由于我们没有找到任何东西h,我们应用[namespace.memdef]/3的第一句话:

如果非本地类中的友元声明首先声明了类,函数,类模板或函数模板,则该友元是最内层封闭命名空间的成员.

使特定的行声明了一个void A::h(int),这是一个friendA::X::Y.