You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用相同构造参数初始化带模板参数的无默认构造std::array?

如何初始化元素无默认构造函数的std::array(模板大小未知)

你遇到的问题很典型:当std::array的元素类型没有默认构造函数,而数组大小又是模板参数时,直接初始化会因为无法默认构造元素而触发编译错误。要把mAs里的所有A对象都初始化为A{b,c},我们可以利用编译期索引序列来实现,下面是几种可行的方案:

方案一:C++14及以上(兼容性最好)

我们可以借助std::index_sequence和模板构造函数,在编译期展开初始化每个元素:

#include <array>
#include <utility> // 引入std::index_sequence相关工具

struct A {
  A(int b, int c) : mb(b), mc(c) {}
  int mb;
  int mc;
};

template <size_t NR_A>
struct B {
private:
    // 辅助构造函数:利用编译期索引序列展开初始化
    template <size_t... Is>
    B(int b, int c, std::index_sequence<Is...>)
        : mAs{ (static_cast<void>(Is), A{b, c})... }
    {}
public:
    B(int b, int c)
        : B(b, c, std::make_index_sequence<NR_A>{})
    {}
    std::array<A, NR_A> mAs;
};

// 测试代码
B<3> inst(1, 1);

原理说明

  • std::make_index_sequence<NR_A>会生成一个包含0,1,...,NR_A-1的编译期索引序列;
  • 初始化列表里的(static_cast<void>(Is), A{b,c})利用逗号运算符忽略索引值,为每个位置构造一个A{b,c};
  • 展开后相当于显式写出A{b,c}, A{b,c}, ...(共NR_A次),完美绕过了std::array默认构造元素的需求。

方案二:C++20及以上(更简洁)

如果你能使用C++20,可以结合std::to_array和lambda表达式来实现:

#include <array>
#include <utility>

struct A {
  A(int b, int c) : mb(b), mc(c) {}
  int mb;
  int mc;
};

template <size_t NR_A>
struct B {
  B(int b, int c) : 
    mAs(std::to_array<A>([b,c]<size_t... Is>(std::index_sequence<Is...>) {
        return std::array{A{b,c}...};
    }(std::make_index_sequence<NR_A>{})))
  {}
  std::array<A, NR_A> mAs;
};

B<3> inst(1, 1);

为什么原代码会报错?

因为你自定义了A的构造函数,编译器不会再自动生成默认构造函数;而std::array的默认构造函数会尝试默认构造每个元素,这就导致std::array<A, 3UL>的默认构造函数被隐式删除,直接初始化自然会失败。我们的方案都是通过显式构造每个元素,避开了默认构造的要求。

内容的提问来源于stack exchange,提问作者Alex Darsonik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:10:40