Multiplying Pattern 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'm trying to declare std::arraywith a name arras a member of a class A. Here I want the arrsize of the unpacked elements to be dimensioned N_i, for example, in the case A<2,3,4>, "arr" should be dimensioned 2*3*4=24.
Does anyone know how this can be implemented?

+4
source share
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 function constexpr.

+11
source

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,"!");
}

:

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

++ 17 fold-expressions .

+3

You can use this function in an array declaration:

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

It uses 17x C ++ expressions and can be included as

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

This can be done using the recursive definition of the constexpr function.

And in C ++ 14, using a variable template , this can have a 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;
};
+1
source

Source: https://habr.com/ru/post/1657552/


All Articles