C++ 通过填充一个元素来构造std::array

C++ 通过填充一个元素来构造std::array,c++,c++11,stdarray,C++,C++11,Stdarray,我有一个list类,其中size变量是const成员。这对我很有帮助,因为它强制要求列表的大小在不同的运行中可能有所不同,但不能在单个运行中有所不同 我想创建这些列表的集合。集合中的列表数是一个模板变量,因此我想使用std::array。。。i、 例如,我想要一个列表数组,其中数组的大小是一个模板参数,每个列表的大小是在构造时指定的const 不幸的是: constsize列表没有默认构造函数(需要指定其大小!),因此我需要为列表的每个元素提供一个构造函数参数。我不能只是创建数组然后设置元素

我有一个list类,其中size变量是
const
成员。这对我很有帮助,因为它强制要求列表的大小在不同的运行中可能有所不同,但不能在单个运行中有所不同

我想创建这些列表的集合。集合中的列表数是一个模板变量,因此我想使用
std::array
。。。i、 例如,我想要一个列表数组,其中数组的大小是一个模板参数,每个列表的大小是在构造时指定的
const

不幸的是:

  • constsize列表没有默认构造函数(需要指定其大小!),因此我需要为列表的每个元素提供一个构造函数参数。我不能只是创建数组然后设置元素
  • 因为我的列表大小是一个模板变量,所以我不能使用标准的初始值设定项列表-所需的元素数量会有所不同
我认识到还有其他选择:

  • 我可以使用一个
    std::vector
    ,然后将元素一个一个地推回
    直到向量的大小等于我的模板参数,但这似乎不美观,因为它不会自然地强制执行这样的条件,即结果向量的大小在完全填充后不应更改
  • 我可以翻转索引顺序,得到一个常量大小的
    std::array
    列表。但是,这与我的代码的其余部分不太匹配;我希望能够将单个常量大小的列表从数组传递到客户端代码
  • 我可以为常量大小的list类创建一个默认构造函数,创建数组,然后使用placement new逐个替换数组元素。这似乎有一些坏的副作用(const-sized list的默认构造函数是做什么的?如果它在别处被意外调用怎么办?如果我的继任者不知道我做了什么怎么办?)
由于没有一个是完全理想的,我认为如果有一个数组构造函数(或帮助函数)将作为参数:

  • T数组中的元素数
  • 单个T形物体
  • …并返回一个
    std::array
    ,其中每个
    T
    都是从参数2复制构造的

    这样的东西存在吗?

    std::array
    是一个模板类,表示
    T
    类型元素的长度为
    N
    的数组。如果要创建列表数组,只需执行
    std::array,N>
    ,其中
    N
    编译时已知<代码>常量std::size\u t N
    不够,必须如此

    所以不,你不能那样做。但是,您可以使用
    std::vector
    进行此操作


    如果您发布一些您的工作代码,我们可以想出更好的方法。

    好的。模板魔术。由于
    std::array
    是聚合类型,因此可以使用聚合初始化对其进行初始化:

    std::array<T, 5> arr = { one, two, three, four, five };
    
    因此,让我们创建一个函数,返回已初始化的数组:

    std::array<A, 5> arr = create_array_by_copy<5>(A(10));
    
    这将创建一个名为
    voids\u t
    的参数包,它只是
    s
    void
    s的列表。现在,技巧的核心是:

    template<std::size_t s, class T, class... pack_t>
    std::array<T, s>
    create_array_by_copy_helper(sized_pack<0, pack_t...> const&,
                                T const& o)
    { return { (pack_t(), o)... }; }
    
    template<std::size_t s, class T>
    std::array<T, s> create_array_by_copy(T const& o)
    {
        return create_array_by_copy_helper<s>(sized_pack<s>(), o);
    }
    
    它只是逗号运算符,因此返回
    o
    。我们在“模式”中插入了
    pack\u t
    (参数包),因此,当对表达式应用
    时,它将被逗号分隔的表达式替换,其中每个
    pack\u t
    外观将被参数包中的每个元素以相同的顺序替换,因此:

      { (pack_t(), o)... }
    
    转换为:

      { (void(), o), (void(), o), (void(), o), (void(), o), (void(), o) }
    
    初始化列表!!最后,每个元素只是一个后跟coma运算符的
    void
    表达式,逗号运算符只返回每对中的第二个元素。因此,求值表达式将为:

      return { o, o, o, o, o }; // With its corresponding calls to `forward`.
    
    我们想要的初始化列表

    例如:


    您只需要用list类替换类型
    T

    “每个列表的大小是在构造时指定的常量”-我真诚地希望您也指在编译时,对吗?否则,您可以从一开始就考虑使用
    std::array
    。列表的大小不是编译时常量。谢谢!我认为最简单的方法是存储指向常量大小列表的std::指针数组,然后使用new()创建具有适当大小的列表。我不得不担心新的ing和删除ing,但它保证了我所追求的尺寸possible@user1476176使用智能指针,它自己处理内存分配/释放。你为什么要重新发明std::make_integer_sequence?好的,我不知道它存在。无论如何,它是C++14的一个特性,而且一些编译器版本(如g++4.8.4)至今仍在使用,但还没有完全支持C++14.Cool!我接受这个答案,但你可能也有兴趣看到其他人对我问题的前一个化身给出的答案:我的答案中有一个错误。对象必须通过副本传递,因为不能将同一对象移动五次。这太危险了。我已经简化了解决方案,尽管我知道可以进一步简化。
      { (pack_t(), o)... }
    
      { (void(), o), (void(), o), (void(), o), (void(), o), (void(), o) }
    
      return { o, o, o, o, o }; // With its corresponding calls to `forward`.