如何将带参数的boost::bind绑定类方法转换为函数指针?
问题:将带参数的类方法绑定为函数指针(基于Boost.Bind)
已实现无参数类方法到函数指针的绑定,代码如下:
#include <boost/optional.hpp> #include <boost/bind.hpp> #include <iostream> #include <ostream> using namespace std; template<unsigned ID,typename Functor> boost::optional<Functor> &get_local() { static boost::optional<Functor> local; return local; } template<unsigned ID,typename Functor> typename Functor::result_type wrapper() { return get_local<ID,Functor>().get()(); } template<typename ReturnType> struct Func { typedef ReturnType (*type)(); }; template<unsigned ID,typename Functor> typename Func<typename Functor::result_type>::type get_wrapper(Functor f) { (get_local<ID,Functor>()) = f; return wrapper<ID,Functor>; } // ---------------------------------------------------------------------- void test(void (*fptr)()) { fptr(); } struct SomeStruct { int data; void some_method() { cout << data << endl; } void another_method() { cout << -data << endl; } }; int main() { SomeStruct local[] = { {11} }; test(get_wrapper<0>( boost::bind(&SomeStruct::some_method,local[0]) )); test(get_wrapper<1>( boost::bind(&SomeStruct::another_method,local[0]) )); }
尝试扩展为支持带参数和返回值的场景时编译失败,修改后的代码及错误如下:
修改后的代码
#include <boost/optional.hpp> #include <boost/bind.hpp> #include <iostream> #include <ostream> using namespace std; template<unsigned ID,typename Functor> boost::optional<Functor> &get_local() { static boost::optional<Functor> local; return local; } template<unsigned ID,typename Functor> typename Functor::result_type wrapper() { return get_local<ID,Functor>().get()(); } template<typename ReturnType> struct Func { typedef ReturnType (*type)(); }; template<unsigned ID,typename Functor> typename Func<typename Functor::result_type>::type get_wrapper(Functor f) { (get_local<ID,Functor>()) = f; return wrapper<ID,Functor>; } // ---------------------------------------------------------------------- void test(void (*fptr)(int )) { fptr(5); } struct SomeStruct { int data; void some_method(int x) { cout << data + x << endl; } }; int main() { SomeStruct local[] = { {11} }; test(get_wrapper<0>( boost::bind(&SomeStruct::some_method,local[0], boost::placeholders::_1) )); }
核心错误
error: invalid conversion from 'Func<void>::type' {aka 'void (*)()'} to 'void (*)(int)' [-fpermissive] test(get_wrapper<0>( boost::bind(&SomeStruct::some_method,local[0], boost::placeholders::_1) )); | ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | Func<void>::type {aka void (*)()}
错误原因
原代码的wrapper函数仅支持无参数调用,Func结构体也只定义了无参数的函数指针类型。当绑定带参数的类方法时,get_wrapper返回的仍然是无参数函数指针,无法匹配test函数要求的void (*)(int)类型。
解决方案
通过模板参数包扩展wrapper、Func和get_wrapper,使其支持任意数量和类型的参数:
修改后的完整代码
#include <boost/optional.hpp> #include <boost/bind.hpp> #include <iostream> #include <ostream> #include <utility> // 用于std::forward using namespace std; // 保存绑定的functor的静态存储 template<unsigned ID, typename Functor> boost::optional<Functor>& get_local() { static boost::optional<Functor> local; return local; } // 带参数转发的wrapper函数,支持任意参数 template<unsigned ID, typename Functor, typename... Args> typename Functor::result_type wrapper(Args&&... args) { return get_local<ID, Functor>().get()(forward<Args>(args)...); } // 定义带参数的函数指针类型 template<typename ReturnType, typename... Args> struct Func { typedef ReturnType (*type)(Args...); }; // 自动推导参数类型,返回匹配的函数指针 template<unsigned ID, typename Functor, typename... Args> typename Func<typename Functor::result_type, Args...>::type get_wrapper(Functor f) { get_local<ID, Functor>() = f; return &wrapper<ID, Functor, Args...>; } // ---------------------------------------------------------------------- // 测试用函数:带int参数 void test(void (*fptr)(int)) { fptr(5); } // 另一个测试:带返回值和多参数 int test_ret(int (*fptr)(int, string)) { return fptr(10, "hello"); } struct SomeStruct { int data; void some_method(int x) { cout << data + x << endl; } int calc(int base, string msg) { cout << msg << endl; return data + base; } }; int main() { SomeStruct local[] = { {11} }; // 绑定带单个参数的方法 test(get_wrapper<0, decltype(boost::bind(&SomeStruct::some_method, local[0], _1)), int>( boost::bind(&SomeStruct::some_method, local[0], _1) )); // 绑定带返回值和多参数的方法 int res = test_ret(get_wrapper<1, decltype(boost::bind(&SomeStruct::calc, local[0], _1, _2)), int, string>( boost::bind(&SomeStruct::calc, local[0], _1, _2) )); cout << "calc result: " << res << endl; }
关键修改说明
wrapper函数:新增模板参数包Args...,使用std::forward转发参数给绑定的functor,支持任意参数调用。Func结构体:扩展为接收返回值类型和参数列表,生成对应的函数指针类型ReturnType (*)(Args...)。get_wrapper函数:新增参数包模板参数,返回匹配参数列表的函数指针,调用时需显式声明参数类型以帮助编译器推导正确的函数指针类型。
内容的提问来源于stack exchange,提问作者RoQuOTriX
相关产品推荐
相关产品推荐

