【问题标题】:How to get rid of "invalid use of incomplete type" when using CwiseBinaryOp in Eigen在 Eigen 中使用 CwiseBinaryOp 时如何摆脱“不完整类型的无效使用”
【发布时间】:2015-10-22 16:47:32
【问题描述】:

我正在尝试用我自己的函数替换 Eigen 中 3x1 向量之和的函数。例如,

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

我希望 q3 是我自己的函数计算出来的。

由于 Eigen 实际上是通过 operator= 而不是 operator+ 来计算总和,并且 operator+ 只返回一个 CwiseBinaryOp 对象,所以我需要重载 operator=。

现在我正在使用 EIGEN_MATRIX_PLUGIN marco 将我的代码添加到 Eigen 的 Matrix.h:

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;
}

我自己的函数需要访问指向q、q2和q3的数据的指针。但是在尝试通过CwiseBinaryOp对象访问q和q2的数据时出现如下错误。

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;

我想知道为什么会出现这个错误以及如何摆脱它。

【问题讨论】:

  • 好吧,我也尝试了 Džanan 在 VS 2015 中所说的,效果很好。我在使用 g++ 时遇到了错误,我不得不使用它。但是这个问题怎么可能和编译器有关系呢?

标签: c++ templates operator-overloading eigen


【解决方案1】:

我不确定你那边出了什么问题,但我通过以下方式让它工作:

MatrixAddons.h

这是包含 operator= 定义的标头,您打算将其放置在 Eigen::Matrix 类中。

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

EIGEN_MATRIX_PLUGIN 定义为指向MatrixAddons.h 标头的标头。

#define EIGEN_MATRIX_PLUGIN "MatrixAddons.h"

ma​​in.cpp

用于测试扩展Eigen::Matrix类的C++源代码。

#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;
}

一点调试(或从新的operator= 记录)表明新添加的运算符作为q3 = q1 + q2 语句的一部分被调用。

【讨论】:

  • 我使用了与您完全相同的文件,但仍然出现此错误。编译的时候加了一些flag吗?
  • 并非如此。我用 MSVC 14.0 (VS 2015) 编译了这个东西,如果这对你有帮助的话。
  • 但我必须使用 g++。那么你知道为什么这个错误与编译器有关吗?
【解决方案2】:

使用 g++,尝试只运行预处理器 (-E)。检查输出时,您会注意到 operator= 函数出现在 Matrix 类的定义中间(类声明开始大约 500 行)。 CwiseBinaryOp 类的声明出现在上面(大约 5,000 行以上),但未定义。对于您的版本,编译器需要在 operator= 函数中使用 CwiseBinaryOp 的定义,但尚未定义。它适用于 MSVC 而不是 g++ 的原因可能是由于 MSVC 的“损坏的”两阶段模板名称查找(我可能在这方面错了。请参阅 here 了解为什么 MSVC 接受代码而不是 g++)。

你可以让 g++ 通过改变它来编译你的函数:

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;
}

在这种情况下,operator= 函数直到在 CwiseBinaryOp 类的定义之后(在 operator= 定义之后大约 3,000 行)第一次使用时才被“定义”。

【讨论】:

  • 感谢您指出此错误的原因。我认为我的问题是我尝试使用 op.lhs(),但根据预处理器的结果,声明了 CwiseBinaryOp 但此时未定义。所以编译器不知道 lhs() 是什么。我的解决方案只是将我的函数声明留在这里,并在定义 CwiseBinaryOp 之后将定义放在另一个地方。但是我还是不明白为什么你的代码在没有定义 CwiseBinary 的情况下可以访问 op.lhs()。
  • 你是对的。这是CwiseBinaryOp,而不是我最初所说的Matrix。然而,原因仍然相同。将其声明为模板有帮助的原因是,在代码中解析模板的位置是调用 operator= 函数的位置,而不是原始情况,它需要在函数定义。
猜你喜欢
  • 1970-01-01
  • 2010-10-13
  • 2017-10-24
  • 2013-05-19
  • 2016-04-06
  • 2017-07-28
  • 1970-01-01
  • 2012-10-07
相关资源
最近更新 更多