欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。
背景
在eigen库中,矩阵类原来的用法是 Matrix<Type, row, col>。
为了方便用户,库中还提供了用户常用的快捷类型,比如Matrix3d 代表Matrix<double, 3, 3>。
这种用法在eigen库里很多,产生的很多矩阵类型也记不住,特意去翻阅了eigen库源码,学习一下其实现原理。
顺便研究一下m(x, y)的实现原理。
原理
别名原理是利用define可以传递参数和##号来拼接出别名类型,事先在代码中生成using或typedef的语句来起别名。
括号原理是利用operator()(…) 后面的括号可以带多个参数,然后在程序中解析。
示例
模板类如下
template<typename T>
class M{
public:
T v;
T& operator()(int a, int b) {
printf("%d %d\n", a,b);
return v;
}
};
期望效果
现在我想实现Mi=M<int>, Md=<double>, Mf=M<float>。
比较直接的做法是
using Mi = M<int>;
或
typedef M<int> Mi;
参照eigen里的做法
把公共部分提取出来
先define 一个方法MT,然后根据类型去调用这个方法
// ##是连接符
#define MT(type, typesuffix) using M##typesuffix=M<type>;
// 下面调用3次类型初始化。
MT(int, i) // 生成 using Mi = M<int>;
MT(double, d) // 生成 using Md = M<double>;
MT(float, f) // 生成 using Mf = M<float>;
测试代码
void checkType(int a) {
puts("int");
}
void checkType(double a) {
puts("double");
}
void checkType(float a) {
puts("float");
}
template<typename T>
class M{
public:
T v;
T& operator()(int a, int b) {
printf("%d %d\n", a,b);
return v;
}
};
#define MT(type, typesuffix) using M##typesuffix=M<type>;
MT(int, i)
MT(double, d)
MT(float, f)
int main() {
M<int> m1;
checkType(m1.v);
Md md;
Mi mi;
Mf mf;
// 测试括号
mi(1, 2) = 10;
printf("%d\n", mi(1, 2));
// 测试类型
checkType(md.v);
checkType(mi.v);
checkType(mf.v);
printf("ok\n");
return 0;
}
测试效果
源码解析
// matrix 类定义
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
class Matrix
: public PlainObjectBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
{
...
};
// 别名定义
#define EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \
/** \ingroup matrixtypedefs */ \
typedef Matrix<Type, Size, Size> Matrix##SizeSuffix##TypeSuffix; \ // 生成方阵形
/** \ingroup matrixtypedefs */ \
typedef Matrix<Type, Size, 1> Vector##SizeSuffix##TypeSuffix; \ // 生成列向量
/** \ingroup matrixtypedefs */ \
typedef Matrix<Type, 1, Size> RowVector##SizeSuffix##TypeSuffix; // 生成行向量
... 这里省略了可变数组
// 生成3种不同规格的矩阵或向量
#define EIGEN_MAKE_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \
EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 2, 2) \
EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 3, 3) \
EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 4, 4) \
...省略可变数组
EIGEN_MAKE_TYPEDEFS_ALL_SIZES(int, i) // 以方阵形为例,生成 typedef Matrix<int, 2, 2> Matrix2i; typedef Matrix<int, 3, 3> Matrix3i;typedef Matrix<int, 4, 4> Matrix4i;
EIGEN_MAKE_TYPEDEFS_ALL_SIZES(float, f)
EIGEN_MAKE_TYPEDEFS_ALL_SIZES(double, d)
EIGEN_MAKE_TYPEDEFS_ALL_SIZES(std::complex<float>, cf)
EIGEN_MAKE_TYPEDEFS_ALL_SIZES(std::complex<double>, cd)
#undef EIGEN_MAKE_TYPEDEFS_ALL_SIZES
#undef EIGEN_MAKE_TYPEDEFS
#undef EIGEN_MAKE_FIXED_TYPEDEFS
常用类型总结
别名 | 类型 |
---|---|
Matrix3d | Matrix<double, 3, 3> |
Matrix3i | Matrix<int, 3, 3> |
Matrix3f | Matrix<float, 3, 3> |
Matrix2d | Matrix<double, 2, 2> |
Matrix2i | Matrix<int, 2, 2> |
Matrix2f | Matrix<float, 2, 2> |
Vector3d | Matrix<double, 3, 1> |
Vector3i | Matrix<int, 3, 1> |
Vector3f | Matrix<float, 3, 1> |
本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。