首页 > 解决方案 > 特征模板不适用于固定大小的矩阵

问题描述

我编写了以下模板来检查三角形是否退化:

template<typename Derived>
bool nondegenerate(const Eigen::PlainObjectBase<Derived>& triangle) {

  typedef typename Derived::Scalar scalarType;

  if (triangle.cols() == 2) {
    Eigen::Matrix<scalarType, 1, 2> v1 = triangle.row(1) - triangle.row(0);
    Eigen::Matrix<scalarType, 1, 2> v2 = triangle.row(2) - triangle.row(0);
    return v1(0)*v2(1) - v1(1)*v2(0);
  } else if (triangle.cols() == 3) {
    Eigen::Matrix<scalarType, 1, 3> v1 = triangle.row(1) - triangle.row(0);
    Eigen::Matrix<scalarType, 1, 3> v2 = triangle.row(2) - triangle.row(0);
    return v1.cross(v2).norm();
  } else {
    std::cerr << "Undefined input." << std::endl;
    return false;
  }
}

如果我nondegenerate用类型的矩阵调用,上面的代码可以正常工作Eigen::MatrixXi

Eigen::MatrixXi triangle;
triangle.resize(3,2);
triangle << 1,2,3,4,5,6;
nondegenerate(triangle);

但是,如果我用固定大小的矩阵替换上述动态大小矩阵:

Eigen::Matrix<int, 3, 2> triangle;
triangle << 1,2,3,4,5,6;
nondegenerate(triangle);

它报告编译错误:

/usr/local/include/eigen3/Eigen/src/Core/AssignEvaluator.h:833:3: error: static_assert 由于要求失败'(int(Eigen::internal::size_of_xpr_at_compile_time<Eigen::Matrix<int, 1 , 3, 1, 1, 3> >::ret) == 0 && int(Eigen::internal::size_of_xpr_at_compile_time<Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<int, int>, const Eigen:: Block<const Eigen::Matrix<int, 3, 2, 0, 3, 2>, 1, 2, false>, const Eigen::Block<const Eigen::Matrix<int, 3, 2, 0, 3, 2>, 1, 2, 假> > >::ret) == 0) || ((int(Matrix<int, 1, 3, 1, 1, 3>::RowsAtCompileTime) == Eigen::Dynamic || int(CwiseBinaryOp<Eigen::internal::scalar_difference_op<int, int>, const Eigen: :Block<const Eigen::Matrix<int, 3, 2, 0, 3, 2>, 1, 2, false>, const Eigen::Block<const Eigen::Matrix<int, 3, 2, 0, 3, 2>, 1, 2, false> >::RowsAtCompileTime) == Eigen::Dynamic || int(Matrix<int, 1, 3, 1, 1, 3>::RowsAtCompileTime) == int(CwiseBinaryOp<Eigen::internal::scalar_difference_op<int, int>, const Eigen::Block<const Eigen::Matrix <int, 3, 2, 0, 3, 2>, 1, 2, false>, const Eigen::Block<const Eigen::Matrix<int, 3, 2, 0, 3, 2>, 1, 2, false> >::RowsAtCompileTime)) && (int(Matrix<int, 1, 3, 1, 1, 3>::ColsAtCompileTime) == Eigen::Dynamic || int(CwiseBinaryOp<Eigen::internal::scalar_difference_op< int, int>, const Eigen::Block<const Eigen::Matrix<int, 3, 2, 0, 3, 2>, 1, 2, false>, const Eigen::Block<const Eigen::Matrix<int , 3, 2, 0, 3, 2>, 1, 2, false> >::ColsAtCompileTime) == Eigen::Dynamic || int(Matrix<int, 1, 3, 1, 1, 3>::
^~~~~~~~~~~~~~~~~~~~~~ /usr/local/include/eigen3/Eigen/src/Core/util/StaticAssert.h:33:40: 注意: 展开从宏 'EIGEN_STATIC_ASSERT' #define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG); ^ ~ /usr/local/include/eigen3/Eigen/src/Core/PlainObjectBase.h:732:17:注意:在函数模板特化'Eigen::internal::call_assignment_no_alias<Eigen::Matrix<int, 1 , 3, 1, 1, 3>, Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<int, int>, const Eigen::Block<const Eigen::Matrix<int, 3, 2, 0, 3, 2>, 1, 2, false>, const Eigen::Block<const Eigen::Matrix<int, 3, 2, 0, 3, 2>, 1, 2, false> >, Eigen::internal::assign_op <int, int> >' 在这里请求 internal::call_assignment_no_alias(this->derived(), other.derived(), internal::assign_op< 标量,类型名 OtherDer... ^ /usr/local/include/eigen3/Eigen/src/Core/PlainObjectBase.h:537:7: 注意:在函数模板特化 'Eigen::PlainObjectBase<Eigen::Matrix< 的实例化中int, 1, 3, 1, 1, 3> >::_set_noalias<Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<int, int>, const Eigen::Block<const Eigen::Matrix<int, 3 , 2, 0, 3, 2>, 1, 2, false>, const Eigen::Block<const Eigen::Matrix<int, 3, 2, 0, 3, 2>, 1, 2, false> > > ' 在这里请求 _set_noalias(other); ^ /usr/local/include/eigen3/Eigen/src/Core/Matrix.h:377:9: 注意:在函数模板特化的实例化中'Eigen::PlainObjectBase<Eigen::Matrix<int, 1, 3, 1 , 1, 3> >::PlainObjectBase<Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<int, int>, const Eigen:: Block<const Eigen::Matrix<int, 3, 2, 0, 3, 2>, 1, 2, false>, const Eigen::Block<const Eigen::Matrix<int, 3, 2, 0, 3, 2>, 1, 2, false> > >' 在此处请求:Base(other.derived()) ^ testEigenIgl.cpp:1052:42: 注意:在函数模板特化 'Eigen::Matrix<int, 1, 3, 1, 1, 3>::Matrix<Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<int, int>, const Eigen::Block<const Eigen::Matrix<int, 3, 2, 0, 3, 2>, 1, 2, false>, const Eigen::Block<const Eigen::Matrix<int, 3, 2, 0, 3, 2>, 1, 2, false> > >' 在这里请求特征: :Matrix<scalarType, 1, 3> v1 = triangle.row(1) - triangle.row(0); ^ testEigenIgl.cpp:1082:7: 注意:在函数模板特化 'nondegenerate<Eigen::Matrix<int, 3, 2, 0, 3, 2> 的实例化中

如何修复模板以同时接受动态和固定大小的矩阵?

谢谢!

标签: c++templatesmatrixeigen

解决方案


您遇到的问题是您的第一个分支的两个分支if都必须有效,并且在固定大小矩阵的情况下,至少一个分支不是,因为您为算术结果指定了确切的尺寸。

template<typename Derived>
bool nondegenerate(const Eigen::PlainObjectBase<Derived>& triangle) {

  typedef typename Derived::Scalar scalarType;

  if (triangle.cols() == 2) {
    auto v1 = triangle.row(1) - triangle.row(0);
    auto v2 = triangle.row(2) - triangle.row(0);
    return v1(0)*v2(1) - v1(1)*v2(0);
  } else if (triangle.cols() == 3) {
    auto v1 = triangle.row(1) - triangle.row(0);
    auto v2 = triangle.row(2) - triangle.row(0);
    return v1.cross(v2).norm();
  } else {
    std::cerr << "Undefined input." << std::endl;
    return false;
  }
}

另外:有一些通用公式可以找到任何大小的方阵的行列式,为什么不使用其中一种方法呢?


推荐阅读