对两个非默认可构造类型的 std::array 求和

问题描述 投票:0回答:3

如果我想写一个对两个

std::array
求和的函数,我会这样做:

template<class T, std::size_t N>
auto sum(const std::array<T, N>& a, const std::array<T, N>& b)
{
    std::array< decltype(a[0] + b[0]), N> result; //the underlying type is not necessarily T
    for (std::size_t i = 0; i < N; ++i)
    {
        result[i] = a[i] + b[i];
    }
    return result;
} 

如果

decltype(a[0] + b[0])
不可默认构造,我该如何编写这个函数?

这是编译器资源管理器的示例:https://godbolt.org/z/qndGfhehM

理想情况下,我想直接创建并初始化

std::array
,但我未能为任何
N
编写函数。

我只想依赖 C++ 标准。

我想可以通过中间

std::vector
来实现,但是需要副本。

我尝试编写一个递归模板函数,例如:

template<class T, std::size_t N>
auto operator+(const std::array<T, N>& a, const std::array<T, N>& b)
{
    if constexpr (N > 1)
    {
        return {a[0] + b[0], ???};
    }
    else
    {
        return {a[0] + b[0]};
    }
}

但我不知道该写什么来代替???

我知道

std::index_sequence
存在,但我不知道在这种情况下如何使用它。

c++ std
3个回答
10
投票

使用

std::index_sequence
是一个两步过程:

创建它并将其传递给使用索引来完成您的任务的助手。
具有显式模板参数的通用 lambda 就足够了(对于早期标准,使用普通函数和更多参数):

template <class T, std::size_t N>
auto operator+(const std::array<T, N>& a, const std::array<T, N>& b)
{
    return [&]<std::size_t... Is>(std::index_sequence<Is...>){
        return std::array<decltype(a[0] + b[0]), N>{(a[Is] + b[Is])...};
    }(std::make_index_sequence<N>());
}

6
投票

大致如下:

template <typename T, std::size_t N, std::size_t... Is>
auto sum_helper(const std::array<T, N>& a, const std::array<T, N>& b,
                std::index_sequence<Is...>) {
    return std::array<decltype(a[0] + b[0]), N>{(a[Is] + b[Is])...};
}

template<class T, std::size_t N>
auto sum(const std::array<T, N>& a, const std::array<T, N>& b)
{
    return sum_helper(a, b, std::make_index_sequence<N>{});
} 

演示


1
投票

要处理

decltype(a[0] + b[0])
不可默认构造的情况,您可以使用辅助函数和
std::index_sequence
来创建和初始化
std::array
。以下是如何实现此目标的示例:

#include <array>
#include <iostream>

// Helper function to initialize the array recursively
template <class T, std::size_t... Is>
constexpr auto sum_helper(const std::array<T, sizeof...(Is)>& a, const std::array<T, sizeof...(Is)>& b, std::index_sequence<Is...>)
{
    return std::array<T, sizeof...(Is)>{(a[Is] + b[Is])...};
}

// Main function that calls the helper with an index sequence
template <class T, std::size_t N>
constexpr auto sum(const std::array<T, N>& a, const std::array<T, N>& b)
{
    return sum_helper(a, b, std::make_index_sequence<N>());
}

int main()
{
    std::array<int, 3> arr1{1, 2, 3};
    std::array<int, 3> arr2{4, 5, 6};

    auto result = sum(arr1, arr2);

    for (const auto& elem : result)
    {
        std::cout << elem << " ";
    }

    return 0;
}

sum_helper
是一个递归函数,它采用两个数组(
a
b
)和代表索引的
index_sequence
。它使用表达式
(a[Is] + b[Is])...
递归地初始化结果数组的元素。

然后

sum

 函数使用 
std::make_index_sequence<N>()
 调用此辅助函数,该函数为给定数组大小 N 生成索引序列。这样,您就可以处理非默认可构造类型,而无需求助于中间 
std::vector
 或其他容器。

© www.soinside.com 2019 - 2024. All rights reserved.