如何使用get std :: bind之类的行为

时间:2015-12-09 22:29:47

标签: c++ templates c++11

我正在尝试为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中。

2 个答案:

答案 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意味着我试图用错误数量的参数调用函数。 (我不明白它为什么使用零绑定算法,但这是一个不同的问题!)