28

在模板化成员函数中使用 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<1>&, const std::_Placeholder <2>&>::type)'</p>

testtemplate.cpp:29:92: 注意: 候选是: testtemplate.cpp:10:7: 注意: 模板无效 Test::setCallback(std::function)

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

testtemplate.cpp:29:92:注意:'std::_Bind(TestA*, std::_Placeholder<1>, std::_Placeholder<2>)>' 不是从 'std::function' 派生的</p >

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

4

2 回答 2

15

要找出问题,请分开声明:

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

setCallback需要知道 type ofT并且它不能从中推断出来f,所以给它一个 type

test.setCallback<TYPE>(f); // TYPE: int, float, a class, ...
于 2013-03-21T08:44:53.483 回答
1

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

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 而是可以转换为一个的东西,它可能会遇到麻烦。我不知道。

于 2013-03-21T18:28:23.597 回答