Wann benötigt ein Mitglied der statischen consExpr-Klasse eine Definition, die außerhalb der Klasse liegt?

8

Ich habe den folgenden C ++ 11 Code (vereinfachte Version):

%Vor%

GCC 4.9.1 kompiliert und verknüpft diesen Code in Ordnung. Clang 3.5.0 dagegen klagt über eine undefinierte Referenz:

%Vor%

Was ist richtig? Ist dieser Code legal oder nicht? Mein Verständnis der Regeln in Bezug auf statische Constexpr-Mitglieder (basierend hauptsächlich auf diese Frage ) ist, dass eine Definition außerhalb der Klasse nur benötigt wird, wenn die Adresse der Variablen verwendet wird. Aber ich nehme nicht die Adresse von Derived :: info oder verwende einen Verweis darauf; Ich übergebe es nur als Wert an den Base-Konstruktor.

Verschiedene Problemumgehungen, die ich gefunden habe:

  • Machen Sie beide Konstruktoren (Basis und abgeleitet) conexpr. Dies kann oder kann nicht eine Option für die realen Klassen sein, die komplexer sind als die im Beispiel. Ich werde es trotzdem versuchen.
  • Deklarieren Sie die Instanz von Derived in main mit automatischer statt statischer Dauer. Dies ist keine Option für das reale Projekt: Die abgeleitete Klasse ist eine Plugin-Implementierung, und eine Instanz davon muss als öffentliches Symbol in einem gemeinsamen Objekt exportiert werden.
  • Entfernen Sie Abgeleitet :: info vollständig und rufen Sie den Base-Konstruktor stattdessen mit einem durch Klammern initialisierten temporären Objekt auf, d. h. Base ({"Foobar", 2}) . Diese Lösung würde funktionieren, aber es wird (meiner Meinung nach) hässlich, da mehr Mitglieder zu struct Info hinzugefügt werden.
John Lindgren 27.09.2014, 18:16
quelle

1 Antwort

2

Aha, das Problem scheint der implizite Konstruktor Info(const Info &) copy zu sein. Um den Verweis const Info & auf diesen Konstruktor zu übergeben, muss die Adresse von Derived :: info übernommen werden.

Offenbar ist GCC bei der Optimierung des Kopierkonstruktors aggressiver als Clang. Wenn ich -fno-elide-constructors verwende, beschwert sich GCC auch über einen undefinierten Verweis auf Derived :: info.

In jedem Fall scheint die Deklaration der Konstruktoren Base und Derived als constexpr das zu erreichen, was ich hier erreichen will: Base :: info wird zur Kompilierzeit initialisiert, anstatt von einer separaten Derived :: info at run kopiert zu werden Zeit.

    
John Lindgren 27.09.2014, 19:24
quelle

Tags und Links