Friend-Klasse, Vererbung und typedef - welches Verhalten ist korrekt?

8

Ich bin auf einen Fehler gestoßen, der sich nur in GCC 6.2.0, aber nicht in Clang 3.9.0 (beide in -std=c++14 mode) manifestiert. Ich bin mir nicht sicher, welches Verhalten korrekt ist (und ob ich einen Fehler einreichen sollte).

Hier ist der Code:

%Vor%

Bei GCC gibt dies den folgenden Fehler:

%Vor%

Nach dem, was ich über den C ++ - Standard weiß, darf das Elternteil typedef (oder using s) nicht in den Geltungsbereich des untergeordneten Elements und Sie müssen den Namen explizit angeben: siehe zum Beispiel propagiert 'typedef' von basierter zu abgeleiteter Klasse für 'template' . Es scheint mir also, dass GCC hier falsch ist, aber ich bin mir meiner C ++ - Kenntnisse nicht so sicher, um es mit Zuversicht zu sagen.

Danke für jede Hilfe!

    
Nikolay Amiantov 05.10.2016, 13:35
quelle

2 Antworten

4
  

Nach dem, was ich über den C ++ - Standard weiß, darf das Elternteil typedef (oder using s) nicht in den Geltungsbereich des untergeordneten Elements gelangen, und Sie müssen den Namen

explizit angeben

Das ist falsch. Mitglieder (einschließlich Typ-Aliase), die in Basisklassen deklariert sind, sind normalerweise in abgeleiteten Klassen sichtbar. Die Frage, mit der Sie verknüpft sind, behandelt Vorlagen mit einer abhängigen Basisklasse, bei denen die Suche nach zweiphasigem Namen gilt (und gilt wiederum für alles, nicht nur Aliase).

Abgesehen davon ist der relevante Teil des Standards C ++ 14 (N4140) [dcl.type.elab] 7.1.6.3/2 (Hervorhebung von mir):

  

3.4.4 beschreibt, wie die Namenssuche für den Bezeichner in einem bearbeiteten Typ-Spezifizierer vorgeht. Wenn der Bezeichner   Wird in einen Klassennamen oder enum-name aufgelöst, der elaborierte-Typ-Spezifizierer führt ihn in die Deklaration ein   Auf die gleiche Weise führt ein einfacher Typ-Spezifizierer seinen Typnamen ein. Wenn der Bezeichner in einen Typdef-Namen aufgelöst wird oder   Die simple-template-ID wird in eine Alias-Vorlagen-Spezialisierung aufgelöst, der elaborated-type-specifier ist schlecht formatiert.

(Hinweis: elaborated-type-specifier ist das Konstrukt class T für einige T , mit denen wir es zu tun haben).

3.4.4 sagt wiederum, dass beim Auflösen des Bezeichners in einem elaborierten Typ-Spezifizierer in einen Namen nicht-type Namen ignoriert werden (aber Typnamen werden normalerweise gefunden).

GCC hat also eigentlich recht, da der typedef-name foo_t im Geltungsbereich bar_t im Geltungsbereich "näher" liegt als der globale Vorlagenname foo_t . Der unqualifizierte Name foo_t in% baz_t wird daher in bar_t::foo_t aufgelöst, was ein typedef-name ist und daher den elaborierten Typ-Spezifizierer schlecht formatiert.

Das Problem liegt in der Auflösung des unqualifizierten Namens foo_t . Wie Sie sich in Kommentaren zu der Frage notieren, sollten Sie explizit angeben, welche foo_t Sie meinen, sollte das Problem lösen:

%Vor%     
Angew 05.10.2016, 13:42
quelle
1

Die Deklaration der Mitglieder ist für ihre Unterklasse sichtbar. Das Problem für Ihre Frage betrifft die doppelte Deklaration. Bitte überprüfen Sie den folgenden Code

%Vor%

Der Fehlercode, den Sie posten test.cpp:9:19: note: ‘using foo_t = int’ has a previous declaration here hat dieses Problem bereits erwähnt.

Andererseits kann die Klasse friend nicht auf einfache Daten angewendet werden. Bitte überprüfen Sie den folgenden Code:

%Vor%

Hier ist die Problemumgehung, wenn Sie wirklich den doppelten Namen der Deklaration haben müssen:

%Vor%     
Kenman Trunk 05.10.2016 13:58
quelle

Tags und Links