在 transform() 中调用成员函数

Calling member function in transform()

所以我一直在尝试使用转换函数从 2 个现有向量创建一个向量。我在没有 类 的情况下成功地做到了,但现在我想使用 类 并且出现错误。下面的代码只是我项目的一小部分相关部分,所以它可能看起来很愚蠢,但最终整个事情实际上是有意义的。

这是我的头文件的一部分:

#include <vector>
#include <algorithm>

class Example
{
public:
    double multiply(double x, double y);
    void generate_amplitude(std::vector<double>& ampVec);
};

还有我的 .cpp 文件的一些内容:

#include "example.h"

double Example::multiply(double x, double y)
{
    return x*y;
}

void Example::generate_amplitude(std::vector<double>& ampVec)
{
    double const a = 3.14;
    int const lenVectors = 10;

    std::vector<double> timeVec = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}
    std::vector<double> ampVec(lenVectors);
    std::vector<double> aVec(lenVectors, a);

    // Fill ampVec with timeVec[i]*aVec[i] for i in range[0:lenVectors[
    transform(timeVec.begin(), timeVec.end(), aVec.begin(), ampVec.begin(), multipy);
}

所以当我尝试编译时,我得到:

error: must use '.*' or '->*' to call pointer-to-member function in '__binary_op (...)', e.g. '(... ->* __binary_op) (...)'

我确实搜索并阅读了数小时有关指向成员函数的指针,尝试了几种不同的方法,例如:

double (Example::*pmf)(double, double);
pmf = &Example::multiply;
transform(timeVec.begin(), timeVec.end(), aVec.begin(), ampVec.begin(), this->*pmf);

但我对此还是个新手,找不到让它发挥作用的方法。这个特定的例子返回了那种消息:

error: no matching function for call to 'transform(std::vector<double>::iterator, std::vector<double>::iterator, std::vector<double>::iterator, std::vector<double>::iterator, double (Example::)(double, double))'
note: candidate: 'template<class _IIter, class _OIter, class _UnaryOperation> _OIter std::transform(_IIter, _IIter, _OIter, _UnaryOperation)'
note:   candidate expects 4 arguments, 5 provided
note:   template argument deduction/substitution failed
note: candidate: 'template<class _IIter1, class _IIter2, class _OIter, class _BinaryOperation> _OIter std::transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation)'
note:   member function type 'double (Example::)(double, double)' is not a valid template argument

不胜感激!

解决此问题的最简单方法是使用 lambda:

transform(
    timeVec.begin(), timeVec.end(),
    aVec.begin(),
    ampVec.begin(),
    [this](double a, double b) { return multiply(a, b); }
);

你不能在这里使用指向成员函数的指针,因为你需要 this 指针来调用指向成员函数的指针,而 std::transform() 没有提供此信息的机制。用 lambda 捕获它通过使 this 成为函子状态的一部分来解决这个问题。

您可以通过编写自定义函子在 C++03 中做类似的事情:

class ExampleMultiply {
public:
    explicit ExampleMultiply(Example &p) : example(p) {}

    double operator()(double a, double b) const {
        return example.multiply(a, b);
    }

private:
    Example &example;
};

然后用这个仿函数调用 std::transform()

transform(
    timeVec.begin(), timeVec.end(),
    aVec.begin(),
    ampVec.begin(),
    ExampleMultiply(*this)
);

在幕后,这基本上就是编译器为实现 lambda 表达式而生成的内容。