2016-07-16 34 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规格大失所望。 –

相关问题