Eigen::Matrix 中的模板重载运算符

问题描述

我得到了这个基本代码

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

using T12 = Eigen::Matrix<double,2,1>;
using T22 = Eigen::Matrix<double,2>;

template <typename Der1,typename Der2> T22
operator^ (const Eigen::MatrixBase<Der1>& d1,const Eigen::MatrixBase<Der2>& d2) {
  return d1 * d2.transpose();
}

void testT12DyadT12 () {
  T12 t12_1,t12_2;
  t12_1 << 2.0,3.0;  t12_2 << 1.5,2.5;

  const double c1{2.0},c2{0.5};
  T22 t22_1 = c1*t12_1 ^ t12_2*c2;
  std::cout << t22_1 << "\n"; 
}

int main () {
  testT12DyadT12();
  //testT1nDyadT1n ();
  return 0;
}

这有效并产生正确的 2 x 2 矩阵输出。现在我想将矩阵中的行数和列数模板化为

template<int nc>
using T1n = Eigen::Matrix<double,nc,1>;
template<int nc>
using T2n = Eigen::Matrix<double,nc>;

template <int nc,typename Der1,typename Der2> T2n<nc>
operator& (const Eigen::MatrixBase<Der1>& d1,const Eigen::MatrixBase<Der2>& d2) {
  return d1 * d2.transpose();
}

void testT1nDyadT1n () {
  T1n<2> t12_1,2.5;

  T2n<2> t22_1 = t12_1 & t12_2;
  std::cout << t22_1 << "\n"; 
}

但它给出了这个编译器错误

error: invalid operands to binary expression ('T1n<2>' (aka 'Eigen::Matrix<double,1,1>') and 'T1n<2>')
T2n<2> t22_1 = t12_1 & t12_2;
               ~~~~~ ^ ~~~~~
note: candidate template ignored: Couldn't infer template argument 'nc'
operator& (const Eigen::MatrixBase<Der1>& d1,const Eigen::MatrixBase<Der1>& d2) {
^

我了解错误消息(编译器无法推断模板 arg)。 我该如何解决这个问题?我尝试将参数作为 const Der1&,const Der2& 传递给运算符,但无济于事。我确信这是愚蠢的……我没有理解或注意。最终我的目标是模板化特征标量类型:template< typename T,int nc > using T1n = Eigen::Matrix<T,1>; 等,并重载 operator^

解决方法

您可以从 Der1::RowsAtCompileTime 推导出返回类型的大小:

template <typename Der1,typename Der2> 
T2n<Der1::RowsAtCompileTime>
operator& (const Eigen::MatrixBase<Der1>& d1,const Eigen::MatrixBase<Der2>& d2) {
  return d1 * d2.transpose();
}

或者完全通用(假设 Der1Der2 具有相同的标量类型):

template <typename Der1,typename Der2> 
Eigen::Matrix<typename Der1::Scalar,Der1::RowsAtCompileTime,Der2::RowsAtCompileTime>
operator& (const Eigen::MatrixBase<Der1>& d1,const Eigen::MatrixBase<Der2>& d2) {
  return d1 * d2.transpose();
}

使用 C++14,您当然可以只返回 auto(这将返回一个惰性表达式,这可能是您所期望的,也可能不是):

template <typename Der1,typename Der2> 
auto
operator& (const Eigen::MatrixBase<Der1>& d1,const Eigen::MatrixBase<Der2>& d2) {
  return d1 * d2.transpose();
}