How would I make a std::vector
that contains a default-constructed instance of all the types contained in a std::variant
?
using TaskVariant = std::variant<TypeA, TypeB, TypeC>;
std::vector<TaskVariant> variants;
// I'd like to do this in a loop
variants.push_back(TypeA());
variants.push_back(TypeB());
variants.push_back(TypeC());
1.Solution: You can convert variant to tuple and then use C++17 std::apply:
#include <variant>
#include <iostream>
#include <string>
#include <vector>
#include <tuple>
using namespace std;
template <typename... Types>
struct ToTuple;
template <typename... Types>
struct ToTuple<variant<Types...>>
{
using type = tuple<Types...>;
};
struct TypeA {};
struct TypeB {};
struct TypeC {};
using TaskVariant = std::variant<TypeA, TypeB, TypeC>;
int main()
{
vector<TaskVariant> vec;
apply([&vec](auto&&... args) {(vec.push_back(args), ...); }, ToTuple<TaskVariant>::type{});
}
EDIT:
2.Solution: Using make_index_sequence, variant_alternative_t and variant_size_v (all C++17) (thanks to @s d by pointing out to variant_alternative_t, but I have modified example by using make_index_sequence instead of recursion):
#include <variant>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct TypeA {};
struct TypeB {};
struct TypeC {};
using TaskVariant = std::variant<TypeA, TypeB, TypeC>;
template <size_t... Idx>
void fill_vec(vector<TaskVariant>& vec, index_sequence<Idx...> idx)
{
(vec.push_back(variant_alternative_t<Idx, TaskVariant>{}), ...);
}
int main()
{
vector<TaskVariant> vec;
fill_vec(vec, make_index_sequence<variant_size_v<TaskVariant>>{});
}