TinySTL 之类型萃取 type_traits
之前对迭代器进行过类型萃取,得到迭代器所指对象类型。同理,我们仍然可以对其他类型的数据进行特性萃取,例如下面的例子,我们对猫和狗能不能被吃的特性进行了萃取,根据萃取结果选择合适的函数
萃取猫的可食用性
代码如下:
#include <iostream>
// 类
struct __true_type {
};
struct __false_type {
};
// 定义的几个类
struct Cat { }; // Cat
struct Dog { }; // Dog
struct Fish { };
// 类的特性
template <typename T>
struct type_traits {
};
template <>
struct type_traits<Cat> {
typedef __false_type isEdible; // 不可食用
typedef __true_type isFed; // 可被饲养
};
template <>
struct type_traits<Dog> {
typedef __false_type isEdible; // 不可食用
typedef __true_type isFed; // 可被饲养
};
template <>
struct type_traits<Fish> {
typedef __true_type isEdible; // 不可食用
typedef __true_type isFed; // 可被饲养
};
bool canBeFood(__true_type) {
std::cout << "Can be Eaten." << std::endl;
return true;
}
bool canBeFood(__false_type) {
std::cout << "Can not be Eaten." << std::endl;
return false;
}
int main() {
typedef typename type_traits<Cat>::isEdible category1; // 萃取猫的可食用性
canBeFood(category1());
return 0;
}
上述代码中的
C/C++编程:trivial 和 non-trivial
在 C/C++ 的 STL 编程中,针对类型 T,可以大致分为 trivial 和 non-trivial 类型。这个类型是对 T 的四种函数来说的:
- 构造函数 (ctor)
- 复制构造函数 (copy)
- 赋值函数 (assignment)
- 析构函数 (dtor)
如果上面的函数满足下面 3 条里的某一条:
- 显示 (explicit) 定义了这四条函数;
- 类里面有非静态非 POD 的数据成员;
- 有基类。
那么上面的四种函数是 non-trivial 函数,也就是有意义的函数。因为这些函数里面有了一些必要的操作,例如类成员的初始化、释放内存等操作。 POD 的意思是 Plain Old Data,也就是 C++ 的内建类型或传统的 C 结构体类型。
比如,下面定义的类 T 就是一个 POD 类型的类,而 T1 由于显式定义了构造函数和拥有了一个非 POD 的数据成员
// 整个T是POD类型
class T {
// 没有显式定义ctor/dtor/copy/assignemt 所以都是trivial
int a; // POD类型
};
// 整个T1是非POD类型
class T1 {
T1() { } // 显式定义了构造函数,所以是non-trivial ctor
// 没有显式定义ctor/dtor/copy/assignemt 所以都是trivial
int a; // POD类型
std::string b; // 非POD类型
};
那这有什么用处呢?
如果这个类是 trivial ctor/dtor/copy/assignment 函数,我们对这个类进行构造、析构、拷贝和赋值的时候可以采用最有效率的方法,不调用无所事事正真的那些ctor/dtor等,而直接采
用内存操作如
比如 STL 的 copy 算法最基本的想法是这样的:
// 非POD重载指针数值
template <typename T>
void copy(T* source, T* destination, int n, __false_type)
{
// 省略异常处理
for (; n > 0; n--,source++,destination++)
{
// 调用source的复制构造函数
constructor(source, *destination);
}
}
// POD重载指针数值
template <typename T>
void copy(T* source, T* destination, int n, __false_type)
{
// 省略异常处理
memmove(source, destination, n);
}
然实际的
迭代器萃取机
迭代器萃取机用于提取迭代器所代表的数据类型,之前说过,迭代器是对
针对是否为 trivial 进行 type_traits
这里的 type_traits 使用了类模板偏特化的语法,对常见的类型进行特征萃取,代码位于 type_traits.h 中。
#ifndef TINYSTL_TYPE_TRAITS_H_
#define TINYSTL_TYPE_TRAITS_H_
// 这个头文件用于提取类型信息
namespace TinySTL {
struct __true_type {
};
struct __false_type {
};
template <typename type>
struct __type_traits {
typedef __true_type this_dummy_must_be_first;
// 不要移除这个成员,它通知[有能力自动将 __type_traits 特化]
// 的编译器说,我们现在所看到的这个 __type_traits template 是
// 特殊的。这是为了确保万一编译器也是用一个名为 __type_traits 而其实
// 与此处定义无任何关联的 template 时,所有事情将顺利运作。
typedef __false_type has_trivial_default_constructor;
typedef __false_type has_trivial_copy_constructor;
typedef __false_type has_trivial_assignment_operator;
typedef __false_type has_trivial_destructor;
typedef __false_type is_POD_type;
};
template <> struct __type_traits<char> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
template <> struct __type_traits<signed char> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
template <> struct __type_traits<unsigned char> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
template <> struct __type_traits<short> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
template <> struct __type_traits<unsigned short> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
template <> struct __type_traits<int> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
template <> struct __type_traits<unsigned int> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
template <> struct __type_traits<long> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
template <> struct __type_traits<unsigned long> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
template <> struct __type_traits<float> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
template <> struct __type_traits<double> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
template <> struct __type_traits<long double> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
// 注意:以下针对原生指标设计 __type_tratis 偏特化版本
// 原生指标也被视为一种纯量型别
template <typename T>
struct __type_traits<T*> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
struct __type_traits<char*> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
struct __type_traits<signed char*> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
struct __type_traits<unsigned char*> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
} // namespace TinySTL
#endif
测试
测试的例子如下