Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiplication of Template Arguments

I have the following problem:

template< size_t... N_i >
class A
{
  // ...
  std::array< float, /* product of the unpacked elements of N_i */ > arr;
};

As you can see above, I try to declare an std::array named arr as a member of a class A. Here, I want arr to have the size product of the unpacked elements of N_i, e.g., in case of A<2,3,4>, "arr" should have the size 2*3*4=24.
Does anyone know how this can be implemented?

like image 721
abraham_hilbert Avatar asked Oct 12 '16 21:10

abraham_hilbert


4 Answers

In C++17:

std::array < float, (... * N_i)> arr;

In C++14:

// outside the class
template<size_t... Ns>
constexpr size_t product(){
    size_t p = 1;
    for(auto n : { Ns... }) p *= n;
    return p;
}

// then
std::array< float, product<N_i...>()> arr;

In C++11:

template<size_t... N_i>
struct product { 
    static const size_t value = 1; 
};

template<size_t N_1, size_t... N_i>
struct product<N_1, N_i...> {
    static const size_t value = N_1 * product<N_i...>::value;
};

std::array< float, product<N_i...>::value> arr;

Alternatively, you can use a recursive constexpr function.

like image 181
T.C. Avatar answered Oct 22 '22 01:10

T.C.


In C++14 you can do this:

size_t v = 1;
size_t _[] = { (v = v*N_i)... };

As a minimal, working example:

#include<cstddef>

template<std::size_t... I>
constexpr auto f() {
    std::size_t v = 1;
    std::size_t _[] = { (v = v*I)... };
    (void)_;  // silent a warning and nothing more
    return v;
}

int main() {
    static_assert(f<2,3,4>() == 24,"!");
}

Your class can be defined as it follows:

template< size_t... N_i >
class A {
    // ...
    std::array< float, f<N_i...>()> arr;
};

In C++17 fold-expressions will simplify it.

like image 36
skypjack Avatar answered Oct 22 '22 01:10

skypjack


This can be done with recursive definition of constexpr function.

And in c++14 using variable template this can have cleaner look :

template <typename ...Ts> 
constexpr size_t product()
{
    return  1;
}
template <size_t I,size_t... Is> 
constexpr size_t product()
{
    return   I * product<Is...>();
}

template <size_t I, size_t... Is> 
constexpr size_t prod = product<I, Is...>();


template< size_t... N_i >
class A
{
    std::array< float, prod<N_i...> > arr;
};
like image 2
rahnema1 Avatar answered Oct 22 '22 03:10

rahnema1


You can use this function in your array declaration:

template<typename ...Args>
constexpr int multiply(Args&&... args)
{
    return (args * ... );
}

It uses C++17 fold expressions, and can be included like

template< size_t... N_i >
class A
{
  // ...
  std::array< float, multiply(N_i ...) > arr;
};
like image 1
davidhigh Avatar answered Oct 22 '22 01:10

davidhigh