2016-07-16 33 views
0
#include <type_traits> 

template<typename T> 
T f(T&& a, T&& b) 
{ 
    return a + b; 
} 

template<typename T, typename... Args> 
T f(T&& a, T&& b, Args&&... args) 
{ 
    return f(a, f(b, std::forward<Args>(args)...)); 
} 

int main() 
{ 
    f(1, 2, 3); 
} 

VS 2015年輸出:錯誤C2672: 'F':沒有匹配的重載函數發現爲什麼遞歸可變參數模板不能按預期工作?

爲什麼預期它不工作?

+0

哪個調用'F'你有問題嗎?您顯示的代碼中有三個。 –

+2

作爲提示g ++ 4.9.3給出以下錯誤: test.cpp:10:3​​:note:template argument deduction/substitution failed: test.cpp:12:49:note:推導出的參數'T'的衝突類型( 'int&'和'int') return f(a,f(b,std :: forward (args)...)); – robal

+2

std :: forward定義在不是 robal

回答

5

的問題是,你不轉發ab當遞歸調用f,從而導致在試圖撥打二進制超載與a : intb : int&。這裏有一個第一步:

template<typename T> 
T f(T&& a, T&& b) { 
    return a + b; 
} 

template<typename T, typename... Args> 
T f(T&& a, T&& b, Args&&... args) { 
    return f(std::forward<T>(a), f(std::forward<T>(b), std::forward<Args>(args)...)); 
} 

現在的問題是,傳遞必須具有相同的價值範疇任何左值參數的所有參數會導致錯誤,例如int i = 2; f(1, i, 3);將會失敗。爲了解決這個問題..:

template<typename T, typename U> 
typename std::decay<T>::type 
f(T&& a, U&& b) { 
    return a + b; 
} 

template<typename T, typename U, typename... Args> 
typename std::decay<T>::type 
f(T&& a, U&& b, Args&&... args) { 
    return f(std::forward<T>(a), f(std::forward<U>(b), std::forward<Args>(args)...)); 
} 

然後可以簡化爲:

template<typename T, typename U> 
typename std::decay<T>::type 
f(T&& a, U&& b) { 
    return a + b; 
} 

template<typename T, typename... Args> 
typename std::decay<T>::type 
f(T&& a, Args&&... args) { 
    return f(std::forward<T>(a), f(std::forward<Args>(args)...)); 
} 
+0

更好地使用auto作爲返回類型。 decay 不關心U.將int添加到float(按該順序)必須返回float,而不是int。 –

+0

@EmilioGaravaglia:OP要求所有類型都是相同的,所以在我的答案中不用考慮支持不同類型。有多種方法可以做到這一點,但考慮到問題被標記爲「C++ 11」,簡單地使返回類型爲「auto」不是其中之一。 : - [ – ildjarn

+0

是的...可悲的是,C++ 0x/1x規格大失所望。 –

相關問題