Binding Funktionen mit unique_ptr Argumente zu std :: functionvoid ()

8

Ich versuche, den folgenden Code funktionieren zu lassen:

%Vor%

Der Aufruf von f () an Foo :: f2 (der letzte Parameter ist ein roher Zeiger) funktioniert gut, aber die Bindung an foo :: f1 verursacht einen Kompilierungsfehler:

%Vor%

Was mache ich falsch?

Ich verwende gcc 4.8.2 und -std = c ++ 0x (-std = c ++ 11 scheitert auch) flags.

Danke

    
rogerzanoni 28.11.2013, 14:21
quelle

3 Antworten

8

Die Probleme mit Bind, die in den anderen Antworten beschrieben werden (zum Zeitpunkt des Schreibens), sind nicht das, worüber sich der Compiler in der Frage beschwert. Das Problem ist, dass std::function CopyConstructible sein muss, was erfordert, dass sein Argument (das von der Funktion gespeichert wird) auch CopyConstructible ist.

Aus der Standardfunktion [20.9.11.2 Klassenvorlage]

%Vor%
  

Benötigt: F soll CopyConstructible sein. f soll Callable (20.9.11.2) für Argumenttypen ArgTypes und Rückgabetyp R sein. Der Kopierkonstruktor und der Destruktor von A dürfen keine Ausnahmen auslösen ...

Betrachten Sie dieses Beispiel, in dem nicht einmal bind enthalten ist:

%Vor%

Hier ist die Ausgabe von clang:

%Vor%

Beachten Sie, dass das resultierende Bindeobjekt nicht kopierbar ist, wenn Sie ein unique_ptr binden. Bind wird trotzdem noch kompiliert.

    
orm 30.06.2014 07:24
quelle
3

Hmm, es scheint wirklich, dass std :: bind Probleme mit r-Wert-Referenzen hat. Eine Alternative wäre die Verwendung einer Lambda-Funktion:

%Vor%

Damit dies funktioniert, müssen Sie auch die Signatur von f1 so ändern, dass sie unique_ptr als r-Wert-Referenz akzeptiert:

%Vor%

(Auch wenn std :: bind R-Wert-Referenzen verarbeiten könnte, müssten Sie dies trotzdem tun, weil std :: unique_ptr keinen Kopierkonstruktor hat, nur der Move-Konstruktor ist zugänglich!)

Beachten Sie jedoch, dass Ihr Konstrukt ziemlich gefährlich ist (auch wenn std :: bind funktionieren würde): Wenn Sie f () zweimal aufrufen, erhalten Sie eine Laufzeitausnahme.

    
craffael 30.11.2013 10:46
quelle
1

1) Der folgende Code wird nicht kompiliert

%Vor%

weil function erfordert, dass das Callable-Objekt copy-constructible ist, aber wenn bind ein nicht kopierbares Argument wie unique_ptr benötigt, wird der zurückgegebene Funktor nicht kopierbar sein, wie in anderen Antworten erwähnt.

2) Verwenden Sie also nicht function für bind . Der folgende Code wird jedoch nicht kompiliert

%Vor%

weil in Schritt (a) bind speichert, was Sie ihm als lvalue geben (außer für reference_wrapper ), und es an den internen Funktor in Schritt (b) übergibt. Daher ist es erforderlich, dass die gebundenen Argumente kopierbar sind, denn diese Parameter werden nach Wert übergeben, nicht nach Referenzen.

3) Versuchen Sie dann, den rohen Zeiger zu verwenden. Der folgende Code wird jedoch nicht kompiliert

%Vor%

Ein ähnlicher Grund wie (2), der Funktor speichert ein int* und versucht, es beim Aufruf in den Parametertyp unique_ptr<int> zu konvertieren. Aber der Konstruktor unique_ptr(pointer p) ist explicit .

Um es zu kompilieren, benötigen Sie eine Funktion wie diese

%Vor%

Beachten Sie, dass f mehrmals aufgerufen werden kann und die Parameter p auf dasselbe unique_ptr verweisen, das im zurückgegebenen Objekt von bind gespeichert ist.

    
neuront 31.07.2016 07:03
quelle

Tags und Links