2013-03-21 45 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,而是可以將其轉換爲一個東西,那麼它可能會陷入困境。我不確定。

相關問題