C++ 基于特征的模板约简

C++ 基于特征的模板约简,c++,c++11,templates,eigen3,C++,C++11,Templates,Eigen3,我试图做一个基于特征矩阵的约简 #include <iostream> #include <Eigen/Dense> #include <type_traits> template<typename T1, typename T2, int n1, int n2> auto reduction(Eigen::Matrix<T1, n1, n2> &a1, Eigen::Matrix<T2,

我试图做一个基于特征矩阵的约简

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

template<typename T1, typename T2, int n1, int n2>
auto reduction(Eigen::Matrix<T1, n1, n2> &a1,
               Eigen::Matrix<T2, n1, n2> &a2)
     -> decltype(T1{}*T2{})
{
  using BaseT3 = 
    typename std::remove_cv<typename std::remove_reference<decltype(T1{}*T2{})>::type>::type;

  BaseT3 res = a1(0, 0)*a2(0, 0);

  for (int i=0; i<n1; ++i)
    for (int j=0; j<n2; ++j)
      if (i+j)
        res = res + a1(i, j)*a2(i, j);

  return res;
}

int main()
{
  Eigen::Matrix<double, 3, 3> m;
  Eigen::Matrix<Eigen::Vector3d, 3, 3> n;

  std::cout << reduction(m, n) << std::endl;
}
如果我没有弄错的话,对于给定的
main
,键入
BaseT3
应该是
Eigen::Vector3d
。我还尝试了静态强制转换,这样
操作符=
就不会失败,但随后会出现其他错误


这是c++11,我使用的是Eigen3,编译器是g++5.4.1。

T1*T2的decltype不是您在这里期望的-Eigen大量使用表达式模板。错误中的CWiseUnaryOp和CWiseBinaryOp类型表明了这一点。换句话说,“double*Vector3d”的结果并不是您所期望的(它不是Vector3d,而是cwisebinaryop)

另见:


在这种特定情况下,您可以通过为模板函数的第一个和第二个参数创建特征基类型的部分专门化来找到解决方案。

特征使用表达式模板来优化操作链

所以MatrixA*MatrixB不是一种矩阵类型,而是一个表达式,表示“当计算时,它将是一个MatrixA乘以一个MatrixB的乘积”

结果是,
A*B+C*D
不会创建(至少同样多)临时矩阵,而是当存储在输出矩阵中时,结果直接“延迟”计算到输出矩阵中

现在,你是多重元素。但其中一种元素类型是矩阵。最后,Eigen对标量乘以向量的表达式模板进行了优化

您需要的类型是
std::decation\t
(C++11详细版本)

你可以写一个奇特的SFINAE东西来检查它是否可以被评估,如果可以的话。或者您可以测试特征表达式模板类型

error: no match for ‘operator=’ (operand types are ‘BaseT3 {aka 
Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>, 
const Eigen::Matrix<double, 3, 1> >}’ 
and 
‘const Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<double>, 
const Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>, 
const Eigen::Matrix<double, 3, 1> >, 
const Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>, 
const Eigen::Matrix<double, 3, 1> > >’)
         res = res + a1(i, j)*a2(i, j);
             ^