C++ 将存储在共享指针向量中的仿函数应用于 Eigen unaryExpr

C++ Apply a functor that is stored in a vector of shared pointers to Eigen unaryExpr

我有一个函子对象的共享指针向量:std::vector<std::shared_ptr<MyFunctor>>,我想将其中之一应用于本征 MatrixXd 对象中的所有元素。

抽象基础 class MyFunctor 定义了一个成员函数 operator(),它接受 returns 一个 double 并且是 const。派生 classes 实现函数。

unaryExpr 函数似乎是合适的,但我不太明白语法是否正确。

我正在尝试做类似的事情:

mat.unaryExpr( *(vectorOfFunctors[0]) );

我正在添加一个示例,其中包含我发现可行的解决方法。
这是针对 Windows 10、64 位上的 MSVC 2019 (16.2.5)。

#include <Eigen/Dense>
#include <vector>
#include <memory>

class MyFunctorBase {
public:
    virtual double operator()(double) const = 0;
    virtual std::string getName() const = 0;
};

class MyFunctor : public MyFunctorBase {
public:
    MyFunctor() {};
    std::string getName() const { return "MyFunctor"; }
    double operator()(double d) const { return d + 1; }
};

void func() {
    std::shared_ptr<MyFunctor> mf1(new MyFunctor());
    std::vector<std::shared_ptr<MyFunctorBase>> vectorOfFunctors;
    vectorOfFunctors.push_back(mf1);

    Eigen::MatrixXd A(2, 2);
    A << 1, 2,
         3, 4;

    //Method 1
    //Eigen::MatrixXd t0 = A.unaryExpr(*(vectorOfFunctors[0]));    //Does not compile

    //Method 2
    const MyFunctorBase& mfb = *(vectorOfFunctors[0]);       //Compiles
    Eigen::MatrixXd t2 = A.unaryExpr(std::ref(mfb));
}

Eigen 尝试实例化您传递给它的抽象仿函数的实例,因此出现编译错误。请注意,因为取消引用指针,所以将切片抽象对象传递给 unaryExpr 方法。您可以直接传入派生仿函数,或者 dynamic_cast 在取消引用之前传递给派生类型。

您使用 std::ref 获得预期行为的原因是它将 MyFunctorBase 包装在引用包装器中,因此在实例化时,您不会收到有关创建的错误一个抽象类型。稍后,当调用仿函数时,它隐式转换为 MyFunctorBase&,允许虚拟 operator() 调用。在此之后,您可以拥有一个 std::vector 的引用包装器 objs (std::vector<std::reference_wrapper<MyFunctorBase>>),而不是使用 std::ref.

手动包装容器中的每个元素

请注意,Eigen 矩阵提供了与 STL 算法兼容的迭代器,您可以使用 std::transform 实现相同的目标。