Home > Software design >  Create a tuple of successive elements of a vector divided by each other
Create a tuple of successive elements of a vector divided by each other

Time:09-07

I have a member variable of a class, offsets, which is a vector with at leastN 1 elements. I would like to create a member function which will return a tuple with N entries with values of successive elements of the vector divided by each other. An example is shown below for a specific instance of this function when N=3.

std::tuple<3> get_shape()
{
    return std::make_tuple(offsets[N]/offsets[N-1], offsets[N-1]/offsets[N-2], offsets[N-2]/offsets[N-3]);
}

Is there a way that this sequence can be generalized to implement the function std::tuple<N> get_shape()?

CodePudding user response:

You can implement this with std::index_sequence.

template<size_t N>
struct foo {
    std::array<double, N   1> offsets;

    auto get_tuple() const {
        auto make_tuple = 
            [this]<typename I, I... idx>(std::index_sequence<idx...>) {
                return std::make_tuple((offsets[N - idx] / offsets[N - idx - 1])...);
            };

        return make_tuple(std::make_index_sequence<N>());
    }
};

std::make_index_sequence<N> turns into std::index_sequence<0, 1, 2, ... N - 1>. This can be applied on a templated lambda since . Where we can access 0, 1, 2, ... N - 1 via the variadic I... idx. Now saying ... inside std::make_tuple will unpack all the idx numbers into N arguments

int main() {
    foo<3> f = { 2, -4, 7, 1 };

    auto tuple = f.get_tuple();
    static_assert(std::is_same_v<decltype(tuple), std::tuple<double, double, double>>);

    std::apply([](auto&&... rest) {
        ((std::cout << rest << " "), ...);
    }, tuple);
}

output:

0.142857 -1.75 -2
  • Related