为什么递归可变参数模板无法按预期工作

Why does recursive variadic templates not work as expected?

本文关键字:工作 递归 变参 参数 为什么      更新时间:2023-10-16
#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":未找到匹配的重载函数

为什么它没有按预期工作?

问题是您在递归调用f时没有转发ab,这会导致尝试使用 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)...));
}