2010-05-14 12 views
10

Einige C++ - Objekte haben keinen Kopierkonstruktor, aber einen Move-Konstruktor. Zum Beispiel boost :: promise. Wie kann ich diese Objekte mit ihren Move-Konstruktoren binden?Wie boost :: bind mit nicht kopierbaren Parametern, zB boost :: promise?

#include <boost/thread.hpp> 

void fullfil_1(boost::promise<int>& prom, int x) 
{ 
    prom.set_value(x); 
} 

boost::function<void()> get_functor() 
{ 
    // boost::promise is not copyable, but movable 
    boost::promise<int> pi; 

    // compilation error 
    boost::function<void()> f_set_one = boost::bind(&fullfil_1, pi, 1); 

    // compilation error as well 
    boost::function<void()> f_set_one = boost::bind(&fullfil_1, std::move(pi), 1); 

    // PS. I know, it is possible to bind a pointer to the object instead of 
    // the object itself. But it is weird solution, in this case I will have 
    // to take cake about lifetime of the object instead of delegating that to 
    // boost::bind (by moving object into boost::function object) 
    // 
    // weird: pi will be destroyed on leaving the scope 
    boost::function<void()> f_set_one = boost::bind(&fullfil_1, boost::ref(pi), 1); 
    return f_set_one; 
} 
+0

folgen ein Zeiger verwenden das nicht seltsam, es hängt davon ab, was Sie die bind Objekte geben zu. Wenn Sie beispielsweise Signale verwenden, können Sie das Verbindungsobjekt speichern und die Verbindungstrennung im dtor des Objekts aufrufen. Wenn Sie keine Signale verwenden, können Sie etwas Ähnliches entwickeln oder den Zeiger in einem shared_ptr umbrechen. – Kyle

+0

Boost :: Versprechen, ist eigentlich ein shared_ptr und ein bool. Es scheint seltsam, dass es auf Heap zugeordnet werden sollte und mit einem weiteren shared_ptr verfolgt werden. – user222202

Antwort

4

Ich bin mir nicht sicher, wie stattdessen einen Zug Konstruktor zu verwenden, aber ein anderer Ansatz ist boost :: ref zu verwenden, die kopierbar Verweise auf Objekte erstellt, und Sie können dann diejenigen in boost :: bind passieren.

+0

Funktioniert boost :: ref nur so lange, wie das Objekt, auf das verwiesen wird, existiert? –

+0

Ja, Sie müssen sich also Gedanken über die Lebensdauer der Objekte machen, mit denen Sie arbeiten. – swestrup

5

Ich sehe, dass Sie std :: move verwenden. Warum verwenden Sie nicht std :: bind, das die Bewegungssemantik beachten sollte?

template<class F, class... BoundArgs> 
unspecified bind(F&&, BoundArgs&&...); 
template<class R, class F, class... BoundArgs> 
unspecified bind(F&&, BoundArgs&&...); 

Wht eine Bewegung Version von fullfil_1

void fullfil_1(boost::promise<int>&é prom, int x) 
{ 
    prom.set_value(x); 
} 

Boost.Bind nicht unterstützt bewegen Semantik noch (zumindest ich bin mir nicht bewusst) zu erklären. Ich hoffe, dass der aktuell überarbeitete Boost.Move akzeptiert wird, und dass Boost.Bind, Boost.Lambda und Boost.Phoenix die move semantics interfaces hinzufügen werden.

können Sie versuchen, ref Komponieren und bewegen, wie

boost::function<void()> f_set_one = boost::bind(&fullfil_1, boost::ref(std::move(pi)), 1);