Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to iterate over a tuple of elemenets that have the same base class

Tags:

c++

tuples


Iterating over a tuple is a common question in the C++ world and I know the various ways it can be done - usually with recursion and variadic templates.
The reason is that a tuple usually holds different element types and the only way to correctly handle every type is to have a specific overload that matches this type. then we let the compiler dispatch every element to the correct function using recursion.

My case goes like this: I have a tuple of elements, every element is an instantiation of a template class:

std::tuple<my_class<int>, my_class<string>, my_class<float>>

Also, my_class<T> is a derived class of my_class_base, which isn't a template.
Considering this constraint, is it possible to write an at(tuple_type& tuple, size_t n) function that returns the nth element of the tuple, as a reference to the base class, in O(1) steps?

Then I can write

for (size_t i = 0; i < N; i++){
   auto& o = at<my_base_class>(tuple, i);
   o.call_base_method(...);
} 

Thanks.

like image 639
David Haim Avatar asked Nov 06 '22 01:11

David Haim


1 Answers

You might just using std::apply:

std::apply([](auto&...args){ (args.call_base_method(), ...); }, tuple);

Else to answer your question, you might do something like:

template <std::size_t... Is, typename tuple_type>
my_class_base& at_impl(std::index_sequence<Is...>, tuple_type& tuple, size_t n)
{
    my_class_base* bases[] = {&std::get<Is>(tuple)...};
    *return bases[n];
}

template <typename tuple_type>
my_class_base& at(tuple_type& tuple, size_t n)
{
    auto seq = std::make_index_sequence<std::tuple_size<tuple_type>::value>();
    return at_impl(seq, tuple, n);
}

Demo

like image 147
Jarod42 Avatar answered Nov 14 '22 10:11

Jarod42