Ch02-C++ 之 trait
June 21, 2022
trait 并不是 C++ 的关键字之类的,属于 C++ 的一种“机制”,或者说 C++ 特有的一种编程小技巧。
众所周知容器与算法是分开的,算法在运行的时候需要有一种手段来获取容器元素类型,这个手段就是 type traits。
1. 模板特化 (Template Specialization) #
举个简单的 type traits 的例子。
template <class T>
class MyVector {
public:
class iterator {
public:
// 将类型 T 重命名为 value_type
typedef T value_type;
};
};
template<class T>
struct MyItrTrait {
// 将 T::value_type 重命名为 value_type
typedef typename T::value_type value_type;
};
MyItrTrait<MyVector<std::string>::iterator> itr;
- MyVector 采用模板编程,所以使用的时候需要把类型传递进去。比如
MyVector<std::string>
,在 MyVector::iterator 内部会对该类型重新起个别名 value_type(约定俗成)。 - MyItrTrait 同样采用的是模板编程,使用的时候需要将
MyVector<std::string>::iterator
作为类型传递进去,但是因为约定俗称的原因,因此可以通过T::value_type
获取到MyVector
中每个元素的基本类型。然后再对T::value_type
重新起个别名方便后续操作。
这一套约定俗称的编程技巧便称为 traits。MyIterTrait 这个类称为萃取类(traits class),因为使用了模板,所以也被称为模板特化(template specialization),里面的那一行代码便被称为类型萃取(type traits)。
2. 偏特化 (Patial Spcialization) #
模板特化时,可以只指定一部分而非所有模板参数,或者是参数的一部分而非全部特性,这叫做模板的偏特化。一个类模板的偏特化本身是一个模板,使用它时用户还必须为那些在特例化版本中未指定的模板参数提供实参。
/* 模板特化 */
template<class T>
struct MyItrTrait {
typedef typename T::value_type value_type;
};
/* 偏特化 */
template<class T>
// 对 T 进行限定,必须是指针类型
struct MyItrTrait<T*> {
typedef typename T::value_type value_type;
};