2013-03-28 53 views
5

以下(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(); 
}; 

此外,它崩溃铛3.2(!)。我已经提交了一个bug报告,并且已经提供了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!

新的编辑:下面约翰内斯的回答解释了为什么我原来的例子被拒绝,但它似乎并没有解释为什么GCC和ICC也拒绝以下(LiveWorkspace here)

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

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

回答

4

8.3p1:

当声明符-id为合格, 声明应指类或命名空间,其限定词 指的先前声明的构件(或者,在一个命名空间的情况下, (7.3.1)) 的内联命名空间集合的元素或其专业化; 该成员不仅仅是由声明者ID的嵌套名称说明者指定的类或名称空间范围内的使用声明 引入的。

一个class foo;class foo::bar;不包含声明符-ID,所以它不受此规则。相反,foo::bar是详细说明类型说明符(7.1.6.3)的一部分。

+0

那么为什么类的版本可以吗? –

+0

好吧,+1,对我来说很有意义。好东西,否则这将需要更多的努力来解决:D –

+0

但我不知道的理由。这就是规则出现在规范中的地方。如果这能帮助你,我很高兴。 –