Linux/GCC正常的模板函数特化代码在MSVC2017触发C1001错误
解决MSVC 2017编译g2o内部
axpy模板特化时的C1001内部错误 我之前遇到过类似的MSVC模板兼容性问题,你的情况是因为MSVC 2017对基于typedef的模板显式特化处理存在内部bug,导致触发C1001错误。
问题分析
你的代码中针对Eigen::MatrixXd的模板特化写法在GCC下正常,但在MSVC 2017中失效——本质是Eigen::MatrixXd是Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>的typedef,MSVC对这种typedef类型的模板特化处理逻辑存在缺陷。你之前尝试的template<Eigen::MatrixXd> inline void axpy<Eigen::MatrixXd>写法是错误的,因为模板特化要求针对原始模板参数而非typedef类型定义。
解决方案:用函数重载代替模板特化
针对Eigen::MatrixXd这种具体类型,直接重载axpy函数可以绕过MSVC的模板特化bug,同时保持功能完全一致,兼容性更好:
namespace g2o { namespace internal { template<typename MatrixType> inline void axpy(const MatrixType& A, const Eigen::Map<const Eigen::VectorXd>& x, int xoff, Eigen::Map<Eigen::VectorXd>& y, int yoff) { y.segment<MatrixType::RowsAtCompileTime>(yoff) += A * x.segment<MatrixType::ColsAtCompileTime>(xoff); } template<int t> inline void axpy(const Eigen::Matrix<double, Eigen::Dynamic, t>& A, const Eigen::Map<const Eigen::VectorXd>& x, int xoff, Eigen::Map<Eigen::VectorXd>& y, int yoff) { y.segment(yoff, A.rows()) += A * x.segment<Eigen::Matrix<double, Eigen::Dynamic, t>::ColsAtCompileTime>(xoff); } // 替换原模板特化为普通重载函数,直接匹配Eigen::MatrixXd类型 inline void axpy(const Eigen::MatrixXd& A, const Eigen::Map<const Eigen::VectorXd>& x, int xoff, Eigen::Map<Eigen::VectorXd>& y, int yoff) { y.segment(yoff, A.rows()) += A * x.segment(xoff, A.cols()); } } // end namespace internal } // end namespace g2o
备选方案:针对原始模板参数特化
如果你坚持使用模板特化,可以直接针对Eigen::Matrix的原始模板参数(而非typedef)进行特化,写法如下:
namespace g2o { namespace internal { // ... 保留原有两个模板函数 ... // 针对原始动态矩阵模板参数特化 template<> inline void axpy<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>>( const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>& A, const Eigen::Map<const Eigen::VectorXd>& x, int xoff, Eigen::Map<Eigen::VectorXd>& y, int yoff) { y.segment(yoff, A.rows()) += A * x.segment(xoff, A.cols()); } } // end namespace internal } // end namespace g2o
不过这种写法在部分旧版MSVC中仍可能存在兼容性问题,因此更推荐第一种重载方案。
内容的提问来源于stack exchange,提问作者Humam Helfawi
相关产品推荐
相关产品推荐

