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

时间:2013-03-28 21:39:12

标签: c++ language-lawyer

以下(LiveWorkspace here)被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(!)。我已经为崩溃错误提交了一个错误报告和patch,但我不能100%确定这段代码是否真的出错,因为我在§7.3中找不到任何内容。 3 [namespace.udecl] §11.3[class.friend] 明确解决了这种情况,但也许在我的各种名称说明符之一的定义中有一些东西错过。

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

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

class D {
    friend class A::C;
};

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

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

编辑This is patched now in clang/trunk!

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

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

    class D {
        friend void C();
    };
}

1 个答案:

答案 0 :(得分:4)

8.3p1:

  

当declarator-id合格时,   声明应引用先前声明的限定符所在的类或命名空间的成员   引用(或者,在命名空间的情况下,引用该命名空间的内联命名空间集合的元素(7.3.1))   或专业化; 该成员不仅仅是通过使用声明引入的   在由declarator-id的nested-name-specifier指定的类或命名空间的范围内。

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