Aha, ja das ergibt Sinn. Darauf bin ich auch schon des öfteren reingefallen und habe viel zu lange gesucht. Ich wünschte der VS C++-Compiler würde bei expliziten
default-Funktionen den Fehler direkt auch dort anzeigen, wenn die Funktion verwendet wird aber nicht generiert werden kann. Wenn man die Funktion in der Quelldatei
default macht, dann geht es ja auch.
Bezüglich deiner Frage: Ja, Referenzen als Klassenvariablen sind doof. Die Funktionen können nicht generiert werden, da die Zuweisungsoperatoren ja die Variablen überschreiben würden.
Eine Möglichkeit es trotzdem zu erzwingen ist es, den Zuweisungsoperator wie folgt über den Konstruktor zu implementieren:
Code: Alles auswählen
#include <new>
SoundController& SoundController::operator=(SoundController&& other)
{
if (this == &other)
return *this;
this->~SoundController();
::new(this) SoundController(static_cast<SoundController&&>(other));
return *this;
}
Das habe ich in der Vergangenheit schon öfter so gemacht. Ich muss aber zugeben, dass ich mir nicht 100% sicher bin, ob das nach dem C++-Standard eigentlich überhaupt erlaubt ist. Insbesondere wenn man eben Referenzen oder andere konstante Klassenvariablen hat. Das ist auch etwas, dessen Status sich unter Umständen mal geändert hat.
Referenzen oder generell konstante Klassenvariablen sind leider generell sehr unpraktisch in C++. Wobei man konstante Klassenvariablen wenigstens schnell nicht-konstant machen kann, sollte das notwendig sein. Aber bei Referenzen hat man dann einen riesen Ärger. Und dabei ist es nur eine Frage der Zeit bis man sie doch mal neuzuweisen möchte (vlt. auch zu Test-/Debuggingzwecken). Und dann muss man ja alle Zugriffsstellen manuell mit
* versehen bzw. alle
. in
-> umwandeln. Aus diesem Grund verwende ich seit einiger Zeit rein grundsätzlich keine Referenzen mehr als Klassenvariablen. Der Ärger ist das meiner Meinung nach einfach nach nicht Wert.
Das ganze Objektmodel und inklusive Move-Semantiks ist eh ein Fall für den Jammer-Thread. Dieses ganze Move ist einfach mal irre verwirrend und kompliziert implementiert. Als Beispiel in unserem Fall wäre es viel schöner, wenn standardmäßig Zuweisungen so wie in meinen Vorschlag implementiert wären, sodass man insbesondere auch (fast) nie mehr explizit Zuweisungsoperatoren selbst definieren muss, sondern nur noch die Verschiebe- und Kopier
konstruktoren. Sehr oft sind Zuweisungsoperatoren sonst nur eine manuelle Kopie des Codes im Destruktor & Konstruktor.