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

如何实现可拼接任意std::array的constexpr函数,最小化构造调用

实现方案

完全可以实现,借助C++17及以上的折叠表达式、std::index_sequence和完美转发特性,无需手动编写多参数版本。以下是符合所有要求的实现:

完整代码

#include <array>
#include <utility>
#include <tuple>
#include <type_traits>

namespace detail {
    // 辅助函数:转发单个数组的所有元素,保留值类别
    template <typename Array, std::size_t... Idx>
    constexpr auto forward_elements(Array&& arr, std::index_sequence<Idx...>) {
        return std::initializer_list<std::remove_reference_t<typename Array::value_type>>{
            std::forward<decltype(arr[Idx])>(arr[Idx])...
        };
    }

    // 折叠所有数组的元素列表,合并为一个初始化列表
    template <typename... Arrays>
    constexpr auto concat_elements(Arrays&&... arrays) {
        using ElementType = typename std::remove_reference_t<std::tuple_element_t<0, std::tuple<Arrays...>>>::value_type;
        return std::initializer_list<ElementType>{
            forward_elements(std::forward<Arrays>(arrays), 
                            std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Arrays>>>{}).begin()...,
            ...
        };
    }
} // namespace detail

template <typename... Arrays>
constexpr auto concat(Arrays&&... arrays) {
    using ElementType = typename std::remove_reference_t<std::tuple_element_t<0, std::tuple<Arrays...>>>::value_type;
    constexpr std::size_t TotalSize = (std::tuple_size_v<std::remove_reference_t<Arrays>> + ...);
    
    return std::array<ElementType, TotalSize>{
        detail::concat_elements(std::forward<Arrays>(arrays)...)
    };
}

关键特性解释

  1. 混合引用支持:通过万能引用Arrays&&...和std::forward实现对左值、右值数组的完美转发,元素的拷贝/移动语义完全匹配原数组。
  2. 总大小计算:使用C++17折叠表达式(std::tuple_size_v<...> + ...)直接计算所有数组的大小总和,无需递归逻辑。
  3. 单次构造保证:每个元素通过std::forward直接转发到目标数组的初始化列表,仅触发一次拷贝或移动构造,无额外临时对象产生。
  4. 非默认构造兼容:目标数组通过初始化列表直接构造元素,完全依赖原数组的元素拷贝/移动,不要求ELEMENT支持默认构造。

验证示例

struct NonDefaultConstructible {
    int val;
    constexpr NonDefaultConstructible(int v) : val(v) {}
    NonDefaultConstructible(const NonDefaultConstructible&) = default;
    NonDefaultConstructible(NonDefaultConstructible&&) = default;
};

constexpr std::array<NonDefaultConstructible, 2> arr1 = {NonDefaultConstructible(1), NonDefaultConstructible(2)};
constexpr std::array<NonDefaultConstructible, 3> arr2 = {NonDefaultConstructible(3), NonDefaultConstructible(4), NonDefaultConstructible(5)};

constexpr auto result = concat(arr1, std::move(arr2));
static_assert(result.size() == 5);
static_assert(result[0].val == 1);
static_assert(result[4].val == 5);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 18:07:05