2013-03-28 5 views
5

Das folgende (LiveWorkspace here) wird von GCC 4.7.2, GCC 4.8.0 und ICC 13.0.1 abgelehnt.Ist es legal, eine Funktion über eine using-Deklaration zu befreunden?

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

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

Darüber hinaus stürzt Clang 3.2 (!). Ich habe bereits einen Fehlerbericht und patch für den Absturz Bug, aber ich bin nicht 100% sicher, wenn dieser Code wirklich falsch ist, weil ich nichts finden kann in §7.3.3 [namespace.udecl] oder §11.3 [class.friend], die explizit diesen Fall anspricht, aber vielleicht gibt es etwas in der Definition eines der verschiedenen Name Specifier Begriffe, die ich verpasst habe.

Darüber hinaus scheint es, wie alle vier Compiler die folgende (LiveWorkspace here) akzeptieren:

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

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

Es hat nichts grundlegend anders über diese beiden Fälle zu sein scheinen, so bin ich gespannt, was GCC und ICC Gründen lehne das erste Beispiel ab, aber nicht dieses, falls vorhanden. Kann jemand, der mit dem Standard vertrauter ist, etwas finden, das sich damit befasst?

Es ist definitiv ein kleines Problem am besten, aber da ich es bin Patchen, ich möchte sicher sein, ich bin das Richtige zu tun ...

EDIT: This is patched now in clang/trunk!

NEW EDIT: Johannes Antwort unten erklärt, warum mein ursprüngliches Beispiel abgelehnt, aber es scheint nicht zu erklären, warum GCC und ICC auch die folgend (LiveWorkspace here) ablehnen:

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

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

Antwort

4

8.3p1:

Wenn die declarator-ID ist qualifiziert, die Erklärung zu einem zuvor erklärten Mitglied der Klasse oder Namensraumes, zu dem der Qualifier bezieht (oder, im Fall eines Namensraumes beziehen soll, eines Elements des Inline-Namensraumsatzes dieses Namensraums (7.3.1)) oder einer Spezialisierung davon; Das Member darf nicht einfach durch eine using-Deklaration in den Bereich der Klasse oder des Namespace eingeführt worden sein, der vom Nested-Name-Specifier der Deklarator-ID nominiert wurde.

A class foo; oder class foo::bar; enthält keine declarator-id, so wird es von dieser Regel nicht betroffen. Stattdessen ist der foo::bar Teil eines elaborierten Typ-Spezifizierers (7.1.6.3).

+0

Warum ist die Klassenversion in Ordnung? –

+0

ok, +1, macht Sinn für mich. Gute Sache auch, sonst würde dies mehr Aufwand erfordern, um zu beheben: D –

+0

Ich kenne die Begründung jedoch nicht. An dieser Stelle wird die Regel in der Spezifikation angezeigt. Ich bin froh, wenn dir das hilft. –

Verwandte Themen