简体   繁体   中英

How to get rid of "invalid use of incomplete type" when using CwiseBinaryOp in Eigen

I'm trying to replace the function for the sum of 3x1 Vector in Eigen with my own function. For example,

Matrix<float, 3, 1> q, q2, q3;
q.setRandom();
q2.setRandom();
q3.setRandom();
q3 = q + q2;

I hope that q3 is computed by my own function.

Since Eigen actually computes the sum by the operator= instead of operator+, and operator+ just returns a CwiseBinaryOp objects, I need to do overload the operator=.

Now I'm using EIGEN_MATRIX_PLUGIN marco to add my code to the Matrix.h of Eigen:

inline Matrix<float, 3, 1> &operator=(
const CwiseBinaryOp<internal::scalar_sum_op<float>, const Matrix<float, 3, 1>, const Matrix<float, 3, 1>>
    &op) {
    float *t = m_storage.data();
    op.lhs(); //error here
    return *this;
}

My own function needs to access the pointer to the data of q, q2 and q3. But I got the following error when trying to access the data of q and q2 by the CwiseBinaryOp object.

In file included from /home/tong/Program/Eigen/Eigen/src/Core/Matrix.h:340:0,
                 from /home/tong/Program/Eigen/Eigen/Core:294,
                 from /home/tong/Program/Eigen/Eigen/Dense:1,
                 from /home/tong/ClionProjects/EigenTest/main.cpp:7:
/home/tong/ClionProjects/EigenTest/MatrixAddon.h: In member function ‘Eigen::Matrix<float, 3, 1>& Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::operator=(const Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<float>, const Eigen::Matrix<float, 3, 1>, const Eigen::Matrix<float, 3, 1> >&)’:
/home/tong/ClionProjects/EigenTest/MatrixAddon.h:12:7: error: invalid use of incomplete type ‘const class Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<float>, const Eigen::Matrix<float, 3, 1>, const Eigen::Matrix<float, 3, 1> >’
     op.lhs();
       ^
In file included from /home/tong/Program/Eigen/Eigen/Core:252:0,
                 from /home/tong/Program/Eigen/Eigen/Dense:1,
                 from /home/tong/ClionProjects/EigenTest/main.cpp:7:
/home/tong/Program/Eigen/Eigen/src/Core/util/ForwardDeclarations.h:89:65: error: declaration of ‘const class Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<float>, const Eigen::Matrix<float, 3, 1>, const Eigen::Matrix<float, 3, 1> >’
 template<typename BinaryOp,  typename Lhs, typename Rhs>  class CwiseBinaryOp;

I wonder why does this error appear and how to get rid of it.

I'm not sure what went wrong at your side, but I got it to work in the following way:

MatrixAddons.h

This is header that contains the definition of the operator= that you intend to place within Eigen::Matrix class.

Matrix<float, 3, 1>& operator=(
    const CwiseBinaryOp<internal::scalar_sum_op<float>, const Matrix<float,
    3, 1>, const Matrix<float, 3, 1>>& op)
{
    float *t = m_storage.data();
    op.lhs();
    return *this;
}

config.h

Header that defines the EIGEN_MATRIX_PLUGIN to point to the MatrixAddons.h header.

#define EIGEN_MATRIX_PLUGIN "MatrixAddons.h"

main.cpp

C++ source used to test the expanded Eigen::Matrix class.

#include <iostream>
#include "config.h"
#include "Eigen/Core"

int main()
{
    Eigen::Matrix<float, 3, 1> q1, q2, q3;
    q1.setRandom();
    q2.setRandom();
    q3 = q1 + q2;
    std::cout << q3 << std::endl;
}

A bit of debugging (or logging from new operator= ) shows that newly added operator is invoked as part of q3 = q1 + q2 statement.

With g++, try running just the preprocessor ( -E ). When examining the output, you'll note that your operator= function appears in the middle of the definition of the Matrix class (the class declaration starts about 500 lines up). The declaration of the CwiseBinaryOp class appears above (about 5,000 lines above that) but is undefined. With your version, the compiler needs to use the definition of CwiseBinaryOp in the operator= function but it is not yet defined. The reason it works with MSVC and not g++ might be due to MSVC's "broken" two-phase template name lookup (I could be wrong on this. See eg here as to why MSVC accepts the code as opposed to g++).

You could get g++ to compile your function by changing it like so:

template <typename T>
Matrix<T, 3, 1>& operator=(
    const CwiseBinaryOp<
        internal::scalar_sum_op<T>,
        const Matrix<T, 3, 1>,
        const Matrix<T, 3, 1>
        > & op)
{
    std::cout << "Custom thingy\n";
    T *t = m_storage.data();
    op.lhs();
    return *this;
}

In this case, the operator= function is not "defined" until it's first use which is after the definition of the CwiseBinaryOp class (about 3,000 lines after the operator= definition).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM