您的位置:首页 > 编程语言 > C语言/C++

《Essential C++》笔记三(1)、使用泛型算法

2013-09-30 22:34 232 查看
Essential C++第三章主要介绍的是泛型编程风格。

在讲“如何设计泛型算法”时,给出了一个filter的template例子。为了更好的理解和运用泛型算法以及template。将P89(中文版)页给出的sub_vec函数写成template版本。

其原版non-template函数如下:

vector<int> sub_vec( const vector<int> &vec, int val )
{
vector<int> local_vec( vec );
sort ( local_vec.begin(), local_vec.end() );

vector<int>::iterator iter =
find_if (	local_vec.begin(),
local_vec.end(),
bind2nd( greater<int>(), val ));

local_vec.erase ( iter, local_vec.end() );
return local_vec;
}

将其改为template格式后,函数返回一个iterator指针,指针指向find_if找到的第一个大于指定值的元素,函数为:

//sub_vec的泛型算法
template <	typename InputIterator,	typename OutputIterator,	typename ElemType>
OutputIterator
sub_vec ( InputIterator first, InputIterator last, OutputIterator at, const ElemType &val )
{
OutputIterator at_begin = at;
while ( first < last )
*at++ = *first++;
OutputIterator at_end = at;
sort ( at_begin, at_end );
OutputIterator iter = find_if ( at_begin, at_end, bind2nd ( greater<ElemType>(), val ));
return iter;
}

这样改写是因为,之前的non-template版本与书中改写的filter()函数最大的不一样就是,需要另外开辟空间保证在不改变原数据的顺序的情况下在副本进行排序。而为了增加函数的弹性和扩大函数可用的范围,就不能按照non-template版本那样,通过语句
vector<int> local_vec( vec );

来建立一个本地的向量。根据Essential C++书中所说,还是采用iterator指针来解决这一问题。虽然这样做可以使函数脱离vector等容器,但走到最后erase一步时,库中没有提供删除的泛型算法,现在还没有想到解决办法,希望知道怎么做的人能留言O(∩_∩)O~。

为了跟书中的filter()函数功能相同,最后加上比较操作,用户可以通过输入比较操作来控制最后留下的数是大于value还是小于value。实现代码如下:

//sub_vec的泛型算法改编的filter()算法
template <	typename InputIterator,	typename OutputIterator,
typename ElemType,	typename Comp>
OutputIterator
filter ( InputIterator first, InputIterator last, OutputIterator at,
const ElemType &val, Comp pred )
{
OutputIterator at_begin = at;
while ( first < last )
*at++ = *first++;
OutputIterator at_end = at;
sort ( at_begin, at_end, pred );
OutputIterator iter = find_if ( at_begin, at_end, bind2nd ( not2( pred ), val ));
return iter;
}


下面贴出测试该函数的main函数代码:
int main()
{
const int element_size = 10;
int number[ element_size ] = {32, 54, 22, -23, 78, 99, 0, 698, 10, 2};
vector<int> big_vec ( number, number+element_size );
int value = 10;
vector<int> sub_vector( element_size );
cout << "filtering integer array for values less than " << value << endl;
vector<int>::iterator iter = filter ( big_vec.begin (), big_vec.end(),  sub_vector.begin() , value, less<int>() );
if( iter != sub_vector.end() )
sub_vector.erase( iter , sub_vector.end() );
for ( int ix = 0; ix < sub_vector.size(); ++ix )
cout << "element is : " << sub_vector[ix] << endl;

return 0;
}

需要注意的是,定义的容器一定要定义容量(vector<int> sub_vector(element_size);),否则在编译时会发生错误,初步认为filter()函数中*at++ = *first++;这句话中自加到最后会指向不明地址,编译器无法通过,所以需要定义容器容量。还需注意的是,返回的指针iter,由于需要erase操作,最好先检测是否指针指到容器最后一个指针。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: