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

时间:2019-03-06 15:20:17

标签: c++ variadic-templates typetraits

我有以下代码,复制了可变参数模板: 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的返回值-是否有可能避免编写此sum()函数并具有相同的功能?

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

谢谢

3 个答案:

答案 0 :(得分:6)

为补充@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 + ...);
}

答案 1 :(得分:3)

诀窍是永远不允许空的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

答案 2 :(得分:1)

  
      
  1. 此处需要sum()函数,这样我才能获得在处理最后一个可变参数成员时传递的void的返回值-是否有可能避免编写此sum()函数并具有相同的功能?
  2.   

每次递归都需要停止条件。在对可变参数模板进行递归的典型用法中(例如在此代码中),停止条件是主模板的不同重载。因此,您无法完全摆脱这一点。

您当然可以用其他条件代替停止条件。也许这一点,也可以用于对不可默认构造的事物求和:

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

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

  
      
  1. sum()函数返回整数'0'限制了整数使用整个模板-我可以扩展同一模板来连接字符串吗?
  2.   

否,因为非模板函数不知道先前的递归调用处理的是哪种类型。这可以通过使用我上面建议的“最后一项”停止条件来解决。