Я пишу библиотеку, в которой шаблоны Eigen-выражений хранятся как переменные-члены для выполнения сложных вычислений, необходимых для этого. Тем не менее, похоже, что я не могу сохранить или вернуть эти шаблоны выражений, если они не конвертированы напрямую в MatrixXd или тому подобное. Это заставляет каждый шаг быть сохраненным во времени и разрушает эффективность всего проекта.
Вот короткий пример, который вызывает проблемы. Holder просто содержит собственную матрицу, а Summer берет два держателя и выводит сумму двух матриц, которые они хранят при вызове get (). Следующий тест не пройден (segfault или std :: bad_alloc), когда шаблон выражения суммы оценивается в матрицу.
Включить файл
#ifndef PB_SIMPLE_H
#define PB_SIMPLE_H
#include <Eigen/Dense>
template <class EigenType>
class Holder {
public:
typedef EigenType result_type;
private:
result_type in_;
public:
Holder(const EigenType& in) : in_(in) {}
result_type get() const { return in_; }
};
template <class HoldLeft, class HoldRight>
class Summer {
public:
typedef const typename Eigen::CwiseBinaryOp<
Eigen::internal::scalar_sum_op<double>,
const typename HoldLeft::result_type,
const typename HoldRight::result_type> result_type;
// typedef Eigen::MatrixXd result_type;
private:
HoldLeft left_;
HoldRight right_;
public:
Summer(const HoldLeft& left, const HoldRight& right)
: left_(left), right_(right) {}
result_type get() const { return left_.get() + right_.get(); }
};
typedef Holder<Eigen::MatrixXd> MatrixHolder;
typedef Summer<MatrixHolder, MatrixHolder> MatrixSummer;
#endif /* PB_SIMPLE_H */
простой тест
#include "PbSimple.h"
#include <Eigen/Dense>
int main(int, char * []) {
const unsigned int szx=10,szy=3;
Eigen::MatrixXd x(Eigen::MatrixXd::Constant(szx,szy,1));
MatrixHolder vx(x);
Eigen::MatrixXd y(Eigen::MatrixXd::Constant(szx,szy,2));
MatrixHolder vy(y);
MatrixSummer vsum(vx,vy);
auto expr = vsum.get();
MatrixHolder vz(expr); //force evaluation of sum into new matrix, fails here
return 0;
}
Это потому что Holder::get
возвращает копию матрицы как временную. Затем этот временный объект сохраняется как постоянная ссылка CWiseBinaryOp
объект, возвращенный Summer::get
, то этот временный удаляется, и, наконец, когда expr
оценивается, expr
ссылается на удаленные объекты. Вы можете решить эту проблему, сделав Holder::get
возвращает постоянную ссылку на матрицу.
Других решений пока нет …