作者: 边城量子 ( shihezichen@live.cn )
背景
在阅读 Sophus 库代码时, 经常会遇到 typename 和 constexpr 的使用, 例如:
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;一般情况下,
typename和class在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。