通过使用声明来传递函数是否合法?

Ste*_*Lin 5 c++ language-lawyer

以下(此处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();
};
Run Code Online (Sandbox Code Playgroud)

此外,它崩溃了Clang 3.2(!).我已经为崩溃错误提交了一个错误报告和补丁,但是我不能100%确定这段代码是否真的错误,因为我在§7.3.3[namespace.udecl]中找不到任何内容或者§11.3[class.friend]明确地解决了这种情况,但也许在我错过的各种名称说明符之一的定义中有一些东西.

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

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

class D {
    friend class A::C;
};
Run Code Online (Sandbox Code Playgroud)

这两种情况似乎没有任何根本的不同,所以我很好奇GCC和ICC拒绝第一个例子的理由,但不是这个例子,如果有的话.任何更熟悉标准的人都可以找到解决此问题的任何内容吗?

这绝对是一个小问题,但是因为我正在修补它,我想确定我做的是正确的事情......

编辑:现在在clang/trunk中打补丁!

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

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

    class D {
        friend void C();
    };
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*itb 4

8.3p1:

当 declarator-id 被限定时,声明应引用该限定符所引用的类或命名空间的先前声明的成员(或者,在命名空间的情况下,引用该命名空间的内联命名空间集的元素(7.3 .1)) 或其专业化;该成员不应仅仅由声明符 id 的嵌套名称说明符指定的类或命名空间范围内的 using 声明引入。

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