编译时初始化元素含const成员的std::array:自定义to_array实现
编译时基于constexpr数组创建含const成员的静态数组的解决方案
你的问题核心在于:Foo包含const成员,编译器会自动删除它的默认赋值运算符(拷贝/移动赋值),同时Foo也无法默认构造(因为const成员没有默认初始化值)。原代码先默认构造std::array的元素再赋值,必然触发编译错误。
解决思路
跳过默认构造和赋值步骤,直接在编译时通过索引序列展开的方式,逐个构造Foo对象并初始化整个std::array,完全避免对赋值运算符的依赖。
修改后的代码
#include <array> #include <string_view> #include <utility> struct FooConfig { const std::string_view name; }; struct Foo { const std::string_view name; const unsigned index; void* owner; }; inline constexpr std::array foo_config = std::to_array<const FooConfig>( {{ .name = "A", }, { .name = "B", }, { .name = "C", },}); // 实现函数:利用索引序列展开构造每个元素 template<const decltype(foo_config)& arr, std::size_t... Idx> consteval auto make_foo_array_impl(std::index_sequence<Idx...>) { return std::array<Foo, arr.size()>{ // 逐个构造Foo对象,展开索引序列 Foo{.name = arr[Idx].name, .index = Idx, .owner = nullptr}... }; } // 对外接口:生成对应长度的索引序列并转发给实现函数 template<const decltype(foo_config)& arr> consteval auto make_foo_array() { return make_foo_array_impl<arr>(std::make_index_sequence<arr.size()>()); } inline auto foo_array = make_foo_array<foo_config>();
原理说明
std::make_index_sequence<arr.size()>()会在编译时生成一个包含0到arr.size()-1的索引序列- 通过参数包展开
Idx...,将每个索引对应的FooConfig转换为Foo对象,直接作为std::array的初始化列表 - 整个过程完全在编译期完成,既满足
consteval的要求,又避免了对Foo赋值/默认构造函数的依赖
内容的提问来源于stack exchange,提问作者JD.
相关产品推荐
相关产品推荐

