如何使用boost :: bind正确使用函数指针的映射

时间:2016-05-11 11:59:53

标签: c++ dictionary boost bind function-pointers

我正在努力实现类似这样的东西,但却得到了与绑定相关的错误

#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;
}

我得到的错误是

   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]

似乎我对boost :: bind的使用方式感到困惑。有人可以帮我正确地做吗?非常感谢。

1 个答案:

答案 0 :(得分:2)

调用站点预期的函数签名是int(myStruct *)

因为这一行(我添加了&amp;来删除逻辑错误):

int myInt = (iter->second)(&myStruct);

在这种情况下,地图的声明应该是:

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")));

然后你很高兴去。

说明:

boost [std] :: bind返回一个函数对象,该对象仅用于接受bind表达式中作为占位符提及的参数。

这意味着最终调用的函数通常会有比bind返回的函数对象更多的参数

因此,在您的情况下,foo具有以下签名:

int foo(  myStruct_t* m, std::string str)

即。接受两个参数并返回一个int。

然而,在致电bind

boost::bind(&foo, boost::placeholders::_1, std::string("A"))

我们所说的是&#34;捕获函数foo和第二个参数(字符串)。返回一个需要一个参数(_1)的函数对象,并将该参数作为foo的第一个参数转发,同时将绑定字符串作为第二个参数传递。

所以给出:

auto f = boost::bind(&foo, boost::placeholders::_1, std::string("A"));

f具有签名int f(MyStruct*)

并在使用

进行调用时
auto i = f(&mystruct);

它相当于调用:

auto i = foo(&mystruct, std::string("A"));