ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

第 14 章 · 模板与泛型编程

第 14 章 · 模板与泛型编程 模板template是 C 最强大的特性之一也是理解 Eigen 的关键。它让你写一套代码适用所有类型。本章从为什么需要模板讲起一步步理解模板最后揭示 Eigen 类型的真面目。14.1 问题重复的代码想写一个返回较大值的函数要支持 int、doubleintmaxInt(inta,intb){returnab?a:b;}doublemaxDouble(doublea,doubleb){returnab?a:b;}逻辑完全一样只是类型不同却要写两遍。类型一多代码会爆炸式重复。14.2 函数模板一套代码适用多类型用函数模板把类型参数化#includeiostreamtemplatetypenameT// 声明模板T 是类型参数Tmax(T a,T b){returnab?a:b;}intmain(){std::coutmax(3,5)std::endl;// T 推导为 int5std::coutmax(3.5,1.5)std::endl;// T 推导为 double3.5std::coutmax(a,z)std::endl;// T 推导为 charz}拆解template typename Ttemplate声明这是模板typename TT是一个类型占位符调用时会被替换成实际类型调用max(3, 5)时编译器自动把T替换成int生成一个int版本的函数。这个过程叫模板实例化。可以理解成模板是模具调用时用实际类型浇铸出具体函数。T可以换成int、double、string、甚至自定义类。14.3 类模板类型也可作类的参数类也能参数化。比如一个坐标点类坐标类型可以是 int 也可以是 double#includeiostreamtemplatetypenameTstructPoint{T x,y;TlengthSq(){// 返回 x² y²returnx*xy*y;}};intmain(){Pointintp1{3,4};// int 版std::coutp1.lengthSq()std::endl;// 25Pointdoublep2{2.5,3.0};// double 版std::coutp2.lengthSq()std::endl;// 15.25}Pointint和Pointdouble是两个不同的类型编译器分别生成。14.4 模板可以有多个参数templatetypenameT,intN// 类型参数 非类型参数structArray{T data[N];};Arrayint,5a;// 装 5 个 intArraydouble,10b;// 装 10 个 doubleN是非类型参数一个具体的值如 5、10在编译期确定。14.5 揭开 Eigen 类型的真面目现在Eigen 的类型名就能看懂了。Eigen 的矩阵是这么定义的Eigen::Matrixdouble,3,3// 全称元素 double3 行3 列这正是类模板Matrix是模板double, 3, 3是模板参数元素类型 行数 列数。那些Matrix3d、Vector3d之类其实是别名typedefusingnamespaceEigen;// 先打开Eigen下面才能直接写 Matrix、DynamicusingMatrix3dMatrixdouble,3,3;// 等价别名usingVector3dMatrixdouble,3,1;// 3x1 的矩阵usingMatrixXdMatrixdouble,Dynamic,Dynamic;// 动态大小这三行就是 Eigen 自己定义别名时写的代码它写在namespace Eigen里面所以你平时不用写using namespace Eigen;也能用Eigen::Matrix3d。所以Eigen::Matrix3d m;// 写法一用别名Eigen::Matrixdouble,3,3n;// 写法二把模板参数展开写nm;// 能直接赋值——说明两者是同一个类型Matrix3d里的3d “3 行 3 列 double”MatrixXd里的X Dynamic动态大小d doubleVector3d 3 行 1 列的 double 矩阵列向量这就是 Eigen 强大的根源一个MatrixScalar, Rows, Cols模板配合不同参数就产生了 Matrix3d、MatrixXd、Vector3d、VectorXd 等几十种类型还能扩展到你自定义的类型。模板让 Eigen 用一套代码支持一切。14.6 模板函数实战打印任意矩阵#includeiostream#includeEigen/Dense// 模板函数能打印任意 Eigen 矩阵templatetypenameDerivedvoidprintMat(constEigen::MatrixBaseDerivedm){std::cout矩阵 (m.rows()xm.cols()):\nmstd::endl;}intmain(){Eigen::Matrix3d m1Eigen::Matrix3d::Identity();Eigen::VectorXd v2Eigen::VectorXd::LinSpaced(5,0,4);printMat(m1);// 3x3printMat(v2);// 5x1}这个函数能打印任何大小、任何类型的 Eigen 矩阵——这就是模板的力量。实际输出矩阵 (3x3): 1 0 0 0 1 0 0 0 1 矩阵 (5x1): 0 1 2 3 4printMat里用了m.rows()、m.cols()还用了Eigen::MatrixBaseDerived这种接住任何 Eigen 表达式的写法。第 23 章会解释为什么参数要写成MatrixBaseDerived而不是直接写MatrixXd。14.7 小结模板 类型参数化一套代码适用多类型。函数模板template typename T调用时自动推导实例化。类模板template typename T class XXint、Xdouble是不同类型。Eigen 的MatrixScalar, Rows, Cols是类模板Matrix3d等是别名。模板是 Eigen 灵活性的根源。下一章学习现代 C 的实用特性让代码更简洁。练习题写函数模板swap交换任意两个同类型的值。写类模板PairT, U存两个不同类型的值。写函数模板sum求一个std::vectorT所有元素的和。用Eigen::Matrixdouble, 3, 3和Eigen::Matrix3d各声明一个矩阵验证它们等价。用自己的话解释模板实例化是什么。
返回列表