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:
Getestet mit clang ++ 3.8 und gcc 5.4, aber Godbolt schlägt vor, dass dies in neueren GCC-Versionen nicht geändert wurde .
Ich schaute auf Interaktion zwischen declltype und Klassenmitgliedsnamen shadowing einen externen Namen , wo der Name eines variable kann sich entweder auf eine Variable im äußeren Bereich oder auf einen Klassenmember beziehen. Im Gegensatz dazu handelt meine Frage hier von einem Typalias. Es gibt keine Mehrdeutigkeit, da sich Foo
immer auf ::Foo
innerhalb des Klassenbereichs bezieht. Ich sehe nicht, wie die Antwort dort auf mein Problem zutrifft.
Dies liegt wahrscheinlich an einem Missverständnis dessen, welcher Typ tatsächlich Aliasnamen sind.
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.
Tags und Links c++ g++ c++14 clang++ type-alias