Search code examples
c++tuplesvariadic-templates

Create a tuple of successive elements of a vector divided by each other


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()?


Solution

  • 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