I’m trying to turn a vector
of variant
s into a tuple
of vector
s variadicly (i.e. I’d like to factor out the following code into a variadic template std::variant<Ts...>
).
std::vector<std::variant<float, int>> vector_of_variants;
vector_of_variants.emplace_back(1);
vector_of_variants.emplace_back(2.f);
std::tuple<std::vector<float>, std::vector<int>> result;
for (auto& el : vector_of_variants)
{
auto index = el.index();
std::get<index>(result).pushback(std::get<index>(el)); // error: index is runtime value
}
However, the line std::get<index>(result).pushback(std::get<index>(el));
obviously won’t work and I need to replace it with some std::visit
like behaviour (i.e. generate the line tuple_size
times and delegate at runtime).
What’s the ergonomic way to do this?
>Solution :
Assuming you have guaranteed that corresponding indices in the variants and result
match, something like the following should work for a naive implementation. Might not be the best performance:
[&]<std::size_t... Is>(std::index_sequence<Is...>){
((index == Is ? std::get<Is>(result).push_back(std::get<Is>(el)) : void()), ...);
}(std::make_index_sequence<std::tuple_size_v<decltype(result)>>{});
If you don’t care about repeated types, you can also use std::visit
instead:
std::visit([](auto&& v){
std::get<std::remove_reference_t<decltype(v)>>(result).push_back(std::forward<decltype(v)>(v));
}, el);
Unfortunately there is no std::visit
alternative that passes both the value of the variant as well as the type index (e.g. as a std::integer_constant
) to the visitor. That would make it easier here.