如何制作一个模板函数,该函数采用 boost::bind 结果的参数?
How can I make a templated function that takes a parameter that is the result of boost::bind?
我有一个辅助方法,它将一个 boost::function<>
类型的对象作为输入,并用另一个处理其他物流的仿函数包装该函数。
我的签名是这样的:
class Example {
public:
typedef ... Callback;
...
template<typename T>
static Callback make_wrapper( const boost::function<void( T )>& );
};
如果我尝试传递 make_wrapper 内联调用 boost::bind
的结果,我会收到有关类型不兼容的编译错误(Apple LLVM 版本 7.3.0)
class OtherClass {
public:
void method ( uint32_t );
};
OtherClass* other;
Example::Callback c = Example::make_wrapper ( boost::bind( &OtherClass::method, other, _1 ) );
这给出:
error: no matching function for call to 'make_wrapper'
note: candidate template ignored: could not match 'function' against 'bind_t'
我找到了两种解决方法:
临时变量:
boost::function<void( uint32_t )> f = boost::bind( &OtherClass::method, other, _1 );
Example::Callback c = Example::make_wrapper ( f );
调用make_wrapper的具体特化:
Example::Callback c = Example::make_wrapper<uint32_t> ( boost::bind( &OtherClass::method, other, _1 ) );
如果我可以跳过额外的提示并通过内联调用绑定来调用 make_wrapper,我会更喜欢它。
有没有一种方法可以声明 make_wrapper 模板的签名以帮助编译器确定类型,而无需使用上述解决方法之一?
两个 std::bind
and boost::bind
都将 return 类型列为未指定。这意味着你根本不知道,如果你想完全便携。
无论何时使用 bind
,都会丢弃有关绑定函数参数类型的所有信息。函数模板不可能推断出参数类型 T
,因为 bind
的 return 值是一个函数对象,可以使用任意数量的任意类型的参数调用。
您可以将 bind
函数包装到辅助函数模板中以推导出绑定的成员函数,尤其是它的结果类型和参数(示例使用 std::bind
和 std::function
但我相信可以轻松转换为boost
):
#include <iostream>
#include <string>
#include <functional>
struct foo {
void bar(int a, std::string s) {
std::cout << a << " " << s << std::endl;
}
};
template<typename T1, typename T2>
void make_wrapper(const std::function<void( T1, T2 )>&) {
}
template <class Foo, class Res, class... Args, class... Placeholders>
std::function<Res(Args...)> my_bind(Res (Foo::*bar)(Args...), Foo& f, Placeholders... ps) {
return std::bind(bar, f, ps...);
}
int main() {
foo f;
make_wrapper(my_bind(&foo::bar, f, std::placeholders::_1, std::placeholders::_2));
}
只要 foo::bar
没有超载,代码就可以正常工作,在这种情况下,您无法避免 static_cast
。
我有一个辅助方法,它将一个 boost::function<>
类型的对象作为输入,并用另一个处理其他物流的仿函数包装该函数。
我的签名是这样的:
class Example {
public:
typedef ... Callback;
...
template<typename T>
static Callback make_wrapper( const boost::function<void( T )>& );
};
如果我尝试传递 make_wrapper 内联调用 boost::bind
的结果,我会收到有关类型不兼容的编译错误(Apple LLVM 版本 7.3.0)
class OtherClass {
public:
void method ( uint32_t );
};
OtherClass* other;
Example::Callback c = Example::make_wrapper ( boost::bind( &OtherClass::method, other, _1 ) );
这给出:
error: no matching function for call to 'make_wrapper'
note: candidate template ignored: could not match 'function' against 'bind_t'
我找到了两种解决方法:
临时变量:
boost::function<void( uint32_t )> f = boost::bind( &OtherClass::method, other, _1 ); Example::Callback c = Example::make_wrapper ( f );
调用make_wrapper的具体特化:
Example::Callback c = Example::make_wrapper<uint32_t> ( boost::bind( &OtherClass::method, other, _1 ) );
如果我可以跳过额外的提示并通过内联调用绑定来调用 make_wrapper,我会更喜欢它。
有没有一种方法可以声明 make_wrapper 模板的签名以帮助编译器确定类型,而无需使用上述解决方法之一?
两个 std::bind
and boost::bind
都将 return 类型列为未指定。这意味着你根本不知道,如果你想完全便携。
无论何时使用 bind
,都会丢弃有关绑定函数参数类型的所有信息。函数模板不可能推断出参数类型 T
,因为 bind
的 return 值是一个函数对象,可以使用任意数量的任意类型的参数调用。
您可以将 bind
函数包装到辅助函数模板中以推导出绑定的成员函数,尤其是它的结果类型和参数(示例使用 std::bind
和 std::function
但我相信可以轻松转换为boost
):
#include <iostream>
#include <string>
#include <functional>
struct foo {
void bar(int a, std::string s) {
std::cout << a << " " << s << std::endl;
}
};
template<typename T1, typename T2>
void make_wrapper(const std::function<void( T1, T2 )>&) {
}
template <class Foo, class Res, class... Args, class... Placeholders>
std::function<Res(Args...)> my_bind(Res (Foo::*bar)(Args...), Foo& f, Placeholders... ps) {
return std::bind(bar, f, ps...);
}
int main() {
foo f;
make_wrapper(my_bind(&foo::bar, f, std::placeholders::_1, std::placeholders::_2));
}
只要 foo::bar
没有超载,代码就可以正常工作,在这种情况下,您无法避免 static_cast
。