Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variadic Templates - Recursive function - Last variadic member

I have the following code with a variadic template copied from: 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;
}

I have two questions: 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?

  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?

Thank You

like image 985
Nujufas Avatar asked Dec 24 '22 00:12

Nujufas


2 Answers

To complement @GuillaumeRacicot answer I prefer to end a recursion with if constexpr which is a c++17 feature.

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;
}

You can also consider fold expressions:

template<typename ...Pack>
auto sum(Pack... args) {
    return (args + ...);
}
like image 131
KostasRim Avatar answered Feb 24 '23 06:02

KostasRim


The trick is to never allow empty sum() calls, and treat the sum(last) as the last recursion:

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

like image 22
Guillaume Racicot Avatar answered Feb 24 '23 06:02

Guillaume Racicot