反转 Eigen::VectorXd 并分配给另一个 Eigen::VectorXd

Invert a Eigen::VectorXd and assign to another Eigen::VectorXd

所以我偶然发现了 Eigen 的这个编译问题。我正在使用 Eigen 3.3.4 并使用 gcc 8.4.0 在 Linux 上编译。 基本上我有一个定义的 class 继承自 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 上编译,但它使用 MSVC 在 Windows 上编译。

我真的不明白为什么这不能编译,我怀疑它与隐式转换或操作 -a 实际上 returns 有什么关系;也许它不是 dVector 而是操作树。还没有完全掌握 Eigen 幕后发生的事情。

那么两个问题:

  1. 为什么dVector b = -a;编译不了?

  2. MSVC 编译器做了什么不同的事情来允许它接受 gcc 拒绝的任何内容?

operator-(dVector) 不存在,但 Eigen::VectorXddVector 的 public 基,因此 Eigen::operator-(Eigen::VectorXd) 被选为 -a

此运算符不是 return Eigen::VectorXd 而是包装类型可转换 至 Eigen::VectorXd。此包装器类型不可转换为 dVector,因为需要先将其转换为 Eigen::VectorXd

如果您尝试 dVector b = Eigen::VectorXd(-a) 它会起作用,原因与 dVector b = dVector(-a) 起作用相同。

解决方法: 我不建议 public 从 Eigen::VectorXd 继承,而是使用组合。

方案二: 实施 operator-(dVector)。现在编译器将选择此运算符。

方案三: 实施 operator=(Eigen::VectorXd)Eigen::operator-(Eigen::VectorXd) 的 return 类型可转换为 Eigen::VectorXd,因此可以分配给 dVector

MSVC 有错误或语言扩展来进行此编译。