我将coeffRef()
与CWiseUnaryView
函数一起使用时遇到了一些问题,但前提是该函数被声明为const
可重现的示例:
#include <Eigen/Core>
struct dummy_Op {
EIGEN_EMPTY_STRUCT_CTOR(dummy_Op)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE const double&
operator()(const double &v) const { return v; }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE double&
operator()(double &v) const { return v; }
};
void foo(Eigen::MatrixXd &out)
{
//Compiles
Eigen::CwiseUnaryView<dummy_Op, Eigen::MatrixXd> view(out);
view.coeffRef(0,0);
//Doesn't Compile
const Eigen::CwiseUnaryView<dummy_Op, Eigen::MatrixXd> const_view(out);
const_view.coeffRef(0,0);
}
返回:
<source>: In function 'void foo(Eigen::MatrixXd&)':
<source>:21:28: error: passing 'const Eigen::CwiseUnaryView<dummy_Op,
Eigen::Matrix<double, -1, -1> >' as 'this' argument discards qualifiers
[-fpermissive]
const_view.coeffRef(0,0);
^
In file included from /opt/compiler-explorer/libs/eigen/v3.3.4/Eigen/Core:413,
from <source>:1:
/opt/compiler-explorer/libs/eigen/v3.3.4/Eigen/src/Core/DenseCoeffsBase.h:340:33: note:
in call to 'Eigen::DenseCoeffsBase<Derived, 1>::Scalar&
Eigen::DenseCoeffsBase<Derived, 1>::coeffRef(Eigen::Index, Eigen::Index)
[with Derived = Eigen::CwiseUnaryView<dummy_Op, Eigen::Matrix<double,
-1, -1> >; Eigen::DenseCoeffsBase<Derived, 1>::Scalar = double; Eigen::Index = long int]'
EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
^~~~~~~~
Compiler returned: 1
编译器资源管理器:https://godbolt.org/z/kPHPuC
这样做的副作用是两个(非常量(CWiseUnaryViews的乘法也失败,请参阅以下示例:https://godbolt.org/z/JYQb3d
底线是你正在调用常量实例的非常量方法。被调用的(第一个(coeffRef
是DenseCoeffsBase.h(DenseCoeffsBase<Derived, WriteAccessors>
(中的一个(也是唯一一个(,它不合格。DenseCoeffsBase<Derived, ReadOnlyAccessors>
类没有coeffRef
方法。如果启用 -fpermissive
编译器标志,则可以绕过此错误(并收到警告(。
在密集的情况下,您可能仍然希望使用 operator()(Index, Index)
方法,该方法确实具有 const 限定版本。我刚刚注意到文档明确表示无论如何都要使用该方法,即使对于非 const 版本也是如此。这显然不会返回 const 引用,但至少在您的示例中作为双精度,它应该不会太重要。
CwiseUnaryView
旨在用于类似 L 值的表达式,例如
MatrixXcd A;
A.real() = something; // `A.real()` is writable
如果要应用元素级函子并将其用作 R 值,则应改用CwiseUnaryOp
:
void foo(Eigen::MatrixXd &out)
{
Eigen::CwiseUnaryOp<dummy_Op, Eigen::MatrixXd> view1(out);
// shorter:
auto view2 = out.unaryExpr(dummy_Op());
Eigen::MatrixXd result = view1 * view2;
// or directly write: out.unaryExpr(dummy_Op()) * out.unaryExpr(dummy_Op());
}