GCC: Vorlagenkonstruktor instanziiert, wenn Kopierkonstruktor benötigt wird

8

Im folgenden Beispiel instanziiert GCC >= 4.7 den Vorlagenkonstruktor (den Sie durch Lesen der Fehlermeldungen beobachten können), obwohl nur der implizit generierte Kopierkonstruktor benötigt wird.

%Vor%

Der obige Code wird in GCC < 4.7 , clang und MSVS kompiliert (weiß nicht, welche Version ich verwendet habe, die von Ссылка ). In GCC >= 4.7 compilation schlägt mit der folgenden Meldung fehl:

%Vor%

Beim Aufruf von b.set(a); sucht GCC offensichtlich nach einem Kopierkonstruktor und instanziiert den Template-Konstruktor, der seinerseits ambiguous<int, int> instanziiert, was (uhm ...) mehrdeutig ist.

Frage : Ist GCC richtig, um den Vorlagenkonstruktor zu instanziieren, obwohl ein Kopierkonstruktor benötigt wird?

    
DaviD. 19.05.2014, 15:23
quelle

1 Antwort

6

gcc ist korrekt.

Es gibt hier ein paar Probleme, die sich leider in Ihrer Frage vermischt haben:

Erstens, das Verhalten von gcc & lt; 4.7 ist nicht grundlegend anders; Alle Versionen von gcc seit (mindestens) 4,4 lehnen das sehr ähnliche Programm ab:

%Vor%

Beachten Sie, dass der einzige wirkliche Unterschied darin besteht, dass die Kopierinitialisierung explizit ist und nicht in einem Funktionsaufruf enthalten ist. Clang akzeptiert dieses Programm übrigens.

Als nächstes ist es nicht entscheidend, dass der Kopierkonstruktor beteiligt ist (Regel 12.8p6 in C ++ 11). Hier ist ein anderes ähnliches Programm, das gcc (alle Versionen) ablehnt und akzeptiert:

%Vor%

Der Unterschied zwischen clang und gcc besteht in der Anwendung von 14.8.2p8:

  

[...] [Hinweis: Die Auswertung der substituierten Typen und Ausdrücke kann zu Nebeneffekten wie der Instanziierung von Klassenvorlagenspezialisierungen und / oder Funktionsvorlagenspezialisierungen, der Erzeugung implizit definierter Funktionen usw. führen Nebenwirkungen sind nicht im "unmittelbaren Kontext" und können dazu führen, dass das Programm schlecht aussieht. - Endnote]

Die Ambiguität in der Template-Spezialisierung ambiguous<int, int> liegt außerhalb des unmittelbaren Kontexts, so dass das Programm schlecht gebildet ist. (Ein unterstützendes Argument dafür ist, dass die Mehrdeutigkeit der Vorlagenspezialisierung nicht in der nachfolgenden Liste von Gründen für das Fehlschlagen der Typableitung auftaucht).

MSVC ist wieder anders; Es akzeptiert das folgende Programm, das sowohl clang als auch gcc ablehnt:

%Vor%

Das liegt an Regel 12.8p6:

  

Eine Deklaration eines Konstruktors für eine Klasse X ist fehlerhaft, wenn ihr erster Parameter vom Typ (optional cv-qualifiziert) X ist und entweder keine anderen Parameter vorhanden sind oder alle anderen Parameter Standardargumente haben. Eine Memberfunktionsvorlage wird niemals instanziiert, um eine solche Konstruktorsignatur zu erstellen.

Um jedoch zu bestimmen, ob eine Element-Funktionsschablonen-Instantiierung ein Konstruktor ist, der hinsichtlich 12.8p6 schlecht ausgebildet ist, ist es notwendig, seine Deklaration zu instanziieren (vgl. 14.7.1p9). Beachten Sie, dass MSVC das folgende Programm zurückweist, so dass es nicht einmal konsistent ist:

%Vor%

Dies hat einige sehr amüsante Verhaltenseffekte; MSVC akzeptiert das folgende (schlecht geformte) Programm:

%Vor%

Wenn jedoch die Kopierinitialisierung S b(a) auskommentiert ist, wird das Programm abgelehnt!

    
ecatmur 19.05.2014, 17:37
quelle

Tags und Links