Skip to main content
gamedev.net
🔒 Locked

boost function and bind

Started by Dragon_Strike 3 replies 1.4k views
Original Post
Dragon_Strike
Dragon_Strike
im having some problems with boost bind and function...

template <class FunctionType>
class Handler
{
 //typedef boost::function<void (UINT , WPARAM , LPARAM , Window*)> FunctionType;
public:
 Handler() {}
  virtual ~Handler() {}


  template<class T>
  void Bind(UINT msg, FunctionType r,T* t)
  {
     associations_.insert(AssocMap::value_type(msg, boost::bind(r, t, _1, _2, _3, _4)));
  }

  bool Unbind(UINT msg)
  {
    associations_.erase(msg);
  }

  void HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, Window* pWindow)
  {
    BOOST_FOREACH(AssocMap::value_type p, associations_)
    {
      if((p.first) == uMsg || uMsg == 0)
         (p.second)(uMsg, wParam, lParam, pWindow);    
    } 

  }

private:
   typedef std::map<UINT, FunctionType> AssocMap;
   AssocMap associations_;
};

the problem is in the Bind function: this is what id like... template<class T> void Bind(UINT msg, FunctionType r,T* t) { associations_.insert(AssocMap::value_type(msg, boost::bind(r, t, _1, _2, _3, _4))); } Error 1 error C2064: term does not evaluate to a function taking 4 arguments c:\program\boost\boost_1_34_1\boost\function\function_template.hpp 155 Drone this is what works... template<class T> void Bind(UINT msg, void (T::*r)(UINT, WPARAM, LPARAM, Window*),T* t) { associations_.insert(AssocMap::value_type(msg, boost::bind(r, t, _1, _2, _3, _4))); } why cant i use boost::function in this case?
chairthrower
chairthrower
I think that there is something a bit wrong in the design. You are abstracting the method type (FunctionTYpe) as a generic type of the class Handler which implies that it can only ever work with one particular class/object type which i am guessing is not what you want.

Remember that a method pointer (which is the first argument in your bind) encodes both the method signature and the object to which the method will apply. The advantage of using bind and boost::function is that you 'type erase' this information so that you can use it with *any* valid method of any corresponding type.

I would remove the template abstraction on the Handler class but instead make the type of the method generic as well in the Bind function.

// template <class FunctionType> remove this
class Handler

and then use

template<class Method, class Object>
void Bind(UINT msg, Method m, Object o)
{
associations_.insert(AssocMap::value_type(msg, boost::bind(m, o, _1, _2, _3, _4)));
}

then you should be able to associate any msg with any method of any object that has the standard windows wparam lparam signature.

hope its clear - its a bit difficult to exaplain and i hope that havent missed something else. I have a handler type thing which i use which is similar to the approach i have outlined.

<edit for clarity - sorry i never get it right first time>
Dragon_Strike
Dragon_Strike
thx for the answer... the way u suggest it will only work with "any object that has the standard windows wparam lparam signature"... but id like to make the class generic so that i can specify how many parameters the function will take when creating the class...

it seems this part disapered at the end...


typedef boost::function<void (UINT , WPARAM , LPARAM , Window*)> MessageFunction;
typedef Handler<MessageFunction> MessageHandler;
typedef boost::shared_ptr<MessageHandler> MessageHandlerPtr;
chairthrower
chairthrower
Yes ok i understand the point - the difficulty is that you cant easily factor out the number of arguments which require the placeholders _1 and _2 etc to be made explicit in the bind. In fact you can do this with partial template specialisation and type_traits but it gets really gnarly really quickly.

if you do want to go down that route you need to look at function_traits< S>::result_type and arg1_type and arity and then specialise the instances according to the number of unbound placeholders.
Dragon_Strike
Dragon_Strike
why does

template<class Object>
void Bind(UINT msg, void (Object::*m)(UINT, WPARAM, LPARAM, Window*),Object* o)
{
associations_.insert(AssocMap::value_type(msg, boost::bind(m, o, _1, _2, _3, _4)));
}

work

but not the following?

template<class Method, class Object>
void Bind(UINT msg, Method m,Object o)
{
associations_.insert(AssocMap::value_type(msg, boost::bind(m, o, _1, _2, _3, _4)));
}

Error 1 error C2914: 'drone::win32::Handler<FunctionType>::Bind' : cannot deduce template argument as function argument is ambiguous c:\documents and settings\administratör\mina dokument\visual studio 2008\projects\drone\drone\win32application.cpp 17 Drone


shouldnt the compiler to decide automaticly what the template params are when called?

msgHandler_->Bind(WM_SYSKEYDOWN, &Application::onKeyboard, this);

EDIT:: typos

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.