C++ 我不知道';我不理解模板函数如何成为C+中[namespace.memdef]/3中示例中类a::X::Y的朋友+;14

C++ 我不知道';我不理解模板函数如何成为C+中[namespace.memdef]/3中示例中类a::X::Y的朋友+;14,c++,templates,language-lawyer,c++14,friend,C++,Templates,Language Lawyer,C++14,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 {

考虑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
}
//假设f和g尚未声明。
空h(int);
模板空隙f2(T);
名称空间A{
X类{
朋友void f(X);//A::f(X)是朋友
Y类{
朋友void g();//A::g是朋友
friend void h(int);//A::h是朋友
//::h未考虑
朋友空f2(int);/::f2(int)是朋友
};
};
//A::f、A::g和A::h在此处不可见
X;
void g(){f(x);}//A::g的定义
void f(X){/*…*/}//A::f的定义
void h(int){/*…*/}//A::h的定义
//A::f、A::g和A::h在这里可见,并且被认为是朋友
}
使用A::x;
void h(){
A::f(x);
//A::X::f(X);//错误:f不是A::X的成员
//A::X::Y::g();//错误:g不是A::X::Y的成员
}

我不明白为什么
::f2(int)
a::X::Y
这个班的朋友。名称的查找不应该停止在
名称空间A
?如何允许查找
::f2
?为什么对
h
f2
的处理有差异?

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

如果
friend
声明中的名称既不是 “合格”或“模板ID”和“声明”是一个函数或详细类型说明符,查找该实体是否已被声明之前的查找不应考虑最外面的任何范围。 封闭命名空间

所讨论的
friend
声明中的名称是
f2
。这不是限定的,但它是一个模板id。因此,将查找限制为namespace
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
friend void h(int);//h是一个朋友
//::h未考虑
友元无效f2(int);/::f2(int)是一个朋友
这里的
h
既不是限定的,也不是模板id,因此我们不会查看最里面的封闭名称空间。因为我们在那里找不到
h
的任何内容,所以我们应用了[namespace.memdef]/3的第一句话:

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


因此,这一行声明了一个
void a::h(int)
,它是
a::X::Y的
朋友

模板id不遵循这一段中的一般规则有什么特别的原因吗?@LeonTrotski我不知道。所以我。