2013-03-28 4 views
5

Następujące (LiveWorkspace here) jest odrzucane przez GCC 4.7.2, GCC 4.8.0 i ICC 13.0.1.Czy posiadanie funkcji za pośrednictwem deklaracji użycia jest legalne?

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

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

Dodatkowo powoduje awarię Clang 3.2 (!). Przesłałem już zgłoszenie błędu i patch dla błędu awarii, ale nie jestem w 100% pewien, czy ten kod jest naprawdę błędny, ponieważ nie mogę znaleźć niczego w §7.3.3 [namespace.udecl] lub §11.3 [class.friend], który wyraźnie odnosi się do tej sprawy, ale być może jest coś w definicji jednego z różnych terminów, które przeoczyłem.

Ponadto, wydaje się, że wszystkie cztery kompilatory przyjąć następujące (LiveWorkspace here):

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

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

Tam nie wydaje się być czymś fundamentalnie różni się o tych dwóch sprawach, więc jestem ciekaw co GCC i podstawy do MTK odrzucić pierwszy przykład, ale nie ten, jeśli taki istnieje. Czy ktokolwiek bardziej zaznajomiony z normą może znaleźć coś, co to rozwiązałoby?

To zdecydowanie niewielki problem w najlepszym wypadku, ale ponieważ jestem łatanie go, chciałbym mieć pewność, że robię słusznie ...

EDIT: This is patched now in clang/trunk!

edit: poniżej odpowiedź Johannes wyjaśnia dlaczego mój oryginalny przykład zostanie odrzucony, ale nie wydaje się, aby wyjaśnić dlaczego GCC i ICC również odrzucić następujące (LiveWorkspace here):

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

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

Odpowiedz

4

8.3p1:

Gdy declarator-id jest kwalifikowana, deklaracja odnosi się do wcześniej zadeklarowanej członek klasy lub przestrzeni nazw, do których odnosi się kwalifikator (lub, w przypadku nazw, elementu zbioru przestrzeni wstawionej o tej przestrzeni nazw (7.3.1)) lub do specjalizacji; członek nie zostanie jedynie wprowadzony przez deklarację użycia w zakresie klasy lub przestrzeni nazw wyznaczonych przez specyfikator-nazwy-zagnieżdżnika-deklaratora-id.

class foo; lub class foo::bar; nie zawiera declarator-id, więc nie ma wpływu na to reguły. Zamiast tego, foo::bar jest częścią specyfikacji opracowanego typu (7.1.6.3).

+0

dlaczego więc wersja klasowa jest w porządku? –

+0

ok, +1, ma dla mnie sens. dobrze, w przeciwnym razie wymagałoby to więcej wysiłku, aby naprawić: D –

+0

Nie znam racjonalnego uzasadnienia. To właśnie tam pojawia się reguła w specyfikacji. Cieszę się, że to ci pomaga. –