Reputation: 5793
I am trying to achieve something like this but getting boost bind related errors
#include <map>
#include "boost/assign.hpp"
#include <boost/foreach.hpp>
#include <string>
#include <boost/function.hpp>
#include <boost/bind.hpp>
struct myStruct_t
{
int getInt () {return 1;};
};
int foo( myStruct_t* m, std::string str)
{
if(str == "A")
{
return m->getInt();
}
else if (str == "B")
{
return 2;
}
else
{
return 3;
}
}
typedef std::map<std::string, boost::function<int(myStruct_t*, std::string)> > Map_t;
Map_t myMap = boost::assign::map_list_of ("Jake", boost::bind((&foo, _1), "A")
("Ken", boost::bind((&foo, _1), "B")
("Pete", boost::bind((&foo, _1), "C");
int main ()
{
std::vector<std::string> myVal;
myVal.push_back("Jake");
myVal.push_back("Ken");
myVal.push_back("Pete");
myStruct_t myStruct;
BOOST_FOREACH( const std::string& aStr, myVal)
{
Map_t::const_iterator iter = myMap.find(aStr);
if(iter != myMap.end())
{
int myInt = (iter->second)(myStruct);
}
}
return 0;
}
The errors I am getting are
In file included from /usr/local/boost-1.60.0/include/boost/bind.hpp:22:0,
from prog.cc:6:
/usr/local/boost-1.60.0/include/boost/bind/bind.hpp: In instantiation of 'boost::_bi::result_traits<boost::_bi::unspecified, boost::arg<1> >':
/usr/local/boost-1.60.0/include/boost/bind/bind.hpp:1212:48: instantiated from 'boost::_bi::bind_t<boost::_bi::unspecified, boost::arg<1>, boost::_bi::list1<boost::_bi::value<const char*> > >'
prog.cc:32:81: instantiated from here
/usr/local/boost-1.60.0/include/boost/bind/bind.hpp:75:37: error: no type named 'result_type' in 'struct boost::arg<1>'
prog.cc:34:82: error: expected ')' before ';' token
prog.cc: In function 'int main()':
prog.cc:50:48: error: no match for call to '(const boost::function<int(myStruct_t*, std::basic_string<char>)>) (myStruct_t&)'
/usr/local/boost-1.60.0/include/boost/function/function_template.hpp:765:17: note: candidate is: result_type boost::function2<R, T1, T2>::operator()(T0, T1) const [with R = int, T0 = myStruct_t*, T1 = std::basic_string<char>, result_type = int]
It seems I am puzzled the way boost::bind is used. Can someone please help me doing it correctly? Many Thanks.
Upvotes: 1
Views: 857
Reputation: 69882
The function signature expected at the call site is int(myStruct*)
because of this line (I added the & to remove a logic error):
int myInt = (iter->second)(&myStruct);
in which case the declaration of the map should be:
typedef std::map<std::string, boost::function<int(myStruct_t*)> > Map_t;
Map_t myMap = boost::assign::map_list_of
("Jake", boost::bind(&foo, boost::placeholders::_1, std::string("A")))
("Ken", boost::bind(&foo, boost::placeholders::_1, std::string("B")))
("Pete", boost::bind(&foo, boost::placeholders::_1, std::string("C")));
And then you're good to go.
explanation:
boost[std]::bind returns a function object which is designed to accept only the parameters that are mentioned as placeholders in the bind
expression.
This means that the function that is finally called will often have more arguments than the function object returned by bind
so in your case, foo
has the following signature:
int foo( myStruct_t* m, std::string str)
i.e. takes two arguments and returns an int.
However at the point of the call to bind
:
boost::bind(&foo, boost::placeholders::_1, std::string("A"))
What we're saying is "capture the function foo
and the second argument (a string). Return me a function object that requires one argument (_1
) and forward that argument as the first argument to foo
while passing the bound string as the second argument.
so given:
auto f = boost::bind(&foo, boost::placeholders::_1, std::string("A"));
f
has the signature int f(MyStruct*)
and when called with
auto i = f(&mystruct);
it is equivalent to calling:
auto i = foo(&mystruct, std::string("A"));
Upvotes: 2