不同类型的特征矩阵之间算术后的模糊重载

Ambiguous overload after arithmetic between different types of Eigen matrices

我在针对不同类型的特征矩阵(准确地说是列和矩阵)的函数重载中遇到了问题。当输入是一些简单算术的结果时,重载失败。特别是:

#include <Eigen/Eigen>
#include <iostream>

typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> MatD;
typedef Eigen::Matrix<double, Eigen::Dynamic,              1, Eigen::ColMajor> ColD;

ColD multiply(const ColD &A){ return 2. * A; }
MatD multiply(const MatD &A){ return 2. * A; }

int main()
{
  ColD A = ColD::Ones(10);
  MatD B = MatD::Ones(10,10);

  // overload is correct
  std::cout << multiply(A) << std::endl;
  std::cout << multiply(B) << std::endl;

  // compiler error: "error: call to 'multiply' is ambiguous"
  std::cout << multiply(A+A) << std::endl;
  std::cout << multiply(B+B) << std::endl;

  return 0;
}

即基于 AB 的重载被正确编译。但是当我执行 A+AB+B 时,编译器无法识别正确的重载。 我可以通过做两行来解决这个问题,可能会使用一些临时变量,但我不想这样做。我怎样才能让这个重载为此工作'one-liner' ?

我认为这是 Eigen 的特殊性,但到目前为止我无法准确理解是哪种特殊性以及如何避免它。

如评论中所述,Eigen 的运算符不生成普通矩阵或向量,而是生成运算对象(例如 Eigen::CwiseBinaryOp<...>)。

您可以像这样将运算转换为普通矩阵...

std::cout << multiply(ColD(A + A)) << std::endl;
std::cout << multiply(MatD(B + B)) << std::endl;

... 或使 multiply 成为接受各种格式的模板。语法变得有点难看,但是:

template <typename Derived>
Eigen::Matrix<
    typename Eigen::internal::traits<Derived>::Scalar,
    Eigen::internal::traits<Derived>::RowsAtCompileTime, 
    Eigen::internal::traits<Derived>::ColsAtCompileTime>
    multiply(const Derived& A) 
{
    return 2.0 * A;
}

模板参数为Derived,可以是矩阵,向量,Eigen的任意操作对象。 return 值是一个 Eigen::Matrix,我们通过 traits 模板从 Derived 中提取其特征。