可变参数模板 - 递归函数 - 最后一个可变参数成员

Variadic Templates - Recursive function - Last variadic member

我有以下代码以及从以下位置复制的可变参数模板: https://www.youtube.com/watch?v=iWvcoIKSaoc @41:30

auto sum() { return 0; }

template<typename Head, typename... Tail>
auto sum(Head head, Tail... tail)
{
    return head+sum(tail...);
}

int main() {
    cout<< sum(1,2.4) << endl;
    //cout<< sum("hello ", "world") << endl;
    return 0;
}

我有两个问题: 1. 此处需要 sum() 函数,以便在处理最后一个可变参数成员时传入 void 的 return 值 - 是否可以避免编写此 sum() 函数并具有相同的功能?

  1. 从 sum() 函数返回整数“0”会限制整数使用整个模板 - 我可以扩展相同的模板来连接字符串吗?

谢谢

  1. The sum() function is required here so that I can have a return value for a void passed in when processing the last variadic member - Is it possible to avoid writing this sum() function and have the same functionality?

每个递归都需要一个停止条件。在典型的使用可变参数模板的递归中(例如在这段代码中),停止条件是主模板的不同重载。所以你不能完全摆脱它。

您当然可以将停止条件替换为其他条件。也许这个,它也适用于对不可默认构造的事物求和:

template <class T>
auto sum(T last) { return last; }

当然,除了递归可变模板之外,还有其他方法;这种方法可能不需要停止条件。

  1. Returning a integer '0' from the sum() function restricts the entire template to be used by integers - Can I extend the same template to concatenate strings?

不,因为非模板函数不知道先前的递归调用正在处理哪种类型。这可以通过使用我上面建议的 "last item" 停止条件来解决。

诀窍是永远不允许空 sum() 调用,并将 sum(last) 视为最后一个递归:

template<typename Last>
auto sum(Last last) {
    return last;
}

template<typename Head, typename Second, typename... Tail>
auto sum(Head head, Second second, Tail... tail)
{
    return head + sum(second, tail...);
}

int main() {
    cout<< sum(1,2.4) << endl;
    cout<< sum("hello ", "world") << endl;
    return 0;
}

Live example

为了补充@GuillaumeRacicot 的回答,我更喜欢用 if constexpr 结束递归,这是一个 c++17 特性。

template<typename Head, typename Second, typename... Tail>
auto sum(Head head, Second second, Tail... tail)
{ 
    if constexpr(sizeof...(tail) > 0)
      return head + sum(second, tail...);
    return head + second;
}

也可以考虑折叠表达式:

template<typename ...Pack>
auto sum(Pack... args) {
    return (args + ...);
}