如何将函数应用于数组中的所有元素(在C++模板类中)

Har*_*rry 5 c++ templates function-pointers

我有一个存储数字数组的模板类,我想将现有(标量)函数应用于每个元素.例如,如果我们假设我的类是std :: vector,那么我希望能够在所有元素上调用(例如)std :: cos函数.

也许一个电话看起来像这样:

std::vector<float> A(3, 0.1f);
std::vector<float> B = vector_function(std::cos, A);
Run Code Online (Sandbox Code Playgroud)

注意我还必须处理std :: complex <>类型(为其调用适当的复杂std :: cos函数).

我发现这个答案建议将函数类型作为模板参数:

template<typename T, typename F>
std::vector<T> vector_function(F func, std::vector<T> x)
Run Code Online (Sandbox Code Playgroud)

但是,我根本无法使用它(可能是因为像std :: sin和std :: cos这样的函数都是模板化和重载的?).

我也尝试过使用std::transform,但很快变得非常难看.对于非复杂类型,我设法使用typedef使其工作:

std::vector<float> A(2, -1.23f);
typedef float (*func_ptr)(float);
std::transform(A.begin(), A.end(), A.begin(), (func_ptr) std::abs);
Run Code Online (Sandbox Code Playgroud)

但是,尝试使用std :: complex <>类型的相同技巧会导致运行时崩溃.

有没有一个很好的方法让这个工作?多年来我一直坚持这一点.

rwo*_*ols 6

我仍然认为你应该使用std::transform

template <class OutputIter, class UnaryFunction>
void apply_pointwise(OutputIter first, OutputIter last, UnaryFunction f)
{
    std::transform(first, last, first, f);
}
Run Code Online (Sandbox Code Playgroud)

该函数不仅适用于std::vector类型,而且适用于任何具有begin()和成员函数的容器,甚至在自由函数和end()的帮助下也适用于 C 风格数组。一元函数可以是任何自由函数、函子对象、lambda 表达式甚至类的成员函数。std::beginstd::end

至于 的问题std::sin,这个自由函数是模板化的,因此编译器无法知道您需要哪个模板实例化。

如果您可以访问 C++11,则只需使用 lambda 表达式:

std::vector<float> v;
// ...
apply_pointwise(v.begin(), v.end(), [](const float f)
{
    return std::sin(f);
});
Run Code Online (Sandbox Code Playgroud)

这样,编译器就知道它应该替换T=float为模板参数。

如果你可以使用 C 函数,你也可以使用 function sinf,它不是模板化的并且接受 afloat作为参数:

apply_pointwise(v.begin(), v.end(), sinf);
Run Code Online (Sandbox Code Playgroud)