在将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
此方法的副作用是两个(非const)CWiseUnaryViews的乘法也会失败,请参见此处的示例:https://godbolt.org/z/JYQb3d
答案 0 :(得分:2)
最重要的是,您正在调用常量实例的非常量方法。被调用的(第一个)coeffRef
是DenseCoeffsBase.h(DenseCoeffsBase<Derived, WriteAccessors>
)中的一个(也是唯一一个),它不是const限定的。 DenseCoeffsBase<Derived, ReadOnlyAccessors>
类没有coeffRef
方法。如果启用-fpermissive
编译器标志,则可以解决此错误(并得到警告)。
在密集情况下,您可能仍要使用operator()(Index, Index)
方法,该方法确实具有const限定版本。我只是注意到documentation明确表示无论如何都使用该方法,即使对于非const版本也是如此。显然,这不会返回const引用,但至少在您的示例中为double,这没有太大关系。
答案 1 :(得分:2)
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());
}