2010-05-14 24 views
10

Certains objets C++ n'ont pas de constructeur de copie, mais ont un constructeur de déplacement. Par exemple, boost :: promise. Comment puis-je lier ces objets en utilisant leurs constructeurs de déplacement?Comment utiliser boost :: bind avec des paramètres non-copiables, par exemple 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

utilisant un pointeur est pas bizarre, cela dépend de ce que vous donnez les objets se lient à. Par exemple, si vous utilisez des signaux, vous pouvez enregistrer l'objet Connection et appeler la déconnexion dans le dteur de l'objet. Si vous n'utilisez pas de signaux, vous pouvez développer quelque chose de similaire ou placer le pointeur dans un shared_ptr. – Kyle

+0

boost :: promet, en fait, est un shared_ptr et un bool. Il semble étrange qu'il devrait être alloué sur tas et être suivi avec un plus shared_ptr. – user222202

Répondre

4

Je ne suis pas sûr de savoir comment utiliser un constructeur de déplacement au lieu, mais une autre approche est d'utiliser boost :: ref qui crée des références à des objets copiables, et vous pouvez alors passer ceux en boost :: bind.

+0

Est-ce que boost :: ref ne marche que tant que l'objet référencé est en live? –

+0

Oui, vous devez donc vous soucier de la durée de vie des objets avec lesquels vous travaillez. – swestrup

5

Je vois que vous utilisez std :: move. Pourquoi n'utilisez-vous pas std :: bind qui devrait être conscient de la sémantique de déplacement?

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

Wht sur la déclaration d'une version de déplacement de fullfil_1

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

Boost.Bind ne pas déplacer encore la sémantique des supports (au moins je ne suis pas au courant). J'espère que le Boost.Move actuellement examiné sera accepté, et que Boost.Bind, Boost.Lambda et Boost.Phoenix ajouteront les interfaces sémantiques de déplacement.

Vous pouvez composer ref et se déplacer comme suit

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