我正在尝试为std :: bind编写一个包装器。我的第一次尝试是:
typedef std::function<void(float, int)> tCallback;
template<typename F, class... Args>
tCallback mybind(F f, Args... args)
{
return std::tr1::bind( f, Args... args,
std::tr1::placeholders::_1, std::tr1::placeholders::_2 );
}
给出类似的东西:
struct Foo {
tCallback m__cb;
setcb(tCallback cb) {m_cb = cb;}
....
};
void f1(float f, int i) {}
void f2(int j, float f, int i) {}
Foo foo;
foo.setcb( mybind( f1 ) ); // Fine.
foo.setcb( mybind( f2, 1 ) ); // Not fine.
我做错了什么?在Visual Studio上,错误是指以“int&amp;”开头的Args (这让我感到惊讶,但我可能会出现几层错误消息)。在GCC上,错误指的是“太多参数”。 (我并不天真地期待来自深度模板化代码的有用错误消息!)
我是否需要为函数指针和成员函数指针编写mybind版本(以及如何处理仿函数)?
注意:我使用的是VS2015和GCC 4.9,所以std :: bind和占位符都在tr1中。
答案 0 :(得分:0)
您收到错误的原因是Args... args
应该只是args...
,如评论中所述。
另请考虑使用std::forward
正确转发参数
更喜欢使用decltype
来确定包装函数的返回类型
这不会强制转换为std::function
:
#include <functional>
typedef std::function<void(float, int)> tCallback;
template<typename F, typename... Args>
auto mybind(F f, Args... args)
-> decltype(std::bind(std::forward<F>(f), std::forward<Args>(args)...,
std::placeholders::_1, std::placeholders::_2 ))
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
return std::bind(std::forward<F>(f), std::forward<Args>(args)...,
// ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^~~~~
std::placeholders::_1, std::placeholders::_2 );
}
struct Foo {
tCallback m_cb;
void setcb(tCallback cb) {m_cb = cb;}
};
void f1(float f, int i) {}
void f2(int j, float f, int i) {}
int main()
{
Foo foo;
foo.setcb( mybind( f1 ) ); // Fine.
foo.setcb( mybind( f2, 1 ) ); // Not fine.
}
<强> Demo 强>
关于笔记的快速说明: - )
注意:我使用的是VS2015和GCC 4.9,所以std :: bind和占位符都在tr1中。
std::bind
已从Visual Studio 2013(2012)和std名称空间中移动
应该优先于tr1名称空间。
答案 1 :(得分:0)
所以实际问题是那个
return std::tr1::bind( f, Args... args,
std::tr1::placeholders::_1, std::tr1::placeholders::_2 );
实际上是:
return std::tr1::bind( f, args...,
std::tr1::placeholders::_1,
std::tr1::placeholders::_2, std::tr1::placeholders::_2 );
&#34; Args ... args&#34; vs&#34; args ...&#34;是我记错了我的代码。加倍_2意味着我试图用错误数量的参数调用函数。 (我不明白它为什么使用零绑定算法,但这是一个不同的问题!)