Warum wird der folgende Code kompiliert, obwohl ich nicht definierte Memberfunktionen habe?

8

Ich habe die Hälfte an diesem Stück Code gearbeitet und dachte, dass das offensichtlich nicht kompiliert wird, bevor ich den Build-Knopf drücke. Ich war überrascht, dass es nicht nur kompiliert, sondern auch verlinkt und gearbeitet hat.

Wenn ich raten würde, würde ich sagen, dass SFINAE dafür verantwortlich ist, das zu kompilieren ... oder?

%Vor%

BEARBEITEN : Ich benutze Visual-C ++ 2008, vielleicht ist es eine seltsame Eigenart von VS

    
Samaursa 27.02.2012, 21:19
quelle

5 Antworten

3

Der Code ist nicht legal.

i = j ruft den implizit definierten Kopierzuweisungsoperator in MyClass auf. Diese Funktion ruft den Kopierzuweisungsoperator für jedes seiner Unterobjekte auf, einschließlich der direkten Basisklassen [class.copy 12.8 p28].

Wenn Sie dem Kopierzuweisungsoperator für BaseClass Code hinzufügen, können Sie sehen, wo VS falsch läuft:

%Vor%

Bei mir wird "struct MyClass" ausgedruckt. VS ist der BaseClass Kopie Zuweisungsoperator aufrufe, indem Sie die Parameter übergeben erhielten in MyClass:operator= direkt, und nicht nur das BaseClass Unterobjekt von j.

SFINAE kommt nicht ins Spiel, weil die Template-Funktionen nicht fehlschlagen. VS generiert den impliziten Kopierzuweisungsoperator einfach falsch.

Um es zusammenzufassen: VS generiert den impliziten Kopierzuweisungsoperator als

%Vor%

Wenn es sein sollte:

%Vor%     
bames53 27.02.2012, 22:20
quelle
1

Im Dunkeln geschossen: Der Compiler instanziiert die Basisklasse ' operator = mit T = MyClass . Ich weiß jetzt, ob das legal oder sogar erforderlich ist, aber es macht einen gewissen Sinn: Der automatisch generierte Code für operator = sieht im Wesentlichen so aus (na ja, Pseudocode):

%Vor%

Nun stellt der Compiler fest, dass BaseClass::operator =<MyClass>(MyClass const&) die beste Übereinstimmung ist und instanziiert.

    
Konrad Rudolph 27.02.2012 21:40
quelle
0

Nun, da es BaseClass::operator=(const BaseClass&) nicht aufrufen kann (von der standardmäßig generierten MyClass::operator= für das, was es wert ist), weil es privat ist, ruft es nur template<typename T> BaseClass::operator(const T &) mit T=BaseClass auf. Es gibt also keinen Aufruf für eine nicht definierte Funktion.

Ich schätze, die Situation wäre anders, wenn die anderen öffentlich wären. In diesem Fall würde der Compiler diese über die Vorlage bevorzugen, aber da er sie nicht sehen kann, wenn sie privat sind, passen die Template-Versionen genauso gut.

    
Christian Rau 27.02.2012 21:26
quelle
0

Der Compiler generiert automatisch einen (Standard) Kopierkonstruktor für MyClass , da ein solcher nicht definiert ist. Wenn Sie den Typ i und j von MyClass auf BaseClass ändern, sehen Sie den erwarteten Fehler, da der Compiler dann versucht, den privaten, nicht implementierten Zuweisungsoperator zu binden.

Wenn wir mit MSVC 2010 Ultimate SP1 etwas tiefer gehen, können wir den genauen Grund sehen:

%Vor%

Der Zuweisungsoperator wird für MyClass by BaseClass::=<T> unter Verwendung von MyClass als Typ durch MyClass es Standardkopieoperator aufgerufen, ob dies ein Fehler ist oder ein MSVC-ism an MS und den C ++ - Standard liegt zu entscheiden.

    
Necrolis 27.02.2012 21:27
quelle
0

MyClass verwendet einen implizit definierten Kopierzuweisungsoperator, da es keine vom Benutzer deklarierte Version gibt. Gemäß dem Standard führt diese implizite Kopierzuordnung Folgendes aus (C ++ 03 12.8 / 13 "Kopieren von Klassenobjekten"):

  • Jedes Unterobjekt wird seinem Typ entsprechend zugewiesen: - Wenn das Unterobjekt vom Klassentyp ist, wird der Kopierzuweisungsoperator für die Klasse verwendet (wie durch explizite Qualifizierung; das heißt, alle möglichen virtuellen überschreibenden Funktionen in mehr abgeleiteten Klassen zu ignorieren);

Beachten Sie, dass der Standard in 12.8 / 9 einen benutzerdeklarierten Kopierzuweisungsoperator als "nicht statische Nicht-Template -Memberfunktion der Klasse X mit genau einem Parameter des Typs X, X & amp; , const X & amp;, flüchtig X & amp; oder const flüchtig X & amp; (Betonung meiner).

Also nach dem Standard, die Template-Funktion

%Vor%

Sollte nicht vom Operator für die implizite Kopienzuordnung MyClass aufgerufen werden. MSVC handelt hier nicht standardgemäß. GCC diagnostiziert dies zu Recht:

%Vor%     
Michael Burr 28.02.2012 06:46
quelle

Tags und Links