2014-04-04 478 views
2

模板參數推導,我有以下模板聲明C++與lambda表達式

template<typename T> 
void foo(function<void(T)> f){ 
    // ... 
}; 

但是,當我這樣稱呼它

foo([](string s){ }); 
// visual studio 13 error message => 
// Error: void foo(std::function<void(_Type)>)' : 
//could not deduce template argument for 'std::function<void(_Type)>' 
//from 'main::<lambda_58b8897709e10f89bb5d042645824f66> 

模板參數推導失敗。 爲什麼?如何解決它?

我有可變參數模板

template<typename ... Tn> 
void foo(function<void(Tn ...)> f){ 
    // ... 
}; 

int main() { 
    foo<string,bool>([](string s,bool b){ }); // Works 
    foo([](string s,bool b){ }); // Fails 
} 

同樣的問題,但是,如果我明確地轉換它的工作拉姆達(!)

foo((function<void(string,bool)>) [](string s,bool b){ }); // Works 

// Or even a simpler syntax with a macro 
#define lmda_(a) (function<void a>)[&] a 
foo(lmda_((string s, bool b)) { }); // Works (note the extra()) 

爲什麼模板參數推導失敗?以及如何解決它?

+0

http://stackoverflow.com/q/11500881/560648 –

+1

這應該工作,並且可能是更好... 的#define lmda_(......)(函數<空隙(__VA_ARGS __)>)[&](__VA_ARGS__) - > foo(lmda_(string s,bool b){}); e:你需要使用兩個下劃線前後綴va_args(它們在這裏變成粗體格式文本) – Shaggi

+0

*機器人的Lambda平庸定律*:如果你的設計關心lambda表達式,那就錯了。 (也簡稱爲「lambda不是特別的」) –

回答

4

這是一個不可推卸的背景。不能推導出模板參數T

這是一個最簡單的例子。鑑於:

template<typename T> 
struct X 
{ 
    X(T t) : data(t) {} 
    T data; 
}; 

template<typename T> 
void f(X<T> param); 

現在你在做這樣的事情:

f(100); 

認爲T會被推斷爲int。沒有。它不會被推斷爲int。因爲T可能有多種可能性。例如,可能有專長爲:

template<> 
struct X<double> 
{ 
    X(int t) : data(t) {} 
    int data; 
}; 

template<> 
struct X<float> //another specialization 
{ 
    X(int t) : data(t) {} 
    int data; 
}; 

因此,即使tint(相同的100類型),模板參數可以是doublefloat(或任何其他類型)。

+0

也許你的意思是'f({100});'。 – Constructor

+0

@Constructor:編輯刪除混亂!謝謝。 – Nawaz

0

標準庫函數是一種類型,它可以容納任何可以使用調用操作符()調用的對象,這意味着以其他方式它是 函數類型的對象是函數對象。

函數實例化期間foo([](string str){}); 編譯器沒有辦法爲「函數」函數對象類推導出T的類型 這樣我們就明確指定了導致用於描述函數的依賴關係的更好方式的類型。 auto func1 = [](string str){}; foo(func1); 或 foo([](string str){});