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

C++编译期计算std::integral_constant元组前缀和的方法

编译期计算std::integral_constant元组的前缀和

需求为对存储在std::tuple中的std::integral_constant序列做编译期前缀和计算,优先采用返回类型自动推导的函数实现,降低模板元编程编写复杂度。

输入输出示例

输入类型示例:

using in_t = std::tuple<
    std::integral_constant<unsigned __int64,1>,
    std::integral_constant<unsigned __int64,1>,
    std::integral_constant<unsigned __int64,2>
>;

期望返回类型:

std::tuple<
    std::integral_constant<unsigned __int64,1>,
    std::integral_constant<unsigned __int64,2>,
    std::integral_constant<unsigned __int64,4>
>;

给定函数框架:

template <typename Tuple>
constexpr decltype(auto) prefixSum(Tuple t) {
    // ?
}

int main () {
    using in_t = std::tuple<
        std::integral_constant<unsigned __int64,1>,
        std::integral_constant<unsigned __int64,1>,
        std::integral_constant<unsigned __int64,2>
    >;
    
    using out_t = decltype(prefixSum<in_t>());
}

原有实现的问题

你之前写的递归实现存在两个核心问题:

  • 硬编码值类型为std::size_t,和输入的unsigned __int64类型不匹配
  • 手动递归传递偏移量的写法冗余,且容易触发模板递归深度限制,实际上用索引序列+折叠表达式的写法可以完全规避这些问题。

可直接运行的实现(C++20)

以下实现完全匹配给定框架,自动推导返回类型,无需手动写模板特化,支持任意数值类型的std::integral_constant元组:

#include <tuple>
#include <cstdint>
#include <utility>
#include <type_traits>

template <typename Tuple, std::size_t... Is>
constexpr auto prefixSumImpl(Tuple&& t, std::index_sequence<Is...>) {
    constexpr auto calcUpToIdx = []<std::size_t I>(std::integral_constant<std::size_t, I>, auto&& tuple) {
        using ValueType = typename std::tuple_element_t<0, std::remove_cvref_t<decltype(tuple)>>::value_type;
        return [&tuple]<std::size_t... Js>(std::index_sequence<Js...>) {
            return std::integral_constant<ValueType, (std::get<Js>(tuple).value + ... + ValueType{0})>{};
        }(std::make_index_sequence<I + 1>{});
    };
    return std::make_tuple(calcUpToIdx(std::integral_constant<std::size_t, Is>{}, std::forward<Tuple>(t))...);
}

template <typename Tuple>
constexpr decltype(auto) prefixSum(Tuple&& t = {}) {
    return prefixSumImpl(std::forward<Tuple>(t), 
        std::make_index_sequence<std::tuple_size_v<std::remove_cvref_t<Tuple>>>{});
}

// 验证用例
int main () {
    using in_t = std::tuple<
        std::integral_constant<unsigned __int64,1>,
        std::integral_constant<unsigned __int64,1>,
        std::integral_constant<unsigned __int64,2>
    >;
    
    using out_t = decltype(prefixSum<in_t>());
    // 编译期校验结果类型完全符合预期
    static_assert(std::is_same_v<out_t,
        std::tuple<
            std::integral_constant<unsigned __int64,1>,
            std::integral_constant<unsigned __int64,2>,
            std::integral_constant<unsigned __int64,4>
        >>);
}

实现说明

  • 基于std::index_sequence做元组索引展开,没有手动递归逻辑,编译器对索引序列的展开深度支持远高于手动模板递归的默认阈值,常规长度的元组不会触发深度限制
  • 自动从元组第一个元素提取值类型,不会出现硬编码类型和输入不匹配的问题
  • 所有计算完全在编译期完成,返回的每个元素都是对应前缀和值的std::integral_constant实例,类型完全匹配预期
  • 给入参加了默认值,支持prefixSum<in_t>()的空参调用写法,完全符合给定的函数框架要求

内容的提问来源于stack exchange,提问作者Chris G.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 20:45:36