[gelöst] Compilerfehlerfehler C2280 bei std::vector

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
joggel

Re: [gelöst] Compilerfehlerfehler C2280 bei std::vector

Beitrag von joggel »

Also... ich habe es gerade mal getestet.
Und so weit ich das in meinem Code korrekt gemacht habe (anstatt Building bldng = Building(); vec.push_back(bldng ) habe ich geschrieben vec.emplace_back(), da keine Argumente dem C'tor übergeben werden), bekomme ich wieder diese Fehlermeldung, wenn ich die sf::Shader-Klasse als Member in meine Building-Klasse aufnehme.

Edit:
Gerade etwas gegoogelt. Sollte ich vlt so einen Move-Konstruktor implementieren?
Na toll... dieser Move-C'tor scheint die Lösung meines Problems zu sein...
Ach verdammt!! Da habe ich ja wieder das Problem, das SFML (sf::Shader) nicht move-fähig ist :x
Zuletzt geändert von joggel am 21.02.2018, 11:36, insgesamt 1-mal geändert.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [gelöst] Compilerfehlerfehler C2280 bei std::vector

Beitrag von dot »

Ich denk, an dieser Stelle ist es das Beste, dich auf das hier zu verweisen: http://thbecker.net/articles/rvalue_ref ... on_01.html

Das sollte helfen das Problem zu verstehen und zu einer Lösung zu kommen. Das soll nicht heißen dass ich dir keine Antwort geben will, aber einfach nur den richtigen Code hinzuschreiben wird dir viel weniger helfen als dieser Artikel... ;)

Edit: Du brauchst keinen Move Constructor implementieren, der implizite Move Constructor sollte hier völlig ausreichend sein (sofern dein Building nicht irgendwelche anderen merkwürdigen Member hat).
joggel

Re: [gelöst] Compilerfehlerfehler C2280 bei std::vector

Beitrag von joggel »

Erstmal danke für den Link. Ich muss mich da mal etwas intensiver beschäftigen. Auch mit den ganzen neuen Features von C++, bin noch im Jahr '99 ;) ^^

Meine Lösung:
Ich habe einen move-operator implementiert

Code: Alles auswählen

Building& Building::operator=(Building&& building)
{
	if (this != &building)
	{
		mShader = building.moveShader();
	}
	return *this;
}
moveShader sieht wie folgt aus:
std::unique_ptr<sf::Shader> moveShader() { return std::move(mShader); }
Dann habe ich explizit einen move-C'tor erstellen müssen(!):

Code: Alles auswählen

	Building(Building&& otherBuilding)
	{
		*this = std::move(otherBuilding);
	}
Das Speichern einer Building-Instanz im std::vector habe ich wie folgt realisiert:
vec.push_back(Building());
Es scheint nun zu funktionieren. Ich hoffe das ist eine/die saubere Lösung, und kein dreckiger "Hack"...

Was mich aber etwas an diesem Desgin stört, sofern dies eben der gängige weg ist, ist dass ich dadurch solche öffentlichen Funktionen wie Building::moveShader haben muss, die ja keinerlei Sinn haben, außer eben für std::move(..). Das zerstört, nach meinem geschmack, mir etwas das Design; denn alle Funktionen der zB Building-Klasse sollten ja auch nur Aufgaben erfüllen die typisch für ein Building (Gebäude) sind, und nicht irgend eine Aufgabe erfüllen, die zB dafür da sind, um eine Instanz korrekt in einem std::vector zu speichern....
Aber okay, vlt ist das hier der Fall, weil diese konkrete Klasse (sf::shader) noch nicht für die move-semantik ausgelegt ist.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4852
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [gelöst] Compilerfehlerfehler C2280 bei std::vector

Beitrag von Schrompf »

Also erstmal: Designproblem - den Shader als Instanz in Building zu haben impliziert Besitz. Das heißt, jedes Building hat seinen eigenen Shader. Willst Du das überhaupt? Shader sind für mich Helfer beim Rendering, also üblicherweise im Besitz des Renderers oder einer irgendwie gearteten Ressourcenverwaltung. Das Building hat bestenfalls einen Verweis (Referenz oder Zeiger) auf den Shader, den es benutzen will. Und dann erledigt sich der ganze Move-Kram eh.

Zweitens: Du bist in einer Member Function. Du musst keine öffentliche Funktion bauen, nur um an den Shader der anderen Building-Instanz ranzukommen. Du kannst dem einfach direkt in die Karten greifen. Und da das der Move-Konstruktor ist, weißt Du auch mit Sicherheit, dass das andere Objekt danach stirbt. Eine Move-Zuweisung sieht also üblicherweise so aus:

Code: Alles auswählen

Building& Building::operator = (Building&& b) {
  mShader = b.mShader;
  b.mShader = nullptr;
}
Den Selbsttest kannst Du meiner Meinung nach knicken. Irgendwelche Buchautoren konstruieren da elaborierte Use Cases für den Fall, dass irgendein Trottel mal a = a; schreibt, aber ganz ehrlich: wie blöd muss man für sowas sein. Und wie verzweifelt als Programmierer, damit man Runtime-Performance verbrennt, nur um so einen exotischen Quatschfall abzufangen.

Drittens: wenn Du einen Move-Zuweisungsoperator schreibst, solltest Du auch immer auch einen Move-Konstruktor schreiben. Da gilt das Gleiche wie für Kopierkonstruktor / Zuweisung: hast Du das eine, willst Du quasi zwangsweise auch das andere haben.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
joggel

Re: [gelöst] Compilerfehlerfehler C2280 bei std::vector

Beitrag von joggel »

Ja, stimmt. Das mit dem Selbsttest ist schwachsinn...entstand durch copy&paste.
Das ich auf private membervariablen einer anderen Instanz zugreifen kann ist mir jetzt neu...werd ich testen.
Die Designfrage mit dem shader: das zeichnen, die Sprite(s) und sonst noch halte ich alle in der Klasse.
Also in meinem fall ist die klasse eine repräsentation der Logik UND Grafik. Der Shader findet eben auch nur beim Gebäude verwendung.
Man kann sich da streiten was besser ist. Klar, performanter und resourcen-sparender wäre es wenn man sowas in einer Resourcenverwaltung auslagert...aber hier für diesen kleinen Anwendungsfall hielt ich das für übertrieben... "Nur ein kleines Spiel". Außerdem gibt es vlt maximal 3 gebäude auf der Karte...

Danke Dir erstmal.

Edit:
Tatsache!! Ich kann auf die privaten Member einer fremden Instanz zugreifen...
Antworten