给出一个二进制仿函数(或类似仿函数的)对象,该对象采用两个T*
类型和一个大小的数组并返回T*
,这是将该仿函数应用于对象中每个对象的一种规范方法数组,返回一个新数组?
即,与以下内容相同,但更短,更不容易出错:
template<typename T, typename O>
T* apply(const T* a1, const T* a2, size_t size, O op) {
T* out = new[size];
for (size_t i = 0; i < size; i++) {
out[i] = op(a1[i], a2[i]);
}
return out;
}
对于输出分配的详细信息,我不太担心。在上面的示例中,它是在堆上分配的,但也许其他变体会覆盖其中一个输入或写入提供的缓冲区,或者它正在使用std::array<>
并返回它,依此类推。
答案 0 :(得分:2)
您提到要使用数组,但是要使用带有迭代器/指针的函数,在该函数中,我们已经丢失了数组的类型信息,类似于C风格的C风格的C风格的指针衰减数组参数。
如果适用(在调用网站的限制下),您可以改而使用std::array
来避免丢失大小信息,同时仍在编写大小不可知的函数模板时,必须约束两个数组参数大小相同(在执行典型的zip和map操作时,我们可以预期到此大小)。
例如使用std::transform
将二进制运算符应用于to数组参数中的成对元素:
#include <algorithm>
#include <array>
#include <iostream>
template <typename T, typename BinaryOperator, std::size_t N>
auto apply(const std::array<T, N>& arr1, const std::array<T, N>& arr2,
const BinaryOperator& op) {
std::array<T, N> result{};
std::transform(arr1.begin(), arr1.end(), arr2.begin(), result.begin(), op);
return result;
}
int main() {
const std::array<int, 5> arr1 = {1, 2, 3, 4, 5};
const std::array<int, 5> arr2 = {6, 7, 8, 9, 10};
const auto results = apply(arr1, arr2, [](int i, int j) { return i + j; });
for (const auto num : results) {
std::cout << num << " ";
} // 7 9 11 13 15
}
或者,如果您使用的是C ++ 14,则将std::integer_sequence
与参数包扩展结合使用:
#include <array>
#include <iostream>
#include <utility>
namespace detail {
template <typename Array, typename BinaryOperator, std::size_t... I>
Array apply_impl(const Array& arr1, const Array& arr2, const BinaryOperator& op,
std::index_sequence<I...>) {
return {op(arr1[I], arr2[I])...};
}
}
template <typename T, typename BinaryOperator, std::size_t N,
typename Indices = std::make_index_sequence<N>>
auto apply(const std::array<T, N>& arr1, const std::array<T, N>& arr2,
const BinaryOperator& op) {
return detail::apply_impl(arr1, arr2, op, Indices{});
}
int main() {
const std::array<int, 5> arr1 = {1, 2, 3, 4, 5};
const std::array<int, 5> arr2 = {6, 7, 8, 9, 10};
const auto results = apply(arr1, arr2, [](int i, int j) { return i + j; });
for (const auto num : results) {
std::cout << num << " ";
} // 7 9 11 13 15
}