C++沉思录读书笔记(20章)- 通过迭代器配接器提高泛型算法的通用性

此次将通过一个例子来说明迭代器配接器的作用,具体来说,使用迭代器配解器也可以扩展泛型算法的通用性
迭代器配接器,就是把迭代器作为参数并转化为其他迭代器的模板

口头的空谈太过于抽象而言而无实,讲很多也未必能理解,软件工程师看代码的能力一般比看中文的能力强,通过阅读代码进行理解可靠得多,所以应该避免过多的口舌


我们的作为示范的泛型算法模板如下

template <class T, class X>
T find(T start, T beyond, const X& x)
{
	while(start != beyond && *start != x)
		++start;
	return start;
}
显然这个算法模板是从头往后找出第一个值为x的元素,并返回这个元素对应的迭代器
现在假设我们需要从尾到头找出第一个元素值为x的元素,我们需要重新写一个泛型算法么?

答案是不需要,我们可以通过迭代器配接器来让find算法也适用于从尾到头查找元素的场合,显然这能让find算法模板的通用性进一步提高

示范代码如下:

#include <iostream>
using namespace std;
template <class T, class X>
T find(T start, T beyond, const X& x)  //泛型算法模板
{
	while(start != beyond && *start != x)
		++start;
	return start;
}

template<class It, class T>
class Rev //迭代器配解器
{
	// It it;  //这三行代码必须注释掉才能够编译不出错,vs编译器对模板的支持确实不行
	//friend bool operator==(const Rev<It,T>&,  const Rev<It,T>&);
	//friend bool operator!=(const Rev<It,T>&,  const Rev<It,T>&);
public:
	It it;  //it本应该设置成为私有成员的,为了通过vs编译器而不得以将其设为公有
	Rev();
	Rev(It i) :it(i) {}
	operator It() { return it; }

	//将参数迭代器反向
	Rev<It,T>& operator++() { --it; return *this; }
	Rev<It,T>& operator++(int)
	{
		Rev<It,T> r = *this;
		--it;
		return r;
	}
	Rev<It,T>& operator--() { ++it; return *this; }
	Rev<It,T>& operator--(int)
	{
		Rev<It,T>& r = *this;
		++it;
		return r;
	}
	T& operator*()
	{
		It i = it;
		--i;
		return *i;
	}

};

template<class It, class T>
bool operator==(const Rev<It,T>& x,  const Rev<It,T>& y)
{
	return x.it == y.it;
}

template<class It, class T>
bool operator!=(const Rev<It,T>& x,  const Rev<It,T>& y)
{
	return x.it != y.it;
}

typedef Rev<int*,int> REV;
void main()
{
	int a[] = {0,7,2,3,4,5,6,7,8,9};
	int *p = find(a, a+10, 8); //正向查找
	cout << *p << endl;

	REV r = find(REV(a+10), REV(a), 7); //反向查找
	cout << *r << endl;
	r--;
	cout << *r;   //如果输出8,则确实是反向查找元素
}

总结:泛型算法不仅能实现独立于类型,独立于数据结构,还能实现普遍的抽象,甚至两个步骤看起来截然相反的场合,通过迭代器配接器也可以实现算法的统一。


思考:执着于这种技巧是否有必要?是不是华而不实?学习究竟应该应该遵从一个什么样的原则?

大牛或前辈要是路过看到这些,请留言指点下。


你可能感兴趣的:(C++沉思录读书笔记(20章)- 通过迭代器配接器提高泛型算法的通用性)