Какой самый простой способ по умолчанию создать std :: варианту из индекса нужного типа, когда индекс известен только во время выполнения? Другими словами, я хочу написать:
const auto indx = std::variant<types...>{someobject}.index();
//...somewhere later, indx having been passed around...
std::variant<types...> var = variant_from_index(indx);
///var is now set to contain a default constructed someobject
Обратите внимание, что indx
нельзя сделать constexpr, поэтому std::in_place_index
здесь не работает.
Проблема здесь, конечно, что поскольку неизвестно, какой конструктор из types...
вызывать во время компиляции, каким-то образом, в основном, таблица всех возможных конструкторов (или, возможно, построенных по умолчанию вариантов для копирования) должна быть построена во время компиляции, а затем доступна во время выполнения , Какой-то шаблон magi c, очевидно, здесь на месте, но какой будет самый чистый путь?
Я пробовал следующее ( на coliru ), но последовательность индекса, кажется, выходит из строя (печать в конце дает 2 0 0
), и я не понимаю, почему:
Редактировать: это работает, как исправлено ниже, у меня была неправильная инициализация массива constexpr. Итак, вопрос в том, есть ли более аккуратный способ сделать это?
#include <variant>
#include <iostream>
using var_t = std::variant<int, float, const char *>;
//For debug
template<class ...types>
struct WhichType;
template<class T, class U>
struct default_variants;
template<class...Params, std::size_t... I>
struct default_variants<std::variant<Params...>, std::index_sequence<I...>> {
using variant_t = std::variant<Params...>;
//Uncomment to see the index sequence
//WhichType<std::index_sequence<I...>> idx{};
constexpr static variant_t variants[sizeof...(Params)]{variant_t{std::in_place_index<I>}...};
constexpr static std::size_t indices[sizeof...(Params)]{I...};
};
template<class T>
struct default_variants_builder;
template<class...Params>
struct default_variants_builder<std::variant<Params...>> {
using indices = std::make_index_sequence<sizeof...(Params)>;
using type = default_variants<std::variant<Params...>, indices>;
};
int main() {
using builder_t = typename default_variants_builder<var_t>::type;
var_t floatvar{1.2f};
var_t variant2 = builder_t::variants[floatvar.index()];
std::cout << "Contained " << floatvar.index() << "; Now contains " << variant2.index() << "\n";
}