为什么递归可变参数模板不能按预期工作?

时间:2016-07-16 12:37:37

标签: c++ templates c++11 recursion variadic-templates

#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:&#39; f&#39;:找不到匹配的重载功能

为什么它不能按预期工作?

1 个答案:

答案 0 :(得分:5)

问题在于,在递归调用a时,您无法转发bf,从而导致尝试使用a : int调用二进制重载并且b : 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)...));
}