2013-03-21 47 views
15

我有一个编译错误时,下面的代码是一个简单的例子:模板参数推导/置换失败,在模板构件函数使用std ::功能时使用std ::函数和std ::绑定

#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: In function ‘int main()’:

testtemplate.cpp:29:92: error: no matching function for call to ‘Test::setCallback(std::_Bind_helper)(int, int), TestA, const std::_Placeholder<1>&, const std::_Placeholder<2>&>::type)’

testtemplate.cpp:29:92: note: candidate is: testtemplate.cpp:10:7: note: template void Test::setCallback(std::function)

testtemplate.cpp:10:7: note: template argument deduction/substitution failed:

testtemplate.cpp:29:92: note: ‘std::_Bind(TestA*, std::_Placeholder<1>, std::_Placeholder<2>)>’ is not derived from ‘std::function’

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

+5

说'test.setCallback (bind ...)'。 'bind'的结果不是'std :: function',所以没有任何推论。 – 2013-03-21 08:28:27

+1

请告诉我你是如何认为编译器可能找出推断“T”的。 – Xeo 2013-03-21 08:29:07

+0

@Xeo我是一个模板大一新生,我不知道如何工作。一些材料的帮助? – haipeng31 2013-03-21 08:33:42

回答

9

为了弄清楚这个问题,让单独的语句:

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, ... 
+0

模板很辛苦,我用了整整一个下午来处理这个问题,最后,我解决不了,谢谢你的解释。顺便说一句,你可以给我一些建议,学习模板 – haipeng31 2013-03-21 08:50:24

+2

@ user1679133:每天编程和练习,这是学习编程概念的唯一方法。我们都是这样做的。并从Stackoverflow阅读问答。 – deepmax 2013-03-21 08:53:38

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,而是可以将其转换为一个东西,那么它可能会陷入困境。我不确定。

相关问题