默认从索引构造一个std :: variant

蒂莫

当仅在运行时知道索引时,从所需类型的索引默认构造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...在编译时要从哪个构造函数调用,因此基本上必须在编译时构造所有可能的构造函数的表(或从中复制默认构造变量),然后再对其进行访问在运行时。这里显然有一些模板魔术,但是最干净的方法是什么?

我尝试了以下操作(在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";
}
巴里

使用Boost.Mp11,这基本上是单线的(像往常一样):

template <typename V>
auto variant_from_index(size_t index) -> V
{
    return mp_with_index<mp_size<V>>(index,
        [](auto I){ return V(std::in_place_index<I>); });
}

您对问题的描述是准确的-您需要一种将运行时索引转换为编译时索引的方法。mp_with_index为您做到这一点-您为它提供运行时索引和最大编译时索引(mp_size<V>此处将提供与std::variant_size_v<V>您更喜欢的值相同的值),并且它将调用您提供的具有正确常数的函数(此处为Itype)integral_constant<size_t, index>,除非index是常量表达式)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章