如何创建含不可默认初始化类型的空std::array?跨编译器兼容问题
解决MSVC下零长度std::array包含不可默认构造类型的问题
我太懂这个坑了——Clang和GCC对零长度std::array的处理完全贴合标准(毕竟零长度数组根本不需要构造任何元素),但MSVC在这方面的检查确实过于严格,会错误地要求元素类型必须具备默认构造能力。下面给你几个亲测可行的解决办法:
方法1:用双层大括号明确聚合初始化
把返回语句从return {};改成双层大括号的形式,因为std::array是聚合类型,内层空括号明确告诉MSVC:元素列表为空,不需要构造任何A对象。修改后的代码如下:
#include <array> struct A { A(double, int) {}; }; using Empty = std::array<A, 0>; inline const Empty GetChildren() { return Empty{{}}; }; // 双层大括号明确空元素列表 int main(int argc, char **argv) { const Empty& test(GetChildren()); for (const auto& a : GetChildren()) {} }
方法2:利用迭代器构造函数绕开检查
std::array支持用两个迭代器来构造,对于零长度数组来说,它的begin()和end()是同一个迭代器,用这两个迭代器构造时,完全不会触发元素类型的构造检查:
inline const Empty GetChildren() { return Empty(Empty::begin(), Empty::end()); };
方法3:C++20及以上用std::make_array简化
如果你的项目支持C++20标准,直接用std::make_array来创建零长度数组就行,它的类型推导逻辑能正确处理这种特殊场景:
#include <array> struct A { A(double, int) {}; }; using Empty = std::array<A, 0>; inline const Empty GetChildren() { return std::make_array<A>(); };
额外补充
其实根据C++标准,零长度的std::array<T, 0>是完全合法的,而且根本不需要T具备默认构造能力——因为它内部不包含任何T类型的对象。MSVC的这个行为属于实现上的过度严格检查(或者说小bug),上面的几种方法都是通过更明确的初始化方式,让MSVC跳过不必要的默认构造校验。
内容的提问来源于stack exchange,提问作者Bomaz
相关产品推荐
相关产品推荐

