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

如何使用参数包构造元素无默认构造函数的定长std::array

实现方案

完全可以实现,核心思路是借助编译期整数序列std::index_sequence生成N个重复的初始化构造调用,不同C++标准的实现方式如下:

C++20 及以上版本(最简洁)

直接用std::make_index_sequence配合lambda展开即可:

#include <array>
#include <utility>

template <typename T, size_t N, typename... Args>
constexpr std::array<T, N> buildArray(Args&&... args)
{
    // 生成长度为N的编译期整数序列,每个位置对应一次T对象构造
    return []<size_t... Is>(std::index_sequence<Is...>, auto&&... initArgs) {
        return std::array<T, N>{(static_cast<void>(Is), T{std::forward<Args>(initArgs)...})...};
    }(std::make_index_sequence<N>{}, std::forward<Args>(args)...);
}

使用时直接指定模板参数即可适配你的场景:

// 生成64个用{init1, init2}初始化的kissfft<float>对象
std::array<kissfft<float>, 64> myArray = buildArray<kissfft<float>, 64>(init1, init2);

其中(static_cast<void>(Is), T{...})的写法是为了避免编译器告警未使用的Is参数,同时保证构造顺序符合预期。

C++11/14/17 兼容版本

如果使用旧标准,需要额外加一层辅助函数处理整数序列展开:

#include <array>
#include <utility>

namespace detail {
template <typename T, size_t... Is, typename... Args>
constexpr std::array<T, sizeof...(Is)> buildArrayImpl(std::index_sequence<Is...>, Args&&... args)
{
    return std::array<T, sizeof...(Is)>{(static_cast<void>(Is), T{std::forward<Args>(args)...})...};
}
}

template <typename T, size_t N, typename... Args>
constexpr std::array<T, N> buildArray(Args&&... args)
{
    return detail::buildArrayImpl<T>(std::make_index_sequence<N>{}, std::forward<Args>(args)...);
}

使用方式和C++20版本完全一致。

原理解释

std::make_index_sequence<N>会生成类型为std::index_sequence<0,1,2,...,N-1>的编译期整数序列,模板参数包展开时,序列里的每一个整数都会对应一次T{init1, init2}的构造调用,刚好填充std::array的N个元素,完全不需要元素类型支持默认构造函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 21:45:00