C ++ 17 effectively multiplies arguments of a parameter package using std :: array elements

I want to efficiently multiply the arguments from a parameter package with std :: array elements:

int index(auto... Is, std::array<int,sizeof...(Is)> strides)
{
  // pseudo-code
  // int idx = 0;
  // for(int i = 0; i < sizeof...(Is); ++i)
  //   idx += Is[i] * strides[i];
  // return idx; 
}

I can't completely wrap my brain around this. I started the sequence index path, but I could figure out how to enable summation.

I use C ++ 17, so fold statements are fair game if they simplify the code.

Thanks for any pointers.

EDIT: Refined Pseudo Code. The only pseudo-part is an expression Is[i]that refers to the package argument of the ith parameter.

The TC answer below was perfect, and here is my final code, which is a member function:

unsigned int index(auto... indexes)
{
    unsigned int idx = 0, i = 0;
    (..., (idx += indexes * m_strides[i++]));
    return idx;
}

Starting with this entry, code is compiled using gcc 6.3.0 with the -fconcepts flag, which introduces the concept of TS.

auto... indexes template<typename Args> f(Args... indexes). unsigned int , .

(...,) - ( [] ):

idx += indexes[0] * m_strides[i++], idx += indexes[1] * m_strides[i++], etc.

, .

+6
2

auto... , index.

(index_helper ), index_sequence, .

#include <array>
#include <cstdio>

template <typename... T, size_t... i>
//                       ^~~~~~~~~~~
//                        use deduction to make {i...} = {0, 1, 2, ..., n}
static int index_helper(const std::array<int, sizeof...(T)>& strides,
                        std::index_sequence<i...>,
                        T... Is) 
{
    return (0 + ... + (strides[i] * Is));
}

template <typename... T>
int index(const std::array<int, sizeof...(T)>& strides, T... Is) {
    return index_helper(strides, std::make_index_sequence<sizeof...(T)>(), Is...);
//                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//                                generates {0, 1, 2, ..., n}
}

int main() {
    printf("%d\n", index({1, 100, 100000, 1000}, 2, 3, 5, 7));
    // 507302
}
+3

, /, :

T arr[] = { static_cast<T>(Is)... }; // for some T, possibly common_type_t<decltype(Is)...>

.

, :

int idx = 0, i = 0;
(..., (idx += Is * strides[i++]));
return idx;
+1

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


All Articles