1

Consider a tuple t of n objects with similar interface (like all have the same base class); n is known during compilation. I need to make a sum as following

std::get<0>(t).foo(vec_0) + std::get<1>(t).foo(vec_1) + ... + std::get<n>(t).foo(vec_n)

I know to add elements of a tuple of numbers, like here, and even variable\functions of an objects in a tuple, e.g.

std::get<0>(t).bar()+std::get<1>(t).bar()...

The situation that I still interesting to find a (template) solution for is the following one:

  1. all vec_0,...,vec_n are different size slices of a bigger vector Vec.
  2. the information about size of each is known from the tuple as well so actually what I need looks as the following
std::get<0>(t).foo(Vec.head(std::get<0>(t).n)) + 
std::get<1>(t).foo(Vec.segment(std::get<0>(t).n, std::get<1>(t).n))+
std::get<2>(t).foo(Vec.segment(std::get<0>(t).n + std::get<1>(t).n, std::get<2>(t).n))+
... +
std::get<n>(t).foo(Vec.tail(std::get<n>(t).n))

Here segment takes (start, size) and return required vector; the size is known from std::get<?>(t).n.

1 Answers1

1

You just need extra std::index_sequence usage for the inner elements, something like:

template <std::size_t ... Is, typename Tuple, typename Vec>
auto helper(std::index_sequence<Is...>, const Tuple& t, const Vec& vec)
{
    constexpr auto N = sizeof...(Is);
    constexpr auto Size = std::tuple_size<Tuple>::value;

    if constexpr (Size == 1) {
        // Unsure what you want here
        return std::get<0>(t).foo(Vec.head(std::get<0>(t).n))
             + std::get<N>(t).foo(Vec.tail(std::get<0>(t).n));
    } else if constexpr (N == 0) {
        return std::get<0>(t).foo(Vec.head(std::get<0>(t).n)); 
    } else if constexpr (N + 1 == Size) {
        return std::get<N>(t).foo(Vec.tail(std::get<N>(t).n));
    } else {
        return std::get<N>(t).foo(Vec.segment((0 + ... + std::get<Is>(t).n),
                                              std::get<N>(t).n));
    }
}

template <std::size_t ... Is, typename Tuple, typename Vec>
auto summation(std::index_sequence<Is...>, const Tuple& t, const Vec& vec)
{
    return (0 + ... + helper(std::make_index_sequence<Is>(), t, vec));
}

template <typename Tuple, typename Vec>
auto summation(const Tuple& t, const Vec& vec)
{
    constexpr auto Size = std::tuple_size<Tuple>::value;
    return summation(std::make_index_sequence<Size>(), t, vec));
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302