当前位置: 首页 > 知识库问答 >
问题:

默认从索引构造std::variant

仰欣悦
2023-03-14

当索引仅在运行时已知时,从所需类型的索引默认构造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";
}

共有1个答案

杜嘉木
2023-03-14

对于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 会给出与std::variant_size_v 相同的值,如果您更愿意的话),并且它将调用您提供的具有正确常量的函数(i在这里具有integral_constant 类型,但index是常量表达式)。

 类似资料:
  • 如果我构造一个空的使用默认的构造函数(和默认的分配器),它可以抛出一个异常吗? 通常,为容器的元素分配空间会引发异常(这将是一个<code>std::bad_alloc</code>)。但是<code>std::vector</code>的默认构造函数不需要分配任何这样的空间;它可以在第一次插入或分配时惰性地分配一些空间。但是C标准是否要求它不抛出异常(意味着延迟分配,或者捕获<code>std:

  • 问题内容: 默认构造函数到底是什么?你能告诉我以下哪个是默认构造函数,它与其他构造函数有何不同? 问题答案: 他们都不是。如果定义,则不是默认值。 除非你定义另一个构造函数,否则默认构造函数是自动生成的无参数构造函数。任何未初始化的字段都将设置为其默认值。对于你的榜样,它看起来像这样假设的类型String,int以及int,那类本身是公共的: 这与 完全没有构造函数。但是,如果定义至少一个构造函数

  • 问题内容: 我知道我在这里问一些严重的101问题… 我有一些课,还有一个延伸课。在我有一个构造函数,它接受一组参数,并对其字段进行设置。派生类(例如)通常不需要进行修改。现在我的IDE给我 “ Foo中没有默认的构造函数” 。从一点点谷歌搜索,这似乎是因为“构造函数没有继承”。因此,一切都很好,但是我现在如何使它工作而不在每个派生类中复制此构造函数?我假设有一个更合理的方法? 问题答案: 使用构造

  • 问题内容: 不知何故,在下面的Node类中,and变量在Node的所有实例之间共享。 有什么办法可以让我继续使用构造函数参数的默认值(在这种情况下为空列表),但要同时获取它们和拥有其自身的变量以及变量? 我正在使用python 3.1.2。 问题答案: 可变的默认参数通常不会执行您想要的操作。相反,请尝试以下操作:

  • 为什么: 如果一个类不提供任何然后在编译时由编译器给出,但是如果一个类包含,那么默认构造函数不是由编译器提供。 我正在编译下面的代码。它给出了编译错误。 代码: 控制台错误: 当我只调用。工作正常。但是当您想使用参数化构造函数调用

  • 问题内容: 根据文档,我尝试按以下方式更新副本数 这将正确更改现有节点的副本数。但是,当logstash在第二天创建新索引时,number_of_replicas设置为旧值。 有没有一种方法可以永久更改此设置的默认值,而无需更新群集中的所有文件并重新启动服务? 我也尝试过 无济于事。 问题答案: 是的,您可以使用索引模板。索引模板是为集群中创建的新索引设置默认设置(包括映射)的好方法。 索引模板