通过using声明将函数设为友合法吗?

Is it legal to friend a function via a using declaration?

本文关键字:using 声明 函数 通过      更新时间:2023-10-16

以下(这里的LiveWorkspace)被GCC 4.7.2、GCC 4.8.0和ICC 13.0.1拒绝。

namespace A {
    namespace B {
        void C();
    }
    using B::C;
}
class D {
    friend void A::C();
};

另外,它使Clang 3.2崩溃。我已经提交了一个bug报告和补丁,对于崩溃的bug,但我不能100%确定这段代码是否真的是错误的,因为我在§7.3.3[命名空间]中找不到任何东西。udecl]§11.3 [class.friend]明确地解决了这种情况,但可能在各种名称说明符术语的定义中有我遗漏的东西。

此外,似乎所有四个编译器都接受以下内容(这里是LiveWorkspace):

namespace A {
    namespace B {
        class C;
    }
    using B::C;
}
class D {
    friend class A::C;
};

这两种情况似乎没有什么根本不同,所以我很好奇GCC和ICC拒绝第一个例子的理由是什么,而不是这个例子,如果有的话。有更熟悉标准的人能找到解决这个问题的方法吗?

这绝对是一个小问题,但既然我正在修补它,我想确保我做的是正确的…

EDIT:这是补丁现在clang/trunk!

NEW EDIT:下面Johannes的回答解释了为什么我的原始示例被拒绝,但它似乎没有解释为什么GCC和ICC也拒绝以下(这里的LiveWorkspace):

namespace A {
    namespace B {
        void C();
    }
    using B::C;
    class D {
        friend void C();
    };
}

8.3p1:

当声明符id被限定时,声明应引用限定符所指向的类或命名空间的先前声明的成员引用(或者,在命名空间的情况下,引用该命名空间(7.3.1)的内联命名空间集的一个元素)或其专业化;成员不能仅仅通过using声明引入在由声明符id的嵌套名称说明符指定的类或命名空间的作用域中。

class foo;class foo::bar;不包含声明符id,因此不受此规则的影响。相反,foo::bar是详细类型说明符(7.1.6.3)的一部分。