1

Assume I have a std::tuple, I'd like to write a function which receives a tuple and a variadic sequence outputting a subtuple containing the columns corresponding to those indexes.

Example usecase:

std::tuple<int, char, float, std::string> t{1, 'd', 3.14, "aaa"};

auto subtuple = extract_subtuple(t, 0, 2);
// returns std::tuple<int, float>(1, 3.14)

Is this possible ?

I had a look at this other question but in the end I didn't find what I was looking for.

Elle
  • 305
  • 2
  • 10
  • but why you want to use indices like that? They must be compile-time constants anyway so there's no difference from `std::make_tuple(std::get<0>(t), std::get<2>(t))` – phuclv May 01 '22 at 12:20
  • I'm trying to implement a parallel method that basically selects tuples according to indices, then I need to pass the indexes and I need a sort of variadic behavior that I'm failing to implement – Elle May 01 '22 at 12:27
  • 1
    Please provide some more context and a code example for the use case. It is not generally possible to create a sub-tuple based on a runtime index range since the type would dependent on the index sets (and using something like `std::variant` would be practically impossible for all possible index sets). – user17732522 May 01 '22 at 12:31
  • You could do `auto subtuple = extract_subtuple<0, 2>(t);`. – super May 01 '22 at 12:33

1 Answers1

2

You can't do it directly because tuple indices should be constant expressions and function parameters are never constant expressions even if corresponding arguments are. You have two main options.

Firstly, you could make indices template parameters:

template<std::size_t... Is, class... Ts>
auto extract_subtuple(const std::tuple<Ts...>& tuple) {
    return std::make_tuple(std::get<Is>(tuple)...);
}

auto subtuple = extract_subtuple<0, 1>(t);

Secondly, if you want to make indices function parameters, you could wrap them into types:

template<class... Ts, class... Indices>
auto extract_subtuple(const std::tuple<Ts...>& tuple, Indices...) {
    return std::make_tuple(std::get<Indices::value>(tuple)...);
}

template<std::size_t I>
using Idx = std::integral_constant<std::size_t, I>;

auto subtuple = extract_subtuple(t, Idx<0>{}, Idx<1>{});
Evg
  • 25,259
  • 5
  • 41
  • 83
  • the first version works perfectly for what I need, thanks a lot. I'm accepting your answer – Elle May 01 '22 at 12:35