#include <functional>
#include <boost/bind.hpp>
class A
{
public:
A(){}
~A(){}
template<typename _Handler>
void call_handler(_Handler handler)
{
handler();
}
};
class B
{
public:
template<typename _Handler>
void call_handler(_Handler handler)
{
}
template<typename _Handler>
void run(_Handler handler)
{
m_a.call_handler(boost::bind(&B::call_handler<_Handler>, this, handler));
//only can use boost::bind here
}
A m_a;
};
class Test
{
public:
void handler()
{
}
};
int main()
{
B b;
Test t;
b.run(boost::bind(&Test::handler,&t));//only can use std::bind here
}
这是我上面的小测试代码。
我很困惑,我只能按特定顺序使用bind ...请参阅上面的注释
如果我将std :: bind更改为boost :: bind,则编译器失败,反之亦然。
测试:
gcc 4.9.2 for cygwin with option:
g ++ -std = c ++ 11 -fdiagnostics-color = always -fdiagnostics-show-location = every-line -I&#34; / cygdrive / e / opensource libs / boost&#34; main.cpp中
msvc 12.0(visual studio 2013 with update4),默认选项。
gcc诊断消息:
包含在/ cygdrive / e / opensource中的文件 库/升压/升压/ bind.hpp:22:0, 来自main.cpp:3:/ cygdrive / e / opensource libs / boost / boost / bind / bind.hpp:在'void的实例化中 boost :: _ bi :: list2 :: operator()(boost :: _ bi :: type,F&amp;,A&amp ;,, int)[与F = boost :: _ mfi :: mf1, boost :: _ bi :: list1&gt; &GT;取代; A = 提高:: _双::列表0; A1 = boost :: _ bi :: value; A2 = 提高:: _双:: bind_t, boost :: _ bi :: list1&gt; &GT;]”: / cygdrive / e / opensource libs / boost / boost / bind / bind.hpp:893:50:
'boost :: _ bi :: bind_t :: result_type需要 boost :: _ bi :: bind_t :: operator()()[with R = void; F = 提高:: _ MFI :: MF1, boost :: _ bi :: list1&gt; &GT;取代; L = boost :: _ bi :: list2,boost :: _ bi :: bind_t, boost :: _ bi :: list1&gt; &GT;取代; boost :: _ bi :: bind_t :: result_type = void]'main.cpp:12:11:
'void A :: call_handler(_Handler)[需要_Handler = 提高:: _双:: bind_t, boost :: _ bi :: list1&gt; &GT; &gt;中 boost :: _ bi :: list2,boost :: _ bi :: bind_t, boost :: _ bi :: list1&gt; &GT; &GT; &gt;]'main.cpp:27:3:
从'void B :: run(_Handler)[与_Handler = 提高:: _双:: bind_t, boost :: _ bi :: list1&gt; &gt;]'main.cpp:44:38:
从这里需要/ cygdrive / e / opensource libs / boost / boost / bind / bind.hpp:313:34:错误:无效使用void 表达 unwrapper :: unwrap(f,0)(a [base_type :: a1_],[base_type :: a2_]); ^
msvc 12.0诊断消息:
1&gt; ------ Build build:Project:scince_x32,Configuration:Debug Win32 ------ 1&gt; main.cpp 1&gt; e:\ opensource libs \ boost \ boost \ bind \ bind.hpp(313):错误C2664:&#39; void boost :: _ mfi :: mf1 :: operator()(T *,A1)const&#39; :不能 转换参数2来自&#39; void&#39;至 &#39;升压:: _双向:: bind_t,升压:: _双向:: list1的&GT;&GT;&#39; 1 GT;用1> [1> _Handler =升压:: _双向:: bind_t,升压:: _双向:: list1的&GT;&GT; 1 GT; ,T = B 1> ,A1 = boost :: _ bi :: bind_t,boost :: _ bi :: list1&gt;&gt; 1 GT; ] 1&gt;和1> [1> T =测试* 1> ] 1&gt;类型void的表达式不能 转换为其他类型1&gt; E:\开源 libs \ boost \ boost \ bind \ bind.hpp(893):参见函数参考 模板实例化&#39; void 提高:: _双::列表2,提高:: _双:: bind_t,提振:: _双::列表1&GT;&GT;&GT; ::运算 ()(boost :: _ bi :: type,F&amp;,A&amp;,int)&#39;存在 编译1&gt;用1> [1> T = B * 1> ,
F =升压:: _ MFI :: MF1,升压:: _双向:: list1的&GT;&GT;&GT; 1 GT; ,A = boost :: _ bi :: list0 1&gt; ] 1&gt; e:\ opensource libs \ boost \ boost \ bind \ bind.hpp(893):参见参考资料 功能模板实例化&#39; void 提高:: _双::列表2,提高:: _双:: bind_t,提振:: _双::列表1&GT;&GT;&GT; ::运算 ()(boost :: _ bi :: type,F&amp;,A&amp;,int)&#39;存在 编译1&gt;用1> [1> T = B * 1> ,
F =升压:: _ MFI :: MF1,升压:: _双向:: list1的&GT;&GT;&GT; 1 GT; ,A = boost :: _ bi :: list0 1&gt; ] 1&gt; e:\ opensource libs \ boost \ boost \ bind \ bind.hpp(891):编译时 类模板成员函数&#39; void 升压:: _双向:: bind_t,升压:: _双向:: list2中,升压:: _双向:: bind_t,升压:: _双向:: list1的&GT;&GT;&GT;&GT; ::运算 ()(无效)&#39; 1 GT;用1> [1> _Handler =升压:: _双向:: bind_t,升压:: _双向:: list1的&GT;&GT; 1 GT; ,T = B * 1> ] 1&gt; e:\ c ++ program \ scince_x32 \ scince_x32 \ main.cpp(12):参见参考资料 功能模板实例化&#39; void 升压:: _双向:: bind_t,升压:: _双向:: list2中,升压:: _双向:: bind_t,升压:: _双向:: list1的&GT;&GT;&GT;&GT; ::运算 ()(无效)&#39;正在编译1&gt;用1> [1> _Handler =升压:: _双向:: bind_t,升压:: _双向:: list1的&GT;&GT; 1 GT; ,T = B * 1> ] 1&gt; e:\ c ++ program \ scince_x32 \ scince_x32 \ main.cpp(27):参见参考资料 类模板实例化 &#39;升压:: _双向:: bind_t,升压:: _双向:: list2中,升压:: _双向:: bind_t,升压:: _双向:: list1的&GT;&GT;&GT;&GT;&#39; 正在编译1&gt;用1> [1> _Handler =升压:: _双向:: bind_t,升压:: _双向:: list1的&GT;&GT; 1 GT; ,T = B * 1> ] 1&gt; e:\ c ++ program \ scince_x32 \ scince_x32 \ main.cpp(44):参见参考资料 功能模板实例化&#39; void B ::运行,提高:: _双向:: list1的&GT;&GT;&GT;(_处理程序)&#39; 正在编译1&gt;用1> [1> T =测试* 1 GT; ,
_Handler =升压:: _双向:: bind_t,升压:: _双向:: list1的&GT;&GT; 1 GT; ] ==========构建:0成功,1个失败,0个最新,0个跳过==========
答案 0 :(得分:2)
你(间接)绑定一个绑定表达式作为参数绑定另一个绑定表达式。
在Boost和标准库中,您需要保护内部绑定表达式,以便占位符/绑定不会混合和冲突。
所以它将从
开始m_a.call_handler(boost::bind(&B::call_handler<_Handler>, this, boost::protect(handler)));
除此之外,protect(handler)
包装了该类型且不再_Handler
,因此您需要&B::call_handler<???>
的其他内容。根据我的经验,迄今为止最简单的方法是使用多态函数对象:
struct handler_caller_f {
typedef void result_type;
template <typename H> void operator()(B* /*this_*/, H/* handler*/) const {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
template <typename H> void run(H handler) {
m_a.call_handler(boost::bind(handler_caller_f(), this, boost::protect(handler)););
}
正如您所看到的,函数对象替换了B::call_handler
,并通过再次推断处理程序的类型来解决问题。
这是一个清理过的版本:
<强> Live On Coliru 强>
#include <boost/bind.hpp>
#include <boost/bind/protect.hpp>
#include <iostream>
struct A {
template <typename H> void call_handler(H handler) {
handler();
}
};
struct B {
struct handler_caller_f {
typedef void result_type;
template <typename H> void operator()(B* this_, H handler) const {
handler();
}
};
template <typename H> void run(H handler) {
m_a.call_handler(boost::bind(handler_caller_f(), this, boost::protect(handler)));
}
A m_a;
};
struct Test {
void handler() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
};
int main() {
Test t;
B b;
b.run(boost::bind(&Test::handler, &t));
}
打印
void Test::handler()
std::bind
标准图书馆没有protect
,但很容易添加:
<强> Live On Coliru 强>
#include <functional>
#include <iostream>
namespace std_ex { // http://stackoverflow.com/questions/18519087/why-is-there-no-stdprotect
template <typename T> struct protect_wrapper : T {
protect_wrapper(const T &t) : T(t) {}
protect_wrapper(T &&t) : T(std::move(t)) {}
};
template <typename T>
typename std::enable_if<!std::is_bind_expression<typename std::decay<T>::type>::value, T && >::type protect(T &&t) {
return std::forward<T>(t);
}
template <typename T>
typename std::enable_if<std::is_bind_expression<typename std::decay<T>::type>::value,
protect_wrapper<typename std::decay<T>::type> >::type
protect(T &&t) {
return protect_wrapper<typename std::decay<T>::type>(std::forward<T>(t));
}
}
struct A {
template <typename H> void call_handler(H handler) { handler(); }
};
struct B {
struct handler_caller_f {
typedef void result_type;
template <typename H> void operator()(B *this_, H handler) const { handler(); }
};
template <typename H> void run(H handler) {
m_a.call_handler(std::bind(handler_caller_f(), this, std_ex::protect(handler)));
}
A m_a;
};
struct Test {
void handler() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
};
int main() {
Test t;
B b;
b.run(std::bind(&Test::handler, &t));
}