- typedef typename iterator_traits<_Iter>::value_type value _type;
1:简介typename
typename iterator_traits<_Iter>::value_type是类型名;但是感到困惑的是这里为什么要使用typename关键字?
typename在C++类模板或者函数模板中经常使用的关键字,此时作用和class相同,只是定义模板参数
typename在下面情况下禁止使用:
- 模板定义之外,即typename只能用于模板的定义中
- 非限定类型,比如int,vector<int>之类
- 基类列表中,比如template <class T> class C1 : T::InnerType不能在T::InnerType前面加typename
- 构造函数的初始化列表中
如果类型是依赖于模板参数的限定名,那么在它之前必须加typename(除非是基类列表,或者在类的初始化成员列表中)。
2:Traits编程技术
在 STL 编程中,容器和算法是独立设计的,即数据结构和算法是独立设计的,连接容器和算法的桥梁就是迭代器了,迭代器使其独立设计成为可能。 Traits 编程技术是STL中最重要的编程技术,Traits可以获取一个类型的相关信息。
若我们要知道用户自定义类型的函数返回值类型,我们可以使用内嵌型别技术就可以知道返回值的类型;看下面程序:
- templates <class T>
- struct Iterator
- {
- typedef T value_type;//内嵌型别声明
- ...
- };
- template <class Iterator>
- typename Iterator::value_type //返回值类型
- GetValue(Iterator iter)
- {
- return *iter;
- }
- int main()
- {
- ...
- Iterator<int> ite(new int(9)); //<可以知道value_type是int,那么GetValue最后也是返回int类型
- std::cout<<GetValue(ite)<<std::endl;
- return 0;
- }
- template <class Iterator>
- struct iterator_traits {
- typedef typename Iterator::value_type value_type; //<运用了typename 这个变量表示这是一个型别
- ...
- };
- template <class Iterator>
- typename iterator_traits<Iterator>::value_type //返回值类型
- GetValue(Iterator iter)
- {
- return *iter;
- }
- template <class Tp>
- struct iterator_traits<Tp*> {
- typedef Tp value_type;
- ...
- };
- template <class Tp>
- struct iterator_traits<const Tp*> {
- typedef Tp value_type; //<我们需要提取的是non-const类型,提取一个不能复制的变量没有任何意义
- ...
- };
我们之所以要萃取 (Traits) 迭代器相关的类型,就是要把迭代器相关的类型用于声明局部变量、用作函数的返回值等一系列行为。对于原生指针和 point-to-const 类型的指针,采用模板偏特化技术对其进行特殊处理。要使用Traits功能,则必须自行以内嵌型别定义的方式定义出相应型别。我们上面讲解的只是迭代器其中一种类型value type,在迭代器中还有其他类型
3: 5中迭代器
- template <class _Iterator>
- struct iterator_traits {
- typedef typename _Iterator::iterator_category iterator_category; //迭代器类型
- typedef typename _Iterator::value_type value_type; //迭代器所指对象的类型
- typedef typename _Iterator::difference_type difference_type;//迭代器之间距离
- typedef typename _Iterator::pointer pointer; //迭代器所指之物
- typedef typename _Iterator::reference reference; //迭代器引用之物
- };
1.value type 迭代器所指向的对象的类型 比如说 vector<int >::iterator it; 那么 value type 的值为 int
2.difference type 可以表示两个迭代器之间的距离 ,比如说,可以用这种类型来计数, 如,typename iterator_traits<I>::difference_type n =0, for(I first ; first != end; ++first ) n++; //n这种变量可做计数,算容量
3.reference type 引用类型,
4.pointer type 指针类型
5.iterator _category 迭代器本身的类型 (详情看下一小节),这个内部类型可以用于标识本身的类型,可用函数重载时候的版本识别, 所有重载时候的版本识别:主要是由于迭代器有5大类,无疑random_access_iterator 的功能是最强大的,但是并不是每次都是用最强大的一个版本性能就是最高的,由于其功能强大了,无疑内部实现会复杂一点,既有可能性能会有所下降,不过相当多的迭代器都是Random Access iterator 这种类型的,如果一个算法find()能够接受一个input_iterator,那么给它Random Access iterator 未必最好,因此,可以实现接受五个版本 的迭代器类型 find()函数,按需选择,(注意不要使用动态绑定,这样会大大减低性能),可以在算法中find(Iterator , iterator tag),加入一个用于识别的参数,然后通过,iterator_traits<Iterator >::category萃取出来这个category类型,可以实现函数版本识别
5中是迭代器:
#include<iostream>
#include<vector>
#include<list>
#include<deque>
#include<iterator>
using namespace std;
//下面定义5个版本的func函数,为了简单起见,就一个参数,分别表示不同的迭代器类型
void func(random_access_iterator_tag)
{
cout<<"random_access_terator 类型的迭代器"<<endl;
}
void func(bidirectional_iterator_tag)
{
cout<<"bidirectional_terator 类型的迭代器"<<endl;
}
void func(forward_iterator_tag)
{
cout<<"forward_terator 类型的迭代器"<<endl;
}
void func(input_iterator_tag)
{
cout<<"input_terator 类型的迭代器"<<endl;
}
void func(output_iterator_tag)
{
cout<<"output_terator 类型的迭代器"<<endl;
}
//这里提供一个接口给用户使用fun()
template<class InputIterator >
void fun(InputIterator it)
{//这句代码最关键,利用iterator_traits<IputIterator>萃取出 iterator_category属性
typedef iterator_traits<InputIterator>::iterator_category category;
func(category()); //调用去萃取
}
int main()
{
vector<int> ve ;
for(int i = 0;i<10;i++)
ve.push_back(i);
int cc=5;
int *d = &cc; //第一个迭代器,指向int 类型
//第二个迭代器
vector<int>::iterator a = ve.begin();
//第三个迭代器
std::istream_iterator<int> is ;
//分别对其调用fun函数
fun(d);
fun(a);
fun(is);
system("pause");
return 0;
}
本文详细介绍了C++ STL中的iterator_traits结构体以及Traits编程技术。通过typename关键字来处理模板中依赖于类型参数的名称,确保它们被解析为类型。文中讨论了在不同场景下typename的使用限制,并展示了如何通过iterator_traits获取迭代器的value_type、difference_type等属性,以及在实际编程中如何利用这些属性进行类型推断和迭代器类型的分类。

190

被折叠的 条评论
为什么被折叠?



