所以我偶然发现了这个Eigen的编译问题,我使用的是Eigen 3.3.4,在Linux上用gcc 8.4.0编译。我使用Eigen 3.3.4,在Linux上用gcc 8.4.0编译。基本上我有一个定义的类,继承于 Eigen::VectorXd
看起来像这样
class dVector : public Eigen::VectorXd {
public:
dVector() : Eigen::VectorXd() { setZero(); }
dVector(int n) : Eigen::VectorXd(n) { setZero(); }
dVector(const Eigen::VectorXd& v) : Eigen::VectorXd(v) {}
dVector(const dVector& v) : Eigen::VectorXd(v) {}
dVector& operator=(const Eigen::VectorXd& v) {
Eigen::VectorXd::operator=(v);
return *this;
}
dVector& operator=(const dVector& v) {
Eigen::VectorXd::operator=(v);
return *this;
}
...
};
然后在我的代码中,我是这样使用的。
static dVector a(100);
// do something with a
dVector b = -a; // <--- won't compile
dVector b = dVector(-a); <---- compiles
第二行最后一行没有编译,给出了通常的Eigen错误信息。
error: no viable conversion from 'const Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1>>::NegativeReturnType'
(aka 'const CwiseUnaryOp<scalar_opposite_op<double>,
const Eigen::Matrix<double, -1, 1, 0, -1, 1> >') to 'dVector'
现在我很感兴趣的原因是 这个程序在Linux上不能编译 但在Windows上却能用MSVC编译。
我真的不明白为什么这个不能编译,我怀疑这与隐式转换有关,或者说与以下操作有关 -a
实际返回;也许这不是一个 dVector
但一个操作树。还没有完全掌握Eigen背后的情况。
那么就有两个问题。
为什么 dVector b = -a;
编译?
MSVC编译器做了什么不同的事情,让它可以接受gcc拒绝的任何东西?
operator-(dVector)
不存在,但 Eigen::VectorXd
是一个公共基础的 dVector
因此 Eigen::operator-(Eigen::VectorXd)
被选为 -a
.
这个运算符不返回一个 Eigen::VectorXd
但包装型可转换为 Eigen::VectorXd
. 该包装类型不能转换为 dVector
因为它需要转换为 Eigen::VectorXd
首先。
如果你尝试 dVector b = Eigen::VectorXd(-a)
同理 dVector b = dVector(-a)
工作。
解决方案:我不建议公开继承自 Eigen::VectorXd
使用合成。
解决方案2:实现 operator-(dVector)
. 现在编译器会选择这个操作符来代替。
解决方案3:实现 operator=(Eigen::VectorXd)
. 返回类型 Eigen::operator-(Eigen::VectorXd)
可转换为 Eigen::VectorXd
因此可以分配给 dVector
.
MSVC要么有一个bug,要么有一个语言扩展,使得这个编译。