3

This is a good answer already, however, they passed arbitrary numbers of arguments as the parameters when I tried to do the same with arguments as typename (don't know the exact word) like this for example:

int sum=0;
int func()
{
    return sum;
}

template <int first, int ... rest>
int func()
{
    sum += first;
    return func(rest...); //Error   C2660   'func': function does not take 4 arguments
    /*
     return func<rest...>(); this also doesn't work: Error 'int func(void)': could not deduce template argument for 'first' and 'func': no matching overloaded function found
     */
}


int main()
{
    cout << func<1,2,3,4,5>();
}

Why there's an error there? Are there any possible fixes? Also, I'm required to pass the argument as typenames, not parameters.

max66
  • 65,235
  • 10
  • 71
  • 111

4 Answers4

2

First of all, the "base" function also needs to be a template.

Then to differentiate the two templates, the parameter-pack template needs to take at least two template arguments.

And lastly, you can solve this without the global sum variable, but using the addition in the return statement.

Putting it all together:

template <int first>
int func()
{
    return first;
}

template <int first, int second, int ...rest>
int func()
{
    return first + func<second, rest...>();
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

For a simple use case as a sum of values, there are many ways (as in Some programmer dude and P Kramer answers).

I'll show you a variant of the recursive solution (Some programmer dude's answer) that isn't particular useful in this case but can come useful in other circumstances (avoiding code repetition when the ground function make something consistent and equal to the recursive version): instead of a ground case version that receive and manage the last value, a ground version that receive a defaulted type and do nothing (return zero, in the sum case):

template <typename = void>
int func ()
 { return 0; }

so you can write the recursive version as follows, without second

template <int first, int ... rest>
int func ()
 { return first + func<rest...>(); }

The trick is in the recursive call: func<rest...>()

When the ...rest template pack isn't empty, the recursive call func<rest...>() invoke the recursive func().

But when the ...rest template pack is empty, the recursive call func<rest...>() become func<>() that doesn't matches the recursive func() (at least a template integer value is required) but matches (thanks to the default void type) func<void>(), so the ground func() function.

max66
  • 65,235
  • 10
  • 71
  • 111
0

If you want to return the sum of a parameter pack and you're okay with a slightly different syntax, you can use fold expressions from C++17 onward or build up recursion with 'if constexpr'

template<typename... args_t>
static constexpr auto sum(args_t&&... values)
{
    return (values + ...);
}

// the sum is evaluated at compile time
static_assert(sum(1, 2, 3, 4) == 10ul);

// or like this without fold
    template<int value, int... values>
constexpr int sum2()
{
    if constexpr (sizeof...(values) > 0)
    {
        return value + sum2<values...>();
    }
    else
    {
        return value;
    }
};

static_assert(sum2<1,2,3,4>() == 10);
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19
0

Just for curiosity here is the version without recursion:

// C++11

template<typename... Ts>
void dummy(Ts... t)
{
}

template<typename T>
T addValue(T& sum, T value)
{
    sum += value;
    return 0;
}

template<typename SumType, typename... Ts>
SumType sumVariadicArgs(Ts... t)
{
    SumType sum = 0;
    dummy(addValue(sum, t)...);
    return sum;
}

int main()
{
    int sum = sumVariadicArgs<int>(1, 2, 3);
    double sum2 = sumVariadicArgs<double>(1.0, 2.0, 3.0);
    return 0;
}
KonstantinL
  • 667
  • 1
  • 8
  • 20