2010-05-26 6 views
4

Pourquoi ne compilera-t-il pas?fonctionnel, bind1st et mem_fun

#include <functional> 
#include <boost/function.hpp> 

class A { 
    A() { 
     typedef boost::function<void()> FunctionCall; 
     FunctionCall f = std::bind1st(std::mem_fun(&A::process), this); 
    } 
    void process() {} 
}; 

Erreurs:

In file included from /opt/local/include/gcc44/c++/bits/stl_function.h:712, 
       from /opt/local/include/gcc44/c++/functional:50, 
       from a.cc:1: 
/opt/local/include/gcc44/c++/backward/binders.h: In instantiation of 'std::binder1st<std::mem_fun_t<void, A> >': 
a.cc:7: instantiated from here 
/opt/local/include/gcc44/c++/backward/binders.h:100: error: no type named 'second_argument_type' in 'class std::mem_fun_t<void, A>' 
/opt/local/include/gcc44/c++/backward/binders.h:103: error: no type named 'first_argument_type' in 'class std::mem_fun_t<void, A>' 
/opt/local/include/gcc44/c++/backward/binders.h:106: error: no type named 'first_argument_type' in 'class std::mem_fun_t<void, A>' 
/opt/local/include/gcc44/c++/backward/binders.h:111: error: no type named 'second_argument_type' in 'class std::mem_fun_t<void, A>' 
/opt/local/include/gcc44/c++/backward/binders.h:117: error: no type named 'second_argument_type' in 'class std::mem_fun_t<void, A>' 
/opt/local/include/gcc44/c++/backward/binders.h: In function 'std::binder1st<_Operation> std::bind1st(const _Operation&, const _Tp&) [with _Operation = std::mem_fun_t<void, A>, _Tp = A*]': 
a.cc:7: instantiated from here 
/opt/local/include/gcc44/c++/backward/binders.h:126: error: no type named 'first_argument_type' in 'class std::mem_fun_t<void, A>' 
In file included from /opt/local/include/boost/function/detail/maybe_include.hpp:13, 
       from /opt/local/include/boost/function/detail/function_iterate.hpp:14, 
       from /opt/local/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:47, 
       from /opt/local/include/boost/function.hpp:64, 
       from a.cc:2: 
/opt/local/include/boost/function/function_template.hpp: In static member function 'static void boost::detail::function::void_function_obj_invoker0<FunctionObj, R>::invoke(boost::detail::function::function_buffer&) [with FunctionObj = std::binder1st<std::mem_fun_t<void, A> >, R = void]': 
/opt/local/include/boost/function/function_template.hpp:913: instantiated from 'void boost::function0<R>::assign_to(Functor) [with Functor = std::binder1st<std::mem_fun_t<void, A> >, R = void]' 
/opt/local/include/boost/function/function_template.hpp:722: instantiated from 'boost::function0<R>::function0(Functor, typename boost::enable_if_c<boost::type_traits::ice_not::value, int>::type) [with Functor = std::binder1st<std::mem_fun_t<void, A> >, R = void]' 
/opt/local/include/boost/function/function_template.hpp:1064: instantiated from 'boost::function<R()>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not::value, int>::type) [with Functor = std::binder1st<std::mem_fun_t<void, A> >, R = void]' 
a.cc:7: instantiated from here 
/opt/local/include/boost/function/function_template.hpp:153: error: no match for call to '(std::binder1st<std::mem_fun_t<void, A> >)()' 

Répondre

7

Parce que bind1st nécessite un objet fonction binaire. Cependant, vous passez un objet fonction unaire. Les classeurs d'objets de fonction de C++ 03 ne sont pas aussi sophistiqués que ceux trouvés dans boost ou tr1. En effet, ils souffrent de problèmes de base comme ne pas pouvoir gérer les fonctions avec des paramètres de référence.

Puisque vous utilisez déjà boost, je vous recommande d'utiliser boost::bind

FunctionCall f = boost::bind(&A::process, this); // yay! 
+0

Yay en effet. Je vous remercie. –

+0

puis-je pas faire boost :: bind (& (decltype (* this) :: process), this)? Je veux mettre cela dans une macro. –

+1

@Neil seul le brouillon le plus récent permettait d'utiliser 'decltype' comme spécificateur de nom imbriqué (la chose avant' :: '. Aussi, vous devrez supprimer la référence du type, tho). Je pense que la version actuelle de GCC ne peut pas encore le supporter. Dans ce cas, essayez de le contourner en disant '& remove_reference :: type :: process' à la place pour y accéder. –

Questions connexes