Darf ich einen Membertyp-Alias ​​für einen Typ in einem umgebenden Bereich mit demselben Namen deklarieren?

8

Ich möchte, dass eine Struktur einen Typalias in einen anderen Typ für Metaprogrammierungszwecke enthält:

%Vor%

Dann kann ich Sachen wie WithNestedTypeAlias::Foo in einer Vorlage usw. machen.

Wie ich verstehe, ist dieser Typ-Alias ​​gültig, weil er die Bedeutung des Typs Foo nicht ändert. Clang kompiliert das glücklich.

Der GCC beschwert sich jedoch:

%Vor%

Jetzt bin ich verwirrt, weil ich die Bedeutung von Foo von struct Foo explizit nicht ändere.

Was ist das richtige Verhalten für C ++ 14? Ich weiß, dass ich das umgehen kann, indem ich die struct Foo umbenenne, aber ich würde gerne verstehen, ob der Fehler von GCC hier richtig ist.

Anmerkungen:

amon 06.01.2017, 23:24
quelle

1 Antwort

7

Die Regel, die GCC erzwingen soll, ist in [basic.scope.class]:

  

2) Ein Name N, der in einer Klasse S verwendet wird, muss sich auf dieselbe Deklaration in seinem Kontext beziehen und wenn er im abgeschlossenen Bereich von S neu bewertet wird. Für einen Verstoß gegen diese Regel ist keine Diagnose erforderlich.

Der Standard besagt, dass die Verletzung keine Diagnose erfordert, daher ist es möglich, dass sowohl GCC als auch Clang konform sind, weil (wenn GCC richtig ist) der Code nicht gültig ist, aber der Compiler sie nicht diagnostizieren muss / p>

Der Zweck dieser Regel besteht darin, dass Namen, die in einer Klasse verwendet werden, immer dieselbe Bedeutung haben, und das Neuordnen von Elementen ändert nicht die Art, wie sie interpretiert werden, z. B.

%Vor%

In diesem Beispiel ändert sich der Name N und die Reihenfolge der Mitglieder ändert die Größe von S::array . Wenn S::array definiert ist N bezieht sich auf den Typ ::N , aber im abgeschlossenen Bereich von S bezieht es sich stattdessen auf S::N . Dies verstößt gegen die oben genannte Regel.

In Ihrem Beispiel ändert sich der Name Foo viel weniger gefährlich, da er sich immer noch auf den gleichen Typ bezieht, jedoch ändert er sich von der Deklaration von ::Foo zur Deklaration von S::Foo . Die Regel ist so formuliert, dass sie sich auf Erklärungen bezieht, daher denke ich, dass der GCC richtig ist.

    
Jonathan Wakely 06.01.2017, 23:45
quelle

Tags und Links