Eigen是常用的线性代数计算库,而且是header-only,意即其只有头文件,没有对应的cpp/cc文件。Eigen目前仍在不断稳定的迭代,截止目前迭代到3.4.0。Eigen拥有完善的文档,高质量的代码,是开源软件的优秀典范。一次在项目中用到Eigen并且在学习模板元编程时,接触到CRTP等概念,遂激发兴趣想深入了解Eigen并将自己阅读Eigen过程中总结记录下来。
Eigen的目录结构分为两大部分src和头文件,如下图所示。头文件按照具体功能划分,用户使用时将其包含在内即可,如客户想使用特征值计算,那么就直接#include<Eigen/Eigenvalues>即可;src是对应的实现。
src虽然是对应的实现,但是却没有一个cpp/cc文件,那么这么多头文件怎么组织好包含关系呢?Eigen给出的答案是,在对外头文件中按照依赖关系排列头文件顺序。
以Core模块为例,该模块定义了Eigen核心数据结构和基本功能。Eigen/src/Matrix.h定义了矩阵,其定义如下:
template<typename Scalar_, int Rows_, int Cols_, int Options_, int MaxRows_, int MaxCols_> class Matrix : public PlainObjectBase<Matrix<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_> >但是我们发现,Matrix.h并没有直接#include<PlainObjectBase.h>。打开Eigen/Core,我们就可以发现如下结构
当用户将Eigen/Core包含在自己的文件中,编译时头文件的代码一经展开,PlainObjectBase便是已经声明并定义好的了,所以客户端代码并不会发生链接问题。需要注意的是,如果客户只include其中一个文件比如Matrix.h,此时就会发生链接问题,因为找不到PlainObjectBase。这样做的好处是减少了各文件之间的编译依赖关系。