作者: 边城量子 ( shihezichen@live.cn )
背景
在阅读 Sophus 库代码时, 经常会遇到 traits 的使用。例如:
sophus.so3.hpp:
namespace Sophus {
template <class Scalar_, int Options = 0>
class SO3;
using SO3d = SO3<double>;
using SO3f = SO3<float>;
} // namespace Sophus
namespace Eigen {
namespace internal {
template <class Scalar_, int Options_>
struct traits<Sophus::SO3<Scalar_, Options_>> {
static constexpr int Options = Options_;
using Scalar = Scalar_;
using QuaternionType = Eigen::Quaternion<Scalar, Options>;
};
template <class Scalar_, int Options_>
struct traits<Map<Sophus::SO3<Scalar_>, Options_>>
: traits<Sophus::SO3<Scalar_, Options_>> {
static constexpr int Options = Options_;
using Scalar = Scalar_;
using QuaternionType = Map<Eigen::Quaternion<Scalar>, Options>;
};
template <class Scalar_, int Options_>
struct traits<Map<Sophus::SO3<Scalar_> const, Options_>>
: traits<Sophus::SO3<Scalar_, Options_> const> {
static constexpr int Options = Options_;
using Scalar = Scalar_;
using QuaternionType = Map<Eigen::Quaternion<Scalar> const, Options>;
};
} // namespace internal
} // namespace Eigen
-
C++ traits是做什么的?
这里使用到了 C++ 的
traits.traits是做什么的? 举个例子, 在STL中, 容器和算法是分开的, 彼此独立设计,容器和算法之间通过迭代器联系在一起. 那么, 算法是如何从迭代器中萃取出容器元素的类型的? 就要用到traits classes的功能. -
为什么要加这些 traits ?
-
Eigen库中没有Sophus所需的这些traits定义在
Eigen库的发布版本源码中是没有SO3的相关数据类型的定义的, 因为Sophus库是在Eigen库为基础的增强.
-
-
Sophus新增了哪些 traits ?
template <class Scalar_, int Options_> struct traits<Sophus::SO3<Scalar_, Options_>> { static constexpr int Options = Options_; using Scalar = Scalar_; using QuaternionType = Eigen::Quaternion<Scalar, Options>; };-
在
Eigen::internal命名空间中,增加了一个新的traits.其中的Sophus::SO3<Scalar_, Options_>, 表明这个traits是针对哪个数据类型的特化. -
在这个
traits类里面, 又定义了两个新的数据类型, 分别是Scalar, QuaternionType. -
在有了如上定义之后, 以后如果要使用到这两个新定义的数据类型, 则可以采用如下代码形式:
template<typename Derived> class T { public: using Scalar = typename Eigen::internal::traits<Derived>::Scalar; using QuaternionType = typename Eigen::internal::traits<Derived>::QuaternionType; //... };定义新的数据类型
Scalar, QuaternionType, 即把traits中的类型暴露出来并别名化的过程. -
当出现以上代码时, Scalar也并不一定会指向上面为
SO3所定义的traits. 因为Eigen库中为旋转向量、旋转矩阵等等都定义了对应的traits, 还是要看Derived是什么类型. 在Sophus库中, 其中的模板参数Derrived往往会被特化为Sophus::SO3类型, 这时候编译器就会使用上面traits的定义了.
-