繁体   English   中英

成员函数Outer :: f()不是类Outer :: Inner的朋友。 为什么?

[英]The member function Outer::f() is not a friend of class Outer::Inner. Why?

根据clang ,gcc和vs2013,函数Outer::f 不是 Outer::Inner类的朋友。

struct Outer {
    void f() {}
    class Inner {
        friend void f();
        static const int i = 0;
    };
};

void f() { int i = Outer::Inner::i; }

从[namespace.memdef] / 3我希望函数Outer::f成为Outer::Inner的朋友,而不是::f ,因为友元声明不是包含名称f的名称空间中的第一个

[namespace,memdef] / 3(重点是我的):

首先在名称空间中声明的每个名称都是该名称空间的成员。 如果非本地类中的朋友声明首先声明了类,函数,类模板或函数模板97,则该朋友是最内部封闭命名空间的成员。 友元声明本身不会使名称对非限定查找(3.4.1)或限定查找(3.4.3)可见。 [注意:如果在命名空间范围内提供匹配的声明(在授予友谊的类定义之前或之后),则朋友的名称将在其命名空间中可见。 - 结束注释]如果调用了友元函数或函数模板,则可以通过名称查找找到其名称,该名称查找考虑名称空间中的函数和与函数参数类型相关联的类(3.4.2)。 如果友元声明中的名称既不是限定语句也不是模板标识,并且声明是函数或详细类型说明符,则确定实体是否先前已声明的查找不应考虑最内层封闭命名空间之外的任何作用域。

你引用的标准的第一部分说(强调我的):

首先在名称空间中声明的每个名称都是该名称空间的成员。 如果非本地类中的友元声明首先声明一个类或函数, 那么友元类或函数是最内层封闭命名空间的成员。

您假设某个类与命名空间相同,这是不正确的。

namespace Outer {
    void f();
    class Inner {
        friend void f();
        static const int i = 0;
    };
}

void Outer::f() { int i = Outer::Inner::i; }

应该管用。 要使用类成员函数作为朋友,您必须使用:

struct Outer {
    void f();
    class Inner {
        friend void Outer::f();
        static const int i = 0;
    };
};

void Outer::f() { int i = Outer::Inner::i; }

根据[namespace.memdef]:

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

“外面”是什么意思? 它可能意味着(1)外部的(如在最内层封闭命名空间内的所有范围都是允许的,但没有其他范围)或者它可能意味着(2)排除(如在,只考虑最内层的封闭命名空间)。 措辞可能含糊不清。 但是,请考虑这个与OP的原始问题和OP的评论合并的例子:

struct Outer {
    void f() { }
    class C { void foo(); };

    class Inner {
        friend class C;
        friend void f();
        static const int i = 0;
    };
};

void f() { (void)Outer::Inner::i; }               // compiles on GCC,Clang
void Outer::C::foo() { (void)Outer::Inner::i; }   // compiles on GCC,Clang

int main() { }

根据措辞(1), Outer::fOuter::C应该是Inner朋友。 基于措辞(2), ::f::C应该是朋友。 一个或另一个解释可能有意义,但GCC和Clang最终都以::fOuter::C作为朋友,这显然没有任何意义。 我已经提交了GCC Bug 66836Clang Bug 24088 所以要么两个编译器在一个方向或另一个方向都是错误的,或者标准的某些部分解释了这个逻辑肯定会让我失望。 我不打赌后者。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM