如何不借助中间数组实现模板参数包行优先转列优先
实现方案
可以通过将参数包转为tuple后直接按转置索引取值的方式,避免显式创建中间数组,参考实现如下:
#include <array> #include <tuple> #include <utility> template <typename T, std::size_t rows, std::size_t cols = rows> class Matrix final { public: std::array<T, cols * rows> m; // 列优先存储的矩阵 template <typename... A> constexpr Matrix(A&&... args) noexcept requires (sizeof...(A) == rows * cols) // 编译期校验参数数量匹配 : m{ [&]<std::size_t... i>(std::index_sequence<i...>, auto&& args_tuple) { // 直接按转置后的索引从tuple中取参数,无需中间数组 return std::array<T, cols * rows>{ std::get<(i % rows) * cols + i / rows>(std::forward<decltype(args_tuple)>(args_tuple))... }; }(std::make_index_sequence<rows * cols>{}, std::forward_as_tuple(std::forward<A>(args)...)) } {} };
方案说明
- 核心逻辑是用
std::forward_as_tuple把参数包直接打包为转发tuple,不需要额外拷贝参数到临时数组 - 借助C++20的模板lambda,直接在初始化列表中完成索引转置和元素取值,全程没有显式的中间数组生成
- 加入了requires约束做参数数量校验,避免参数个数不匹配时的异常编译报错
- 如果需要兼容C++17,只需要把lambda里的逻辑单独抽成静态模板成员函数即可,核心逻辑不需要改动
额外说明:如果编译器开启O2及以上优化,你原本实现中的临时数组会被编译器完全优化消除,运行时性能和无中间数组的版本没有任何区别,可以根据自己的版本兼容需求选择方案。
内容的提问来源于stack exchange,提问作者Elviss Strazdins
相关产品推荐
相关产品推荐

