萃取

Traits 编程技法(萃取)

不论是泛型思维还是STL的实际运用,迭代器都扮演着重要的角色。迭代器是一种行为类似指针的对象,在算法中运用迭代器时,很可能会用到其相关类型。其中的相关类型就包括迭代器所指的对象的类型。假设算法中有必要声明一个变量,其类型就是迭代器所指的对象的类型,但是输入参数却只有迭代器改怎么办?
c++并没有支持typeof()!

我们假设现在要实现一个算法func,其出入参数为迭代器

void func(Iter iter)
{
	//如果我们需要一个iter指向的类型的变量,
	//该怎么声明呢?
}

方法一:参数推导

利用函数模板的参数推导机制(argument deducation)

template <class I, class T>
void fun_impl(I iter, T t)
{
	T tmp; //这里已经申请好了需要的变量
	//剩余的内容
	//...
}

于是,func函数就可以这么写:

void func(Iter iter)
{
	func_impl(iter, *iter); //将*iter传进去后,就知道了iter指向的类型
}
	

func函数将实际操作全部置于func_impl()之中,由于func_impl是一个函数模板,一旦被调用,编译器会自动进行template参数推导,于是导出类型T。

但是,当我们需要func的返回值是*iter的类型而不是void呢,我们连函数声明都写不出来!

返回值类型(不知道怎么写) func(Iter iter)
{
	func_impl(iter, *iter);
	...
}

注意:参数推导机制无法推导返回值

方法二:声明内嵌类型

template <class T>
struct Iter{
	typedef T value_type;
	//...
}
template <class I>
typename I::value_type func(I iter)
{
	return *iter;
}

这样就成功写出了func函数。
看起来不错,但是却有个隐晦的陷阱:并不是所有迭代器都是class type。原生指针就不是!如果不是class type,就无法为它定义内嵌类型。但STL(以及整个泛型思维)绝对必须接受原生指针作为一种迭代器,所以上面这样还不够,有没有办法可以让上述的一般化概念针对特殊情况做特殊化处理呢?template partial specialization(偏特化)可以做到。

方法三:萃取器

下面这个类模板专门用来萃取迭代器的特性,而value_type正是迭代器的特性之一。

template <class I>
struct iterator_traits
{
	typedef typename I::value_type value_type;
	//...
}

我们可以通过这个萃取器萃取类型I的特性,换句话说,如果类型I定义了自己的value_type,那么iterator_traits::value_type就是I::value_type。

如方法二定义的Iter结构,Iter中定义了自己的value_type,那么func就可以改写成:

template <class I>
typename iterator_traits<I>::value_type func(I iter)
{
	return *iter;
}

但这除了多了一个中间层iterator_traits,又带来什么好处呢?
好处就是,iterator_traits可以拥有特化版本。现在,我们令iterator_traits拥有一个partial specializations如下:

template <class T>
struct iterator_traits<T*> //偏特化版,迭代器是个原生指针
{
	typedef T value_type;
};

于是当我们调用func传入的是原生指针时,通过偏特化版本同样可以萃取到value_type。
到此,我们就基本解决了迭代器的相关类型的问题了!

迭代器相关类型

根据经验, 最常用到的迭代器相关类型有五种:value_type, difference_type, pointer, reference, iterator_catagoly。如果你希望你所开发的容器能与STL水乳交融,一定要为你的容器的迭代器定义这五种类型。具体内容参照STL源码剖析的相关章节。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值