如何编写含删除默认构造函数类数组的constexpr构造函数
解决删除默认构造函数后数组成员的初始化问题
你的分析完全正确:当B的构造函数未使用初始化列表初始化数组arr_时,编译器会先尝试默认初始化数组的每个元素,但A的默认构造函数已被删除,因此触发编译错误。构造函数体里的赋值操作是在初始化完成后执行的,无法绕过这一步。
以下是两种可行的解决方案,均能保持代码的constexpr特性:
方案1:利用索引序列初始化原生数组
通过模板构造函数配合std::index_sequence,在初始化列表中直接调用A的带参构造函数逐个初始化数组元素:
#include <utility> // 引入std::index_sequence相关工具 constexpr int data[] = {1,2,3,4,5}; constexpr size_t N = sizeof(data)/sizeof(int); struct A { A() = delete; constexpr A(int a): a_(a) {} private: int a_ = 0; }; struct B{ private: // 辅助模板构造函数,接收索引序列展开初始化 template<size_t... Is> constexpr B(std::index_sequence<Is...>) : arr_{A(data[Is])...} {} public: // 对外构造函数,生成对应长度的索引序列 constexpr B() : B(std::make_index_sequence<N>{}) {} private: A arr_[N]; };
方案2:改用std::array容器
如果允许替换原生数组为std::array,实现方式类似,代码可读性更好:
#include <utility> #include <array> constexpr int data[] = {1,2,3,4,5}; constexpr size_t N = sizeof(data)/sizeof(int); struct A { A() = delete; constexpr A(int a): a_(a) {} private: int a_ = 0; }; struct B{ private: template<size_t... Is> constexpr B(std::index_sequence<Is...>) : arr_{{A(data[Is])...}} {} public: constexpr B() : B(std::make_index_sequence<N>{}) {} private: std::array<A, N> arr_; };
核心原理:两种方案都是通过编译期的索引序列展开,直接在初始化列表中完成每个A对象的带参构造,完全跳过了默认构造的步骤,既满足constexpr要求,又规避了默认构造函数被删除的问题。
内容的提问来源于stack exchange,提问作者u0804138
相关产品推荐
相关产品推荐

