C++标准库(STL)学习笔记(三)仿函数&适配器&元组

C++标准库(STL)学习笔记(三)仿函数&适配器&元组

1、仿函数

仿函数或函数对象functor,是能当函数用的类,为算法服务。为了模仿函数的行为,仿函数需要重载括号运算符()。其实说白了仿函数就是重载了括号的类,并没什么很特殊的玩意。标准库有提供一些仿函数,需要用的时候可以去翻一翻。

自定义的仿函数应该继承仿函数的基类以融入STL的体系。如unary_function类对应一个操作数的仿函数,binary_function对应两个操作数的仿函数。继承基类是为了获得基类中做的类定义,这样仿函数就能够回答使用它的算法关于类型的提问。基类的实现没有参数,只有几个需要的类型定义。

2、适配器

适配器是一个中介的角色,本身不实现什么功能,通过使用并修改源类来实现需要的功能。适配器可以用来修改容器,迭代器等,还可以用来修改函数。长在函数上的适配器叫函数适配器,函数适配器也要被当作函数用,所以也是一种仿函数,要重载()。

好像有点复杂,编一个例子。有一个算法叫count_if(),可以统计容器中满足给出的条件的元素个数。如果我们有一个整数vector,现在想统计其中小于100的数的个数。我们有一种很方便的写法:

int count = count_if(vec.begin(), vec.end(), bind(less<int>(), std::placeholders::_1, 100));

虽然看起来也不是很方便的样子,但起码一行能完成要求的功能,而且能看出来什么意思。less是一个仿函数,由标准库提供,比较两个数,但是它要求两个参数。bind的作用就是把第二个参数固定为100。std::placeholders是一群占位符,在这里表示我们不绑定第一个参数。bind是一个函数适配器,也可以说是个仿函数,定义其实并不重要。

这里说一下跟bind有关的一件事。如果使用bind绑定类成员函数的参数,要注意类的成员函数会有一个隐式的参数this,所以要先放一个占位符占住this的位置。

3、Tuple元组

tuple可以指定任意个数的任意类型组成一个整体单元。

tuple的实现使用了c++11可变模板参数的新特性。tuple的类型声明大概是这样:

template<typename Head, typename... Tail>
class tuple<Head, Tail> : private tuple<Tail...>
{}

template<typename Head>
class tuple<Head>
{}

刚开始看有点难看懂。首先可变模板参数,也就是那个...可以替代任意个数的任意类型的参数。这个tuple干的事情就是把输入的一堆参数中拿出来一个,在这个类中处理一下,剩下的丢给另一个tuple去做,并且继承这个tuple。当最后只剩一个参数时,由于偏特化的性质,会调用最合适的第二个版本。最终形成了一个继承一个的链条,最顶端的类里有最后一个参数,最底端的类里是第一个参数。

tuple的用法。获得某个元素,std::get<index>(someTuple)index为第几个元素,从0开始数。如果这个tuple是未知的,如函数参数,可以通过std::typle_element<index, someTuple>::type获得指定序号元素的类型。

posted @ 2021-04-15 14:41  Napoleon0  阅读(137)  评论(0)    收藏  举报