2016-07-09 26 views
3

Es ist etwas falsch mit, wie der Konvertierungsoperator im folgenden Code verhält:10 Konvertierungsoperator umgeht den Konstruktor des abgeleiteten Typs und überspringt die Initialisierung des Basistyps?

test.cpp:24:7: error: use of deleted function 'A::A(const A&)' 
    foo(c); //2) Not Ok 
    ^

Die Frage ist also: warum in der Hölle

struct A{ 
    A(){}; 
    A(const A &) = delete; 
}; 

struct B : A{ 
    B(const B & x){}; 
    B(int x){}; 
}; 

struct C{ 
    operator B() { 
     return B(1); 
    }; 
}; 

void foo(const A & x){ 
}; 

int main(){ 
    C c; 
    foo(c.operator B()); //1) Ok  
    foo(c); //2) Not Ok 
    return 0; 
}; 

ich einen Fehler im Aufruf 2) erhalten es möchte A kopieren-initialisieren? Beachten Sie, dass B einen eigenen Kopierkonstruktor deklariert. Ich würde zwar das 1) was erfolgreich ist identisch mit 2), aber anscheinend ist es nicht?

Auf das praktische Problem versuche ich zu lösen: In der Klasse C wollte ich eine Konvertierung in eine Drittanbieter-Klasse A, die das Kopieren verbietet, bereitstellen. Die Idee war, einen Proxy B: A zurückzugeben, der die Bewegungssemantik über A hinzufügt. Gibt es vielleicht eine andere Möglichkeit, den Konvertierungsoperator so zu definieren, dass er A auf dem Stapel erhält, während er seine Nicht-Kopier-Richtlinie befolgt.

+0

Oh Mist, ich habe jetzt herausgefunden, es Fehler in gcc 4.8.3 und VS Nov_2013, aber funktioniert ok mit gcc 4.9.3 und clang-7.0.2. Da es sich offenbar um einen gelösten Compiler-Bug handelt, sollte ich die Frage ablehnen? –

+0

Nein, das ist eine gültige Frage. Es ist nichts falsch mit einer Frage, die sich als Compiler-Fehler herausstellt. –

Antwort

1

In C++ 98, wenn eine Const-Referenz mit einem Rvalue initialisiert wird, darf der Compiler eine temporäre Kopie des Rvalue erstellen. Zu diesem Zweck muss möglicherweise ein Kopierkonstruktor vorhanden sein.

Obwohl Sie nicht im C++ 98-Modus kompilieren, sieht die Fehlermeldung, die Sie beobachten, sicherlich wie ein Überbleibsel dieser veralteten Anforderung aus. In Ihrem Fall wird eine const A & Referenz mit einem R-Wert vom Typ B initialisiert.

Der Code scheint mit GCC (http://coliru.stacked-crooked.com/a/0d58fd31a0b50cf5) gut zu kompilieren, was bedeutet, dass das, was Sie beobachten, höchstwahrscheinlich ein Fehler in Ihrem Compiler ist. Ich schlage nur eine mögliche Begründung für diesen Fehler vor.

0

gcc 6.1.1 kompiliert den angezeigten Code ohne Fehler:

$ cat t.C 
struct A{ 
    A(){}; 
    A(const A &) = delete; 
}; 

struct B : A{ 
    B(const B & x){}; 
    B(int x){}; 
}; 

struct C{ 
    operator B() { 
     return B(1); 
    }; 
}; 

void foo(const A & x){ 
}; 

int main(){ 
    C c; 
    foo(c.operator B()); //1) Ok  
    foo(c); //2) Not Ok 
    return 0; 
}; 
$ g++ -g -std=c++1z -o t t.C 
$ g++ --version 
g++ (GCC) 6.1.1 20160621 (Red Hat 6.1.1-3) 
Copyright (C) 2016 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

ich nichts falsch mit dem gezeigten Code. Ich glaube, das ist ein Fehler in welchem ​​Compiler Sie auch verwenden.