STL源码笔记之型别提取技法(2)

2024-05-04 23:32

本文主要是介绍STL源码笔记之型别提取技法(2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.iterator_category

    (1)Input Iterator:这种迭代器所指的对象,不允许外接改变,只读。    

    (2)Output Iterator:只写。

    (3)Forward Iterator:允许“写入型”算法在此迭代器所形成的区间上进行读写操作。

    (4)Bidirectional Iterator:可双向移动。某些算法需要逆向走访某个迭代器区间,可使用Bidirectional Iterator。

    (5)Random Access Iterator:前四种迭代器只提供一部分指针的能力(前三种只支持operator++,operator--),第五种涵盖所有指针算术能力。包括p+n、p-n、p[n]、p1-p2,p1<p2。

      为了能够提供编译迭代器动态选择,STL定义了五种标记用的型别,这样我们在调用涉及到迭代器的函数时,就能选择符合相应迭代器特性的函数。五个迭代器分别为:

                  struct input_iterator_tag{};

                  struct output_iterator_tag{};

                  struct forward_iterator_tag: public input_iterator_tag{};

                  struct bidirection_iterator_tag: public forward_iterator_tag{};

                  struct random_access_iterator_tag: public bidirection_iterator_tag{};

这些class只作标记使用,不占用任何空间。

//advance()为例
//最后一个参数只是用来重载,不需要任何成员
template<class InputIterator,class Distance>
inline void__advance(InputIterator& i,Distance n,input_iterator_tag)
{while(n--)++i;}
template<class ForwardIterator,class Distance>
inline void__advance(ForwardIterator& i,Distance n,forward_iterator_tag)
{
__advance(i,n,input_iterator_tag);
}
template<class BidirectionalIterator,class Distance>
inline void__advance(BidirectionalIterator& i,Distance n,bidirectional_iterator_tag)
{
if(n>=0)while(n--)++i;
else while(n++)--i;
}
template<class RandomAccessIterator,class Distance>
inline void__advance(RandomAccessIterator& i,Distance n,random_access_iterator_tag)
{
i+=n;
}
//调用的时候,InputIterator可以是所有上面的五种迭代器之一
template<class InputIterator,class Distance>
inline void advance(InputIterator& i,Distance n)
{
//自动选择上面的四个函数
//萃取iterator_category必须在每个iterator_traits里面
__advance( i,n,iterator_traits<InputIterator>::iterator_category());
}


2.std::iterator的保证

      为了符合规范,任何迭代器都必须要相应的型别,以利于traits萃取,否则便是自别于整个STL架构,可能无法与STL组件顺利搭配。STL定义了一个标准的iterator class,每个迭代器都继承自它,这样就保证了统一行。

template<
class Category,
class T,
class Distance = ptrdiff_t,
class Pointer = T*,
class Reference = T&              
>
struct iterator{
typedef  Category     iterator_category;
typedef  T                 value_type;
typedef  Distance     difference_type;
typedef  Pointer        pointer;
typedef  Reference   reference  ;
};

      iterator class不含任何成员,纯粹型别定义,所以继承不会招致任何负担,由于后三个参数皆有默认值。故心得迭代器只需要提供两个参数即可。

template<class T>

struct ListIter:public std: iterator<std::forward_iterator_tag,Item>

{...........}

3.__type_traits

      类型粗略的讲有两种,一种是用class封转,并且它的复制拷贝很费时,比如需要深度复制,需要safe copying——即需要调用构造函数完成复制;另一种是所谓的POD(plain old data),一般是build-in类型或是c式的struct类型,这种类型复制和拷贝时只需直接复制内存块就可以了,于是有了bitwise copying或是trival construct/deconstruct/copy/assignment的概念。

      SGI STL中使用__type_traits就可以在编译期间就确定复制一个对象是调用赋值构造函数还是直接调用memcpy,从而提高效率。看SGI STL的源代码:

  1. struct __true_type {};  
  2. struct __false_type {};  
  3.   
  4. template <class type>   //primariy template  
  5. struct __type_traits {   
  6.      typedef __true_type     this_dummy_member_must_be_first;  
  7.       
  8.     typedef __false_type    has_trivial_default_constructor;  
  9.     typedef __false_type    has_trivial_copy_constructor;  
  10.     typedef __false_type    has_trivial_assignment_operator;  
  11.     typedef __false_type    has_trivial_destructor;  
  12.     typedef __false_type    is_POD_type;  
  13. };  
  14. __STL_TEMPLATE_NULL struct __type_traits<char> { //full specialization  
  15.     typedef __true_type    has_trivial_default_constructor;  
  16.     typedef __true_type    has_trivial_copy_constructor;  
  17.      typedef __true_type    has_trivial_assignment_operator;  
  18.     typedef __true_type    has_trivial_destructor;  
  19.     typedef __true_type    is_POD_type;  
  20. };  
  21. __STL_TEMPLATE_NULL struct __type_traits<int> {  
  22.     typedef __true_type    has_trivial_default_constructor;  
  23.     typedef __true_type    has_trivial_copy_constructor;  
  24.     typedef __true_type    has_trivial_assignment_operator;  
  25.     typedef __true_type    has_trivial_destructor;  
  26.     typedef __true_type    is_POD_type;  
  27. };  
接下来,看看怎样使用__type_trairt:
[cpp]  view plain copy
  1. template <class InputIterator, class ForwardIterator, class T>  
  2. inline ForwardIterator __uninitialized_copy(InputIterator first, InputIterator last,  
  3.                      ForwardIterator result, T*) {  
  4.         typedef typename __type_traits<T>::is_POD_type is_POD;  
  5.         return __uninitialized_copy_aux(first, last, result, is_POD());  
  6. }  
  7. template <class InputIterator, class ForwardIterator> inline ForwardIterator   
  8. __uninitialized_copy_aux(InputIterator first, InputIterator last,  
  9.                          ForwardIterator result, __true_type) {  
  10.         return copy(first, last, result); //STL 算法copy里面大有乾坤,针对POD类型,调用memmove,还含有iterator_trait的使用  
  11. }  
  12. template <class InputIterator, class ForwardIterator>  
  13. ForwardIterator __uninitialized_copy_aux(InputIterator first, InputIterator last,  
  14.                          ForwardIterator result, __false_type) {  
  15.         ForwardIterator cur = result;  
  16.         for ( ; first != last; ++first, ++cur)  
  17.                construct(&*cur, *first);  
  18.         return cur;  
  19.   }  
  20. }  

这篇关于STL源码笔记之型别提取技法(2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/960331

相关文章

使用Python在Excel中插入、修改、提取和删除超链接

《使用Python在Excel中插入、修改、提取和删除超链接》超链接是Excel中的常用功能,通过点击超链接可以快速跳转到外部网站、本地文件或工作表中的特定单元格,有效提升数据访问的效率和用户体验,这... 目录引言使用工具python在Excel中插入超链接Python修改Excel中的超链接Python

C#从XmlDocument提取完整字符串的方法

《C#从XmlDocument提取完整字符串的方法》文章介绍了两种生成格式化XML字符串的方法,方法一使用`XmlDocument`的`OuterXml`属性,但输出的XML字符串不带格式,可读性差,... 方法1:通过XMLDocument的OuterXml属性,见XmlDocument类该方法获得的xm

C#提取PDF表单数据的实现流程

《C#提取PDF表单数据的实现流程》PDF表单是一种常见的数据收集工具,广泛应用于调查问卷、业务合同等场景,凭借出色的跨平台兼容性和标准化特点,PDF表单在各行各业中得到了广泛应用,本文将探讨如何使用... 目录引言使用工具C# 提取多个PDF表单域的数据C# 提取特定PDF表单域的数据引言PDF表单是一

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操

C#实现添加/替换/提取或删除Excel中的图片

《C#实现添加/替换/提取或删除Excel中的图片》在Excel中插入与数据相关的图片,能将关键数据或信息以更直观的方式呈现出来,使文档更加美观,下面我们来看看如何在C#中实现添加/替换/提取或删除E... 在Excandroidel中插入与数据相关的图片,能将关键数据或信息以更直观的方式呈现出来,使文档更

Java后端接口中提取请求头中的Cookie和Token的方法

《Java后端接口中提取请求头中的Cookie和Token的方法》在现代Web开发中,HTTP请求头(Header)是客户端与服务器之间传递信息的重要方式之一,本文将详细介绍如何在Java后端(以Sp... 目录引言1. 背景1.1 什么是 HTTP 请求头?1.2 为什么需要提取请求头?2. 使用 Spr

使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)

《使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)》在现代软件开发中,处理JSON数据是一项非常常见的任务,无论是从API接口获取数据,还是将数据存储为JSON格式,解析... 目录1. 背景介绍1.1 jsON简介1.2 实际案例2. 准备工作2.1 环境搭建2.1.1 添加

Java汇编源码如何查看环境搭建

《Java汇编源码如何查看环境搭建》:本文主要介绍如何在IntelliJIDEA开发环境中搭建字节码和汇编环境,以便更好地进行代码调优和JVM学习,首先,介绍了如何配置IntelliJIDEA以方... 目录一、简介二、在IDEA开发环境中搭建汇编环境2.1 在IDEA中搭建字节码查看环境2.1.1 搭建步

python解析HTML并提取span标签中的文本

《python解析HTML并提取span标签中的文本》在网页开发和数据抓取过程中,我们经常需要从HTML页面中提取信息,尤其是span元素中的文本,span标签是一个行内元素,通常用于包装一小段文本或... 目录一、安装相关依赖二、html 页面结构三、使用 BeautifulSoup javascript

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听