C++ typename和constexpr(以Sophus库为例)

656 阅读1分钟

作者: 边城量子 ( shihezichen@live.cn )

背景

在阅读 Sophus 库代码时, 经常会遇到 typenameconstexpr 的使用, 例如:

sophus/so3.hpp:

template <class Derived>
class SO3Base {
 public:
  static constexpr int Options = Eigen::internal::traits<Derived>::Options;
  using Scalar = typename Eigen::internal::traits<Derived>::Scalar;
  using QuaternionType =
      typename Eigen::internal::traits<Derived>::QuaternionType;
  using QuaternionTemporaryType = Eigen::Quaternion<Scalar, Options>;

  
  static int constexpr DoF = 3;
  static int constexpr num_parameters = 4;
  static int constexpr N = 3;
  using Transformation = Matrix<Scalar, N, N>;
  using Point = Vector3<Scalar>;
  using HomogeneousPoint = Vector4<Scalar>;
  using Line = ParametrizedLine3<Scalar>;
  using Hyperplane = Hyperplane3<Scalar>;
  using Tangent = Vector<Scalar, DoF>;
  using Adjoint = Matrix<Scalar, DoF, DoF>;
  • C++ typename 是干什么的?

    using Scalar = typename Eigen::internal::traits<Derived>::Scalar;
    

    一般情况下, typenameclass 在C++中等价, 比如如下代码中的class T可以换成typename T:

    template <class T> 
    class Test{} ;
    

    但是有时候就必须只能用typename. 因为默认情况下,C++语言假定通过作用域运算符访问的名字不是类型。因此, 如果我们希望使用一个模板类型参数的类型成员, 就必须显示告知编译器该名字是一个类型, 就如上面代码所示, 让编译器知道 Eigen::internal::traits<Derived>::Scalar 是一个数据类型。

    此外, typename 这一性质还经常用在模板函数的返回值定义上, 比如:

    template<typename T>
    typename T::value_type top(const T &c)
    {
        if (!c.empty())
            return c.back();
        else
            return typename T::value_type();
    }
    

    其中函数 top() 期待的入参是一个容器类型, 然后它使用typename指明返回值的类型和入参类型一样; 并且, 在入参c容器中没有元素时, 用typename T::value_type() 生成一个初始值的元素,然后返回。

  • C++ constexpr 是干什么的?

    此处的 constexpr 关键字表明这是一个编译期常量.即它的值会在编译期就尝试被计算出来并固定, 提升运行期的执行效率。

    所以, C++中如果符合以上情况的, 应尽量使用constexpr而不是const