首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何计算std::integral_constant元组的前缀和

如何计算std::integral_constant元组的前缀和
EN

Stack Overflow用户
提问于 2022-06-12 17:34:05
回答 1查看 67关注 0票数 1

我想计算一下std::integral_constants的前缀和。

给定的是std::integral_constantstd::tuple中的集合。

示例

代码语言:javascript
复制
using in_t = std::tuple<
    std::integral_constant<unsigned __int64,1>,
    std::integral_constant<unsigned __int64,1>,
    std::integral_constant<unsigned __int64,2>
>;

如何在编译时计算前缀和,最好是使用导出返回类型的函数的方式(因为模板元编程非常痛苦)?

代码语言:javascript
复制
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>());
}

返回类型应该如下所示

代码语言:javascript
复制
std::tuple<
    std::integral_constant<unsigned __int64,1>,
    std::integral_constant<unsigned __int64,2>,
    std::integral_constant<unsigned __int64,4>
>

我经历了各种失败尝试,比如递归方式,将I‘the部分和作为模板参数传递到下一个级别。考虑到最大递归深度,不确定这是否是一种好方法。

一个失败的例子是

代码语言:javascript
复制
template <std::size_t I=0, std::size_t Offset=0, typename Tuple>
constexpr auto prefixSumRecursive(Tuple t) {
    constexpr auto value = Offset + std::get<I>(t);
    constexpr auto tuple = std::make_tuple(std::integral_constant<std::size_t, value>{});
    if constexpr((I+1) < std::tuple_size_v<Tuple>) {
        return std::tuple_cat(tuple, prefixSumRecursive<I + 1, value>(t));
    }
    return tuple;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-12 18:09:33

标准中已经有一个前缀和的算法,即std::inclusive_scan

代码语言:javascript
复制
#include <numeric>
#include <array>
#include <tuple>

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

template<int... values>
constexpr auto prefixSum(
  std::tuple<std::integral_constant<int, values>...>) {
  constexpr auto out = [] {
    constexpr std::array in{values...};
    std::remove_const_t<decltype(in)> out{};
    std::inclusive_scan(in.begin(), in.end(), out.begin());
    return out;
  }();
  return [=]<auto... Is>(std::index_sequence<Is...>) {
    return std::tuple<std::integral_constant<int, out[Is]>...>{};
  }(std::make_index_sequence<out.size()>());
}

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

using out_t = decltype(prefixSum(in_t{}));

演示

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72594484

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档