将coeffRef与const CwiseUnaryView结合使用-将两个CWiseUnaryViews相乘时失败

时间:2019-06-17 16:09:22

标签: eigen eigen3

在将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

2 个答案:

答案 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());
}