如果我想写一个对两个
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
存在,但我不知道在这种情况下如何使用它。
使用
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>());
}
大致如下:
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>{});
}
要处理
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
或其他容器。