Warum kann ich ein Element nicht in Vektor von nicht kopierbaren Objekten verschieben?

8

Der Compiler sagt mir, dass ich versuche, auf eine gelöschte Funktion (d. h. den Kopierkonstruktor eines Lambda-Ausdrucks) zuzugreifen. Aber ich sehe nicht wo.

%Vor%

( Code ist auch hier )

(Ich versuche herauszufinden, warum sie shared_ptr<task> in Ссылка ) verwenden.

Auf Gcc und MSVC bekomme ich den gleichen Fehler - ich fürchte, ich mache etwas falsches ...

%Vor%

Warum kann ich dieses std::function nicht auf den Vektor setzen?

    
xtofl 06.06.2017, 07:32
quelle

3 Antworten

4

Von cppreference :

  

F muss die Anforderungen von Callable und CopyConstructible

erfüllen

Dabei ist F der Funktionstyp, der zum Erstellen von std::function verwendet wird. % Co_de% ist jedoch nicht kopierbar . Daher ist std::packaged_task in der Erfassungsliste nicht kopierbar und ist ein nicht-statisches Mitglied von Lambda, wodurch der implizite Kopierkonstruktor für das Lambda gelöscht wird.

    
James Root 06.06.2017, 08:04
quelle
2

Kurze Antwort: Lambdas und std::packaged_task sind nicht std::function s.

Lange Antwort, Sie können ein std::packaged_task nicht in ein std::function

verschieben

Hier ist, was ich als Lösung anbiete:

%Vor%

Wenn Sie tatsächlich eine std :: -Funktion benötigen und nicht nur irgendeine aufrufbare, müssen Sie ein Lambda in ein std::function

binden     
David LUC 06.06.2017 07:56
quelle
0

Der Konstruktor von std::function benötigt das übergebene Funktionsobjekt als CopyConstructible , aber std::packaged_task<F> ist nicht (für F ). std::function führt -Typ löschen durch, wobei der dynamische Typ im statischen Typ nicht sichtbar ist. Betrachten Sie z.B.:

%Vor%

Der Aufruf von invoke erfordert das Kopieren von f (pass by value). % Co_de% ist jedoch kopierbar, wenn es aus f erstellt wurde, aber nicht kopierbar, wenn es aus l erstellt wurde, und dies hat nichts mit dem statischen Typ von p zu tun. Es gibt grundsätzlich drei Ansätze für dieses Problem:

  • Das Kopieren von f zur Kompilierzeit ist verboten.
  • Kopieren von std::function zur Kompilierzeit zulassen, aber einen Laufzeitfehler ausgeben, wenn der enthaltene Typ nicht kopierbar ist.
  • Kopieren Sie std::function zur Kompilierzeit und fordern Sie jedes Funktionsobjekt, das Sie kopieren, als kopierbar an.

Approach # 1 ist sehr restriktiv in Bezug darauf, wie Funktionen gespeichert, weitergegeben und geteilt werden können, und verbietet im Allgemeinen häufige Anwendungsfälle zugunsten des ungewöhnlichen Falls, ein nicht kopierbares Funktionsobjekt zu verwenden.

Approach # 2 ist problematisch, da die Benutzer darauf hingewiesen werden müssen, dass das Kopieren eines std::function in einigen Fällen fehlschlagen und beim Schreiben ihres Codes große Sorgfalt walten lassen kann. Wenn das Design Sharing-Funktionen erfordert, müssen sie möglicherweise in eine std::function eingebunden werden. Und wenn sie kopiert werden müssen und möglicherweise zustandsbehaftet sind, wird es noch schlimmer.

Egal, wie Sie den Ansatz # 3 betrachten, er ist standardisiert. Aber angesichts der oben genannten Probleme ist es auch leicht zu verteidigen.

Tatsächlich habe ich eine std::shared_ptr -Klassenvorlage geschrieben, die Ansatz Nr. 1 für mein aktuelles Projekt verwendet, weil für uns der Anwendungsfall des Speicherns nicht kopierbarer asynchroner Aufgabenobjekte ziemlich üblich ist und Kopieren oder Teilen von solchen Eine Aufgabe ist nicht notwendig.

    
Arne Vogel 06.06.2017 11:37
quelle

Tags und Links