【发布时间】:2020-03-06 12:31:04
【问题描述】:
当索引仅在运行时已知时,从所需类型的索引默认构造 std::variant 的最简单方法是什么?换句话说,我想写:
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... 的哪个构造函数,所以基本上必须构建一个包含所有可能构造函数的表(或者可能是要复制的默认构造变体)在编译时,然后在运行时访问。这里显然有一些模板魔法,但最干净的方法是什么?
我尝试了以下(on 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";
}
【问题讨论】:
标签: c++ templates c++17 template-meta-programming variant