使用std :: function和std :: bind时,模板参数推导/替换失败

时间:2013-03-21 08:26:08

标签: c++ function templates bind

在模板化成员函数中使用std :: function时出现编译错误,以下代码是一个简单示例:

#include <functional>
#include <memory>
using std::function;
using std::bind;
using std::shared_ptr;

class Test {
public:
     template <typename T>
     void setCallback(function<void (T, int)> cb); 
};

template <typename T>
void Test::setCallback(function<void (T, int)> cb)
{
    // do nothing
}

class TestA {
public:
    void testa(int a, int b) {   }
};


int main()
{
    TestA testA;
    Test test;
    test.setCallback(bind(&TestA::testa, &testA, std::placeholders::_1, std::placeholders::_2));
    return 0;
}

并出现以下编译错误:

  

testtemplate.cpp:在函数'int main()'中:

     

testtemplate.cpp:29:92:错误:没有匹配的调用函数   'test :: setCallback(std :: _ Bind_helper)(int,int),   TestA,const std :: _ Placeholder&lt; 1&gt;&amp;,const   的std :: _占位符&LT 2 - ;&安培;&GT; ::类型)”

     

testtemplate.cpp:29:92:注意:候选人是:testtemplate.cpp:10:7:   注意:template void Test :: setCallback(std :: function)

     

testtemplate.cpp:10:7:注意:模板参数   扣除/替换失败:

     

testtemplate.cpp:29:92:注意:'std :: _ Bind(TestA *,std :: _ Placeholder&lt; 1&gt;,   std :: _ Placeholder&lt; 2&gt;)&gt;'不是来自'std :: function'

我正在使用C ++ 11和g ++ 4.7

2 个答案:

答案 0 :(得分:11)

要找出问题,请单独说明:

auto f = bind(&TestA::testa, &testA, _1, _2); // OK
test.setCallback(f);                          // <<--- Error is here

setCallback需要知道T的类型,并且无法从f推断出来,所以请给它一个类型

test.setCallback<TYPE>(f); // TYPE: int, float, a class, ...

答案 1 :(得分:0)

您可以使用以下某种变体进行类型推导:

template<typename CALLBACK>
void setCallback(CALLBACK cb) {
  typedef CALLBACK::first_argument_type T;
  static_assert(is_same_type<CALLBACK,function<void(T,int)>>::value);
  ...
}

这样可以通过查看参数来确定CALLBACK。如果bind实际上不返回std :: function而是可以作为一个转换的东西,它可能会遇到麻烦。我不确定。