我希望编写一个constexpr函数,用于通过二元操作来将给定的std::array
缩减。也就是说,这个函数需要实现以下功能:
template <typename T, std::size_t N>
reduce(std::array<T, N>, binary_function);
为了简单起见,我想从加法开始讲解。例如:
sum(std::array<int, 5>{{1,2,3,4,5}}); // returns 15.
我已经得到的内容
我使用通常的索引技巧来索引数组元素。即生成一个 int
序列,可以用于参数列表扩展的索引。
template <int... Is>
struct seq {};
template <int I, int... Is>
struct gen_seq : gen_seq<I - 1, I - 1, Is...> {};
template <int... Is>
struct gen_seq<0, Is...> : seq<Is...> {}; // gen_seq<4> --> seq<0, 1, 2, 3>
然后通过可变模板递归定义了
sum
函数。// The edge-condition: array of one element.
template <typename T>
constexpr T sum(std::array<T, 1> arr, decltype(gen_seq<0>{})) {
return std::get<0>(arr);
}
// The recursion.
template <typename T, std::size_t N, int... Is>
constexpr auto sum(std::array<T, N> arr, seq<Is...>) -> decltype(T() + T()) {
return sum(std::array<T, N - 1>{ { std::get<Is>(arr)... } },
gen_seq<N - 2>()) +
std::get<N - 1>(arr);
}
// The interface - hides the indexing trick.
template <typename T, std::size_t N>
constexpr auto sum(std::array<T, N> arr)
-> decltype(sum(arr, gen_seq<N - 1>{})) {
return sum(arr, gen_seq<N - 1>{});
}
这里可以看到它的运行情况。
问题
这个实现方法有效。然而,在目前这个阶段,我有一些问题要问。
- 我是否可以以完美转发的方式将其添加到这个函数中?那样做是否有意义?或者我应该将那些数组声明为const-references?
- 到目前为止,假设归约的返回类型是
decltype(T() + T())
。即当你添加两个元素时得到的结果。虽然这对于大多数情况下的加法来说是正确的,但对于一般归约来说可能不再正确。有没有办法获取a[0]+(a[1]+(a[2]+...))
的类型?我尝试了类似这样的方法,但我不知道如何生成<T,T,T......>
的模板参数列表。
constexpr
的情况下才是这样的。 - iavr