Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add all parameters with parameter pack expansion [duplicate]

Consider I have a variadic template with int... parameters. For example a function like this:

template<int... t>
int add(){
    return t... + ???
}

All the method should do is adding all the parameters. It can be easily achieved using recursive variadic templates. However, is it also possible expressing this (or something similar like using other binary operators to aggregate all the template parameters) using parameter pack expansion?

like image 354
gexicide Avatar asked May 13 '14 10:05

gexicide


2 Answers

Yes, using a trick I learnt from @Xeo in the Lounge. I originally used it to make a variadic "print" template function.

#include <iostream>

template<int... ints>
int add()
{
  int result = 0;
  using expand_variadic_pack  = int[]; // dirty trick, see below
  (void)expand_variadic_pack{0, ((result += ints), void(), 0)... };
  // first void: silence variable unused warning
  // uses braced-init-list initialization rules, which evaluates
  //  the elements inside a braced-init-list IN ORDER, to repetetively
  //  execute a certain operation
  // second void is to prevent malicious "operator," overloads, which
  //  cannot exist for void types
  // 0 at the end is to handle empty variadic pack (zero-size array initializer is illegal.
  return result;
}

int main()
{
  std::cout << add<1,2,3,4>() << '\n';
}

This works on every compiler that has decent C++11 support (GCC 4.8+, Clang 3.2+, MSVS2013, ...)

like image 74
rubenvb Avatar answered Oct 13 '22 01:10

rubenvb


One possible variant which uses lambda and std::accumulate:

#include <array>
#include <numeric>

template <int... t>
int add()
{
    return [](const std::array<int, sizeof...(t)>& a)
    {
        return std::accumulate(a.begin(), a.end(), 0);
    }({t...});
}
like image 45
Constructor Avatar answered Oct 13 '22 00:10

Constructor