STL — SGT STL的私房菜: __type_traits

__type_traits 是 SGI STL 中一种强大的编程技法,用于在编译期间确定类型的各种特性,如是否有非常规的默认构造函数等。通过这些信息,可以在处理大量数据时选择更高效的内存操作方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SGT STL的私房菜: __type_traits




traits的编程技法非常的6,我们在前面的迭代器设计思维的时候已经领教过了,它适当的弥补了C++语言本身的不足. STL只对迭代器加

以规范,制定 iterator_traits. SGI把这种技法进一步扩大到迭代器以外的世界上,于是有了所谓的__type_traits. 双底线前缀词意

这是SGI STL内部所用的东 西 ,不在STL标准规范之内.


iterator_traits负责萃取迭代器的特性,__type_traits则负责萃取型别的特性. 此处我们所关注的型别特性是指:这个型别是否具备

non-trivial  defalt ctor(在我这里理解->非常规默认构造函数)? 是否具备non-trivial copy ctor()?是否具备 non-trivial 

assignment operator? 是否具备 non-trivial dtor?如果答案是否定的,我们在对这个型别进行构造,析构,拷贝,赋值等操作的时候,

就可以采用最有效率的措施,而采用内存直 接处理操作如 malloc(),memcpy()等等,获得最高效率. 这对于大规模而操作频繁的容器,

有这显著的效率提升.

定义于SGI<type_traits.h>中的__type_traits,提供了一种机制,允许针对不同的型别属性,在编译时期完成函数派送决定。 这对于撰

写template很 帮助,例如,当我们准备对一个"元素型别未知"的数组执行copy操作时,如果我们能事先知道其元素型别是否有一个

trivial copy constructor,便 能够 帮助我们决定是否可使用快速的memcpy()或memove().

根据我们的iterator_traits得来的经验,我们希望,程序之中可以这样运用__type_traits<T>,T代表任意型别:

__type_traits<T>::has_trivial_default_constructor
__type_traits<T>::has_trivial_copy_constructor
__type_traits<T>::has_trivial_assignment_operator
__type_traits<T>::has_trivial_destructor
__type_traits<T>::is_POD_type //POD: Plain Old Data

所以现在已经很容易了,我们只需要判断上面这几项是真是假就结束了.   但是上面传输的结果不能单纯是一个bool值,应该是

个有着真/假性质的对 象,因为我们希望利用其响应结果来进行参数推导,而编译器只有面对class object形式的参数,才会做参数

推导. 为此,上述式子应该传会这样的东 西:

struct __true_type {
};

struct __false_type {
};

这两个空白的classes没有任何成员,不会带来额外的负担,却又能够标示真假,满足我们所需:

为了达到上述的五个式子,__type_traits内定义一些typedefs,其值不是__true_type就是__false_type。 下面看看SGI STL源代码:

template <class type>
struct __type_traits {
	typedef __true_type     this_dummy_member_must_be_first;
	/* Do not remove this member. It informs a compiler which
	automatically specializes __type_traits that this
	__type_traits template is special. It just makes sure that
	things work if an implementation is using a template
	called __type_traits for something unrelated. */

	/* The following restrictions should be observed for the sake of
	compilers which automatically produce type specific specializations
	of this class:
	- You may reorder the members below if you wish
	- You may remove any of the members below if you wish
	- You must not rename members without making the corresponding
	name change in the compiler
	- Members you add will be treated like regular members unless
	you add the appropriate support in the compiler. */


	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;
};

因为我们的内置类型就那么几个,而用户自定义类型的可能多的数不过来. 自定义类型可能大部分都是__false_type. 所以我们

的SGI先把所有的类型 的五种萃取型别的特性定义为__false_type. 但是内置类型的五种萃取型别的特性基本为__true_type. 所以呢

,再对内置类型特化就解决掉这个问题.

// Provide some specializations.  This is harmless for compilers that
//  have built-in __types_traits support, and essential for compilers
//  that don't.

__STL_TEMPLATE_NULL 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;
};

__STL_TEMPLATE_NULL 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;
};

__STL_TEMPLATE_NULL 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;
};

__STL_TEMPLATE_NULL 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;
};

__STL_TEMPLATE_NULL 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;
};

__STL_TEMPLATE_NULL 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;
};

__STL_TEMPLATE_NULL 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;
};

__STL_TEMPLATE_NULL 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;
};

__STL_TEMPLATE_NULL 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;
};

__STL_TEMPLATE_NULL 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;
};

__STL_TEMPLATE_NULL 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;
};

__STL_TEMPLATE_NULL 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;
};

#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION

template <class 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;
};

#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */

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;
};

__type_traits在SGI STL应用简直不要太广泛,我们单单的看源代码没有办法更好的理解它. 必须加一点实例. STL定义了5个函

数,他们内部都使用 了__type_traits. 我有一篇博客有源代码加图示来解释这5个函数,相信你了解懂这5个函数的时候,那么你一定

就深刻理解__type_traits的思想.

博客链接: 内存基本处理工具!!!!!!!!!!!!!!
### `std::allocator_traits` 与 `std::iterator_traits` 的区别及各自作用 在 C++ STL 中,`std::allocator_traits` 和 `std::iterator_traits` 是两个用于泛型编程的重要工具,它们分别服务于不同的目的。 #### `std::allocator_traits` `std::allocator_traits` 是用于封装和抽象内存分配器行为的模板类。它提供了一种统一的方式来访问分配器的特性,如内存分配、释放、对象构造与析构等操作。通过 `std::allocator_traits`,容器可以独立于具体的分配器实现,从而支持用户自定义分配器[^2]。 例如,标准容器(如 `vector`)通常使用 `std::allocator_traits<Allocator>` 来获取分配器的接口: ```cpp template <class T, class Allocator = std::allocator<T>> class vector { using allocator_type = Allocator; using traits = std::allocator_traits<allocator_type>; }; ``` `std::allocator_traits` 提供了默认实现,使得即使分配器未显式定义某些类型别名或函数,也能通过默认方式完成内存管理[^2]。 #### `std::iterator_traits` `std::iterator_traits` 是用于萃取迭代器特性的模板结构体,它允许算法和容器在不关心具体迭代器类型的情况下访问其关联类型,如 `value_type`、`difference_type`、`pointer`、`reference` 和 `iterator_category` 等。这一机制是泛型编程中类型萃取(type traits)的经典应用[^3]。 例如,以下是一个典型的 `iterator_traits` 定义: ```cpp template <typename Iterator> struct iterator_traits { using value_type = typename Iterator::value_type; using difference_type = typename Iterator::difference_type; using pointer = typename Iterator::pointer; using reference = typename Iterator::reference; using iterator_category = typename Iterator::iterator_category; }; ``` 对于原生指针,也提供了偏特化版本以使其兼容: ```cpp template <typename T> struct iterator_traits<T*> { using value_type = T; using difference_type = ptrdiff_t; using pointer = T*; using reference = T&; using iterator_category = std::random_access_iterator_tag; }; ``` 该机制确保了算法可以一致地处理各种类型的迭代器,包括类类型迭代器和原生指针。 --- ### 主要区别总结 | 特性 | `std::allocator_traits` | `std::iterator_traits` | |------|--------------------------|-------------------------| | 目的 | 封装内存分配器的行为 | 萃取迭代器的关联类型 | | 使用场景 | 容器内部进行内存管理 | 算法和容器访问迭代器属性 | | 类型萃取 | 提供分配器相关操作的默认实现 | 提供迭代器类型信息的访问 | | 对自定义的支持 | 支持用户自定义分配器 | 支持用户自定义迭代器 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值