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
实现相同的目标。
我有一个函子对象的共享指针向量: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
实现相同的目标。