解决原生指针后,为什么还要引入traits?

bsnry 2012-03-19 10:55:52
对萃取这块很 迷糊。 不知道为什么要引入它。 看了一篇网文。

网文的作者没有 说 引入萃取的原因,只是一来就提供了一个关于迭代器的例子

(MyIter支持原生指针)

template <class T>
struct MyIter {
typedef T value_type;
T* ptr;
MyIter(T* p = 0) : ptr(p) {}
T const & operator*() const { return *ptr; }
};

template<class T>
struct MyIter<T*>
{
typedef T value_type;
T* ptr;
MyIter(T* p=0):ptr(p){}
T const & operator*() const { return *ptr; }
};

//使用迭代器的一个函数,获得迭代器所指的对象。
template<class I>
typename I::value_type TestFunc( I iter)
{
return *iter;
}




接着作者,又提供了类iterator_traits :

template <class I>
struct iterator_traits {
Typedef I::value_type value_type;
}
template <class T>
struct iterator_traits<T*> {
typedef T value_type;
};


不懂 ,为什么要引入 iterator_traits 呢?? MyIter 已经可以解决 原生指针的问题,引入iterator_traits 干嘛啊。


...全文
171 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
bsnry 2012-03-21
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 bluewanderer 的回复:]
template <class T1, class T2, class T3, class T4>
struct OMG
{
...
};

这个时候你还不希望有一个独立模板处理萃取么?
[/Quote]多少体会到了,

迭代器很多, 所以用一个 萃取类 来榨取各种类型。。。。。。。。

可能刚开始学的时候,没有完全领会到萃取的强大之处。。。

我能否再问个问题吗?


回答stl帖子的人真不多,又要劳累你了。
我写了两个迭代器,  迭代器类型有两种:FirstCategory和SecondCategory.

一个接口函数MyAdvance, 其模拟std::advance,我发现,我写的不能够支持原生指针。

代码如下:

struct FirstCategory
{

};


struct SecondCategory:public FirstCategory
{

};

//迭代器1
template <class T>
struct MyIter {
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef FirstCategory category; //迭代器类型
T* ptr;
MyIter(T* p = 0) : ptr(p) {}
T& operator*() const { return *ptr; }

};

//迭代器2
template <class T>
struct MyIter2 {
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef SecondCategory category; //迭代器类型
T* ptr;
MyIter2(T* p = 0) : ptr(p) {}
T& operator*() const { return *ptr; }

};



//萃取机
template <class T>
struct MyTraits {
typedef typename T::value_type value_type;
typedef typename T::reference reference;
typedef typename T::category category;
};



template<class T>
struct MyTraits<T*>
{
typedef T value_type;
typedef T& reference;
typedef T category;
};

template<class T>
struct MyTraits<T const*>
{
typedef T value_type;
typedef T const& reference;
typedef T category;
};



template<class Iter >
void _MyAdvance(Iter iter, int n , FirstCategory)
{
cout<<"MyIterCategory"<<endl;
}

template<class Iter>
void _MyAdvance(Iter iter, int n , SecondCategory)
{
cout<<"MyIterCategory2"<<endl;
}

//接口类, 模拟std::advance这个函数
template<class Iter>
void MyAdvance(Iter iter, int n)
{
_MyAdvance(iter,n, MyTraits<Iter>::category()); //当iter不是迭代器,是原生指针的时候,就会出错,原因是无法匹配_MyAdvance
}


比如:iter是int* ,Mytraits<int*>::category()榨取出来的就是int,就无法调用_MyAdvance这个函数模板了。。

我该怎么修改,让其支持 原生指针。 std::advance是支持原生指针的。


bluewanderer 2012-03-20
  • 打赏
  • 举报
回复
template <class T1, class T2, class T3, class T4>
struct OMG
{
...
};

这个时候你还不希望有一个独立模板处理萃取么?
bsnry 2012-03-19
  • 打赏
  • 举报
回复


呵呵
bluewanderer 2012-03-19
  • 打赏
  • 举报
回复
假设你有十个类都需要对模板变量进行这种处理,有的类甚至有好几个模板变量要处理,你总不能挨个特例化吧。

用分离出来的traits,你可以直接写
template <class T>
struct MyIter {
typedef xxx_traits<T>::value_type value_type;
value_type* ptr;
MyIter(value_type* p = 0) : ptr(p) {}
value_type const & operator*() const { return *ptr; }
};

而不是去特理化MyIter
bsnry 2012-03-19
  • 打赏
  • 举报
回复
你经常回复我的问题,谢谢了啊。。

但是你这次的回答,我没看懂啊

每个类 都那么折腾一次?

每个类 指的是哪个类? 能说一下吗?

2. 迭代器类是必须有的,通过它去访问 类。。。。我提供个Test类:

MyIter是可以做到访问它。

class Test
{
int* ptr; //仅仅用来指向一个整形变量
public:
Test(int* pdata=0 ):ptr(pdata){}

~Test(){ delete ptr; }

int* operator->( ) const
{
return ptr;
}
int operator* () const
{
return *ptr;
}
};





[Quote=引用 1 楼 bluewanderer 的回复:]

用iterator_traits你就不用每个类都那么折腾一次了啊
[/Quote]
bluewanderer 2012-03-19
  • 打赏
  • 举报
回复
用iterator_traits你就不用每个类都那么折腾一次了啊
bsnry 2012-03-19
  • 打赏
  • 举报
回复
。。。。。。榨取到什么???

为什么要榨取,不是说了嘛,功能已经满足了, 主贴的MyIter 可以作为一个迭代器使用了,

干嘛要 再引入 萃取机子来



[Quote=引用 9 楼 gxut555 的回复:]

traits 所扮演的「特性萃取机」角色,萃取各个迭代器的特性。这里
所谓的迭代器特性,指的是迭代器的相应型别(associated types)。

根据经验, 最常用到的迭代器相应型别有五种:value type , difference type ,
pointer , reference , iterator catagoly 。如果你希望你所开发的容器能与STL 水乳
交融,……
[/Quote]
深圳小北 2012-03-19
  • 打赏
  • 举报
回复
traits 所扮演的「特性萃取机」角色,萃取各个迭代器的特性。这里
所谓的迭代器特性,指的是迭代器的相应型别(associated types)。

根据经验, 最常用到的迭代器相应型别有五种:value type , difference type ,
pointer , reference , iterator catagoly 。如果你希望你所开发的容器能与STL 水乳
交融,㆒定要为你的容器的迭代器定义这五种相应型别。「特性萃取机」traits 会
很忠实地将原汁原味榨取出来:
template <class I>
struct iterator_traits {
typedef typename I::iterator_category iterator_category;
typedef typename I::value_type value_type;
typedef typename I::difference_type difference_type;
typedef typename I::pointer pointer;
typedef typename I::reference reference;
};



他这里不仅仅是原始指针,还要推导出自定义类型的。。。建议你看看stl源码剖析
iamnobody 2012-03-19
  • 打赏
  • 举报
回复


#include <iostream>
#include <algorithm>
#include <vector>

template <typename T>
void increaser(T iter)//这个函数的功能是让迭代器参数指向的内容加1
{
//在这个函数里面我们只知道迭代器的类型,不知道迭代器的其他信息,比如要知道他指向的类型,那么就要用下面的方法:

std::iterator_traits<T>::value_type value;//当然,本例中没有必要用这个变量,这里只是为了演示.
value = *iter + 1;
*iter = value;
}

int main()
{
int arr[100] = {0};
increaser(arr + 1);//这里的参数是 int* 类型,不是类类型,所以,不能用 Iterator::value_type这种方法来得到他的元素类型.
std::vector<int> vec(100);
increaser(vec.begin() + 1);//类类型的迭代器.

std::cout<<arr[1]<<std::endl<<vec[1];
system("pause");
}




不知道你要问什么,,,大概像上面说的那样..
学这个最好是看一本书,系统学一下.

例如 the C++ template
bsnry 2012-03-19
  • 打赏
  • 举报
回复
高手,高手,你在哪里啊
bsnry 2012-03-19
  • 打赏
  • 举报
回复
可能你没有看明白我的疑问所在

就事论事,你看 MyIter这个类 ,通过它可以访问 其他类。。。

MyIter<类名> iter;

MyIter<int*>iterInt;

都是可以的。。。 已经解决了原生指针的问题了。


此时 ,网文又提供了一个叫 iterator_traits 的类, 我发帖 就是问:

已经解决原生指针了,为什么还要再引入 iterator_traits 这个类呢?

岂非多余??

[Quote=引用 5 楼 qq120848369 的回复:]

萃取是萃取,特化是特化,有关系?
[/Quote]
qq120848369 2012-03-19
  • 打赏
  • 举报
回复
萃取是萃取,特化是特化,有关系?

64,639

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧