STL学习之路之仿函数

STL中的仿函数(或者叫做函数对象):可以实现类似于函数一样的类型,函数最直接的调用形式就是:返回值 函数名(参数列表),仿函数实现了operator()操作符,使用类似于函数。

同时,STL还为仿函数提供了强大的配接器,也就是适配器Adapters,这些适配器本身也属于仿函数,调用方式同样类似于函数。更进一步,这些适配器可以和仿函数、函数、适配器再进行绑定、组合、适配,完成更加复杂的功能。

这部分应该是STL中最简单的部分,实现也比较简单。另外C++11标准对这部分调整比较大,我们先不考虑。暂且把它作为一个学习template的例子。

#ifndef TESTFUNCTIONAL_H
#define TESTFUNCTIONAL_H

namespace Test{
template<class _Arg, class _Result>
struct unary_function
{
	typedef _Arg argument_type;
	typedef _Result result_type;
};

template<class _Arg1, class _Arg2, class _Result>
struct binary_function
{
	typedef _Arg1 first_argument_type;
	typedef _Arg2 second_argument_type;
	typedef _Result result_type;
};

template<class _Tp>
struct plus : public binary_function<_Tp, _Tp, _Tp>{
	_Tp operator()(const _Tp& _x, const _Tp& _y) const {	return _x + _y; }
};

template<class _Tp>
struct minus : public binary_function<_Tp, _Tp, _Tp>{
	_Tp operator()(const _Tp& _x, const _Tp& _y) const { return _x - _y; }
};

template<class _Tp>
struct multiplies : public binary_function<_Tp, _Tp, _Tp>{
	_Tp operator()(const _Tp& _x, const _Tp& _y) const { return _x * _y; }
};

template<class _Tp>
struct divides : public binary_function<_Tp, _Tp, _Tp>{
	_Tp operator()(const _Tp& _x, const _Tp& _y) const { return _x / _y; }
};

template<class _Tp>
struct modulus : public binary_function<_Tp, _Tp, _Tp>{
	_Tp operator()(const _Tp& _x, const _Tp& _y) const { return _x % _y; }
};

template<class _Tp>
struct negate : public unary_function<_Tp, _Tp>{
	_Tp operator()(const _Tp& _x) const { return -_x; }
};

template <class _Tp>
struct equal_to : public binary_function<_Tp,_Tp,bool>
{
	bool operator()(const _Tp& __x, const _Tp& __y) const { return __x == __y; }
};

template <class _Tp>
struct not_equal_to : public binary_function<_Tp,_Tp,bool>
{
	bool operator()(const _Tp& __x, const _Tp& __y) const { return __x != __y; }
};

template <class _Tp>
struct greater : public binary_function<_Tp,_Tp,bool>
{
	bool operator()(const _Tp& __x, const _Tp& __y) const { return __x > __y; }
};

template <class _Tp>
struct less : public binary_function<_Tp,_Tp,bool>
{
	bool operator()(const _Tp& __x, const _Tp& __y) const { return __x < __y; }
};

template <class _Tp>
struct greater_equal : public binary_function<_Tp,_Tp,bool>
{
	bool operator()(const _Tp& __x, const _Tp& __y) const { return __x >= __y; }
};

template <class _Tp>
struct less_equal : public binary_function<_Tp,_Tp,bool>
{
	bool operator()(const _Tp& __x, const _Tp& __y) const { return __x <= __y; }
};

template <class _Tp>
struct logical_and : public binary_function<_Tp,_Tp,bool>
{
	bool operator()(const _Tp& __x, const _Tp& __y) const { return __x && __y; }
};

template <class _Tp>
struct logical_or : public binary_function<_Tp,_Tp,bool>
{
	bool operator()(const _Tp& __x, const _Tp& __y) const { return __x || __y; }
};

template <class _Tp>
struct logical_not : public unary_function<_Tp,bool>
{
	bool operator()(const _Tp& __x) const { return !__x; }
};

template<class _Predicate>
class unary_negate : public unary_function<typename _Predicate::argument_type, bool>{
protected:
	_Predicate _M_pred;
public:
	explicit unary_negate(const _Predicate& _x):_M_pred(_x){}
	bool operator()(const typename _Predicate::argument_type& _x) const {
		return !_M_pred(_x);
	}
};

template<class _Predicate>
inline unary_negate<_Predicate>
	not1(const _Predicate& _pred){
		return unary_negate<_Predicate>(_pred);
}
template<class _Predicate>
class binary_negate : public binary_function<typename _Predicate::first_argument_type,
		typename _Predicate::second_argument_type, bool>{
protected:
	_Predicate _M_pred;
public:
	explicit binary_negate(const _Predicate& _x) : _M_pred(_x) {}
	bool operator()(const typename _Predicate::first_argument_type& _x,
		const typename _Predicate::second_argument_type& _y) const{
			return !_M_pred(_x, _y);
	}
};

template<class _Predicate>
inline binary_negate<_Predicate>
	not2(const _Predicate& _pred)
{
	return binary_negate<_Predicate>(_pred);
}

//绑定一个二元操作符类的第一个操作数,也就是调用operator()参数需要传递第二个操作数
template<class _Operation>
class binder1st : public unary_function<typename _Operation::second_argument_type,//派生自一元操作符类,
					//一元操作符的参数类型为该二元操作符类的第二个操作数类型,与需要调用的operator()参数类型一样
			typename _Operation::result_type>{
protected:
	_Operation _op;
	typename _Operation::first_argument_type value;
public:
	binder1st(const _Operation& op, const typename _Operation::first_argument_type& _x)
		:_op(op), value(_x){}
	typename _Operation::result_type operator()(const typename _Operation::second_argument_type& _y) const{
		return _op(value, _y);
	}
};

template<class _Operation, class _Tp>
inline binder1st<_Operation>
 bind1st(const _Operation& op, const _Tp& _x){
	 typedef typename _Operation::first_argument_type _Arg1_type;
	 return binder1st<_Operation>(op, _Arg1_type(_x));
}

//绑定一个二元操作符类的第二个操作数,也就是调用operator()参数需要传递第一个操作数
template<class _Operation>
class binder2nd : public unary_function<typename _Operation::first_argument_type,//派生自一元操作符类,
					//一元操作符的参数类型为该二元操作符类的第二个操作数类型,与需要调用的operator()参数类型一样
				typename _Operation::result_type>{
protected:
	_Operation _op;
	typename _Operation::second_argument_type value;
public:
	binder2nd(const _Operation& op, const typename _Operation::second_argument_type& _y)
		:_op(op), value(_y){}
	typename _Operation::result_type operator()(const typename _Operation::first_argument_type& _x) const{
		return _op(_x, value);
	}
};

template<class _Operation, class _Tp>
inline binder2nd<_Operation>
	bind2nd(const _Operation& op, const _Tp& _y)
{
	typedef typename _Operation::second_argument_type _Arg2_type;
	return binder2nd<_Operation>(op, _Arg2_type(_y));
}

//f(g(x))
template<class _Operation1, class _Operation2>
class unary_compose : public unary_function<typename _Operation2::argument_type,
			typename _Operation1::result_type>
{
protected:
	_Operation1 _M_op1;
	_Operation2 _M_op2;
public:
	unary_compose(const _Operation1& op1, const _Operation2& op2)
		:_M_op1(op1), _M_op2(op2){}
	typename _Operation1::result_type operator()(const typename _Operation2::argument_type & _x) const {
		return _M_op1(_M_op2(_x));
	}
};

template<class _Operation1, class _Operation2>
inline unary_compose<_Operation1, _Operation2>
	compose1(const _Operation1& op1, const _Operation2& op2){
		return unary_compose<_Operation1, _Operation2>(op1, op2);
}

//f(g1(x), g2(x))
template<class _Operation1, class _Operation2, class _Operation3>
class binary_compose : binary_function<typename _Operation2::argument_type,
																	typename _Operation3::argument_type,
																	typename _Operation1::result_type>
{
protected:
	_Operation1 _M_op1;
	_Operation2 _M_op2;
	_Operation3 _M_op3;
public:
	binary_compose(const _Operation1& op1, const _Operation2& op2, const _Operation3& op3)
		:_M_op1(op1), _M_op2(op2), _M_op3(op3){}
	typename _Operation1::result_type operator()(typename const _Operation2::argument_type& _x) const{
		return _M_op1(_M_op2(_x), _M_op3(_x));
	}
};

template<class _Operation1, class _Operation2, class _Operation3>
inline binary_compose<_Operation1, _Operation2, _Operation3>
	compose2(const _Operation1& op1, const _Operation2& op2, const _Operation3& op3){
		return binary_compose<_Operation1, _Operation2, _Operation3>(op1, op2, op3);
}

//普通单参数函数转对象
template<class _Arg, class _Result>
class pointer_to_unary_function : public unary_function<_Arg, _Result>{
protected:
	_Result (*_pfn)(_Arg);
public:
	pointer_to_unary_function(){}
	explicit pointer_to_unary_function(_Result (*pfn)(_Arg)) : _pfn(pfn){}
	_Result operator()(_Arg _x) const{
		return _pfn(_x);
	};
};

template<class _Arg, class _Result>
inline pointer_to_unary_function<_Arg, _Result>
	ptr_fun(_Result (*pfn)(_Arg)){
		return pointer_to_unary_function<_Arg, _Result>(pfn);
}

//普通2参数函数转对象
template<class _Arg1, class _Arg2, class _Result>
class pointer_to_binary_function : public binary_function<_Arg1, _Arg2, _Result>
{
protected:
	_Result (*_pfn)(_Arg1, _Arg2);
public:
	pointer_to_binary_function(_Result (*pfn)(_Arg1, _Arg2))
		:_pfn(pfn){}
	_Result operator()(_Arg1 _x, _Arg2 _y) const{
		return _pfn(_x, _y);
	}
};

template<class _Arg1, class _Arg2, class _Result>
inline pointer_to_binary_function<_Arg1, _Arg2, _Result>
	ptr_fun(_Result (*pfn)(_Arg1, _Arg2)){
		return pointer_to_binary_function<_Arg1, _Arg2, _Result>(pfn);
}

//类函数,类对象指针
template<class _Ret, class _Tp>
class mem_fun_t : public unary_function<_Tp*, _Ret>{
protected:
	_Ret (_Tp::*_pfn)();
public:
	explicit mem_fun_t(_Ret (_Tp::*pfn)()) : _pfn(pfn){}
	_Ret operator()(_Tp* _p) const{
		return (_p->*_pfn)();
	}
};

//类const函数,类对象指针
template<class _Ret, class _Tp>
class const_mem_fun_t : public unary_function<const _Tp*, _Ret>{
protected:
	_Ret (_Tp::*_pfn)() const;
public:
	explicit const_mem_fun_t(_Ret (_Tp::*pfn)() const): _pfn(pfn) {}
	_Ret operator()(const _Tp* _p) const{
		return (_p->*_pfn)();
	}
};

//类函数,类对象引用
template<class _Ret, class _Tp>
class mem_fun_ref_t : public unary_function<_Tp, _Ret>{
protected:
	_Ret (_Tp::*_pfn)();
public:
	explicit mem_fun_ref_t(_Ret (_Tp::*pfn)()) : _pfn(pfn){}
	_Ret operator()(_Tp& _p) const{
		return (_p.*_pfn)();
	}
};

//类const函数,类对象引用
template<class _Ret, class _Tp>
class const_mem_fun_ref_t : public unary_function<_Tp, _Ret>{
protected:
	_Ret (_Tp::*_pfn)();
public:
	explicit const_mem_fun_ref_t(_Ret (_Tp::*pfn)() const) : _pfn(pfn){}
	_Ret operator()(const _Tp& _p) const{
		return (_p.*_pfn)();
	}
};

//含参数省略......
template<class _Ret, class _Tp>
inline mem_fun_t<_Ret, _Tp>
	mem_fun(_Ret (_Tp::*pfn)()){
		return mem_fun_t<_Ret, _Tp>(pfn);
}

template<class _Ret, class _Tp>
inline const_mem_fun_t<_Ret, _Tp>
	mem_fun(_Ret (_Tp::*pfn)() const){
		return const_mem_fun_t<_Ret, _Tp>(pfn);
}

template<class _Ret, class _Tp>
inline mem_fun_ref_t<_Ret, _Tp>
	mem_fun_ref(_Ret (_Tp::*pfn)()){
		return mem_fun_ref_t<_Ret, _Tp>(pfn);
}

template<class _Ret, class _Tp>
inline const_mem_fun_ref_t<_Ret, _Tp>
	mem_fun_ref(_Ret (_Tp::*pfn)() const){
		return const_mem_fun_ref_t<_Ret, _Tp>(pfn);
}
}
#endif	//TESTFUNCTIONAL_H

实现方面我写了一部分,一些相似的偷懒省略了,如果想看完整版的可以下载源码。另外,我还对它做了一些测试:

#include "TestFunctional.h"
#include <stdlib.h>
#include <iostream>
using namespace std;

class TestClass{
public:
	void testFun()	{ cout << "testfun" << endl; }
	void testFunC() const { cout << "testfun1 const" << endl;}
};
int main(int argc, char *argv[])
{
	typedef Test::less<int> Op_less;
	int opVal = 6;
	int val = 4;
	// 6 < x
	Test::binder1st<Op_less > bd1 = Test::bind1st<Op_less, double>(Op_less(), opVal);
	cout << opVal << " less than " << val << '\t' << boolalpha << bd1(val) << endl;
	// x < 6 ,即 6 > x
	Test::binder2nd<Op_less > bd2 = Test::bind2nd<Op_less, double>(Op_less(), opVal);
	cout << val << " less than " << opVal << '\t'  << boolalpha << bd2(val) << endl;

	//f(x) = 3 * x, g(x) = x + 2 ==> f(g(x)) = (x + 2) * 3;
	typedef Test::plus<int>			Op_plus;
	typedef Test::multiplies<int> Op_mult;
	cout << Test::compose1<Test::binder1st<Op_mult>, Test::binder2nd<Op_plus> >(
		Test::bind1st<Op_mult, int>(Op_mult(), 3), Test::bind2nd<Op_plus, int>(Op_plus(), 2))(val) << endl;
	//f(x, y) = x * y, g1(x) = x + 2, g2(x) = 6 - x ==>f(g1(x), g2(x)) = (x + 2) * (6 - x)
	typedef Test::minus<int>		Op_minus;
	cout << Test::compose2<Op_mult, Test::binder2nd<Op_plus>, Test::binder1st<Op_minus> >(Op_mult(),
		Test::bind2nd<Op_plus, int>(Op_plus(), 2), Test::bind1st<Op_minus, int>(Op_minus(), 6))(val) << endl;

	TestClass tc1;
	Test::mem_fun(&TestClass::testFun)(&tc1);
	Test::mem_fun(&TestClass::testFunC)(&tc1);
	system("pause");
	return 1;
}

测试结果一并附上吧,我没有在gcc下测试,仅仅是在vs2010中运行了。

代码和例子都很简单,只作为了解STL的一个部分的学习记录。

时间: 2024-10-13 07:04:14

STL学习之路之仿函数的相关文章

我的STL学习之路

说起STL(标准模板库),相信了解C++的都不会陌生吧^_^.LZ是从大三开始学习C++(ps:不是科班出身),并慢慢接触使用STL的,在学校中使用STL比较多的情况是写数据结构代码,使用STL实现数据结构代码(我的数据结构源码),使我们专注于考虑算法思想,不拘泥于底层代码实现. 这里LZ不讲STL的具体知识,只讨论关于STL的学习和使用问题!结合LZ的学习过程,LZ觉得C++的学习(当然,这其中包括的STL)大致路线如下: 学习C++基本语法 掌握类.继承.多态等概念 理解面对对象和泛型编程思

C++ STL 学习 :for_each与仿函数(functor)

简单来将,仿函数(functor)就是一个重载了"()"运算符的struct或class,利用对象支持operator()的特性,来达到模拟函数调用效果的技术. 我们平时对一个集合类遍历的时候,例如vector,是这样做的: for(vector<int>::const_iterator iter = ivec.begin(); iter != ivec.end(); ++iter) { //do your whatever you want here } 例如下面的代码:

我的算法学习之路

关于 严格来说,本文题目应该是我的数据结构和算法学习之路,但这个写法实在太绕口--况且CS中的算法往往暗指数据结构和算法(例如算法导论指的实际上是数据结构和算法导论),所以我认为本文题目是合理的. 这篇文章讲了什么? 我这些年学习数据结构和算法的总结. 一些不错的算法书籍和教程. 算法的重要性. 初学 第一次接触数据结构是在大二下学期的数据结构课程.然而这门课程并没有让我入门--当时自己正忙于倒卖各种MP3和耳机,对于这些课程根本就不屑一顾--反正最后考试划个重点也能过,于是这门整个计算机专业本

Peng Gong:我的算法学习之路

原文出处: Lucida (@peng_gong) 关于 严格来说,本文题目应该是我的数据结构和算法学习之路,但这个写法实在太绕口--况且CS中的算法往往暗指数据结构和算法(例如算法导论指的实际上是数据结构和算法导论),所以我认为本文题目是合理的. 这篇文章讲了什么? 我这些年学习数据结构和算法的总结. 一些不错的算法书籍和教程. 算法的重要性. 初学 第一次接触数据结构是在大二下学期的数据结构课程.然而这门课程并没有让我入门--当时自己正忙于倒卖各种MP3和耳机,对于这些课程根本就不屑一顾--

转----我的算法学习之路

我的算法学习之路 关于 严格来说,本文题目应该是我的数据结构和算法学习之路,但这个写法实在太绕口——况且CS中的算法往往暗指数据结构和算法(例如算法导论指的实际上是数据结构和算法导论),所以我认为本文题目是合理的. 原文链接:http://zh.lucida.me/blog/on-learning-algorithms/ 原文作者:Lucida 这篇文章讲了什么? 我这些年学习数据结构和算法的总结. 一些不错的算法书籍和教程. 算法的重要性. 初学 第一次接触数据结构是在大二下学期的数据结构课程

C++学习之路,漫长而遥远

一.C/C++语言 如果你的基础很差, 建议不要一开始就学C++语言,从C开始学起,对程序有个初步的认识,循序渐进.C语言的书嘛,先买一本 300 页以内的,把书中的每一个例子都通过键盘敲打进去到 Visual studio里面去,然后单步执行,逐行调试去看各个变量的值.或者自行添加一些printf语句去输出变量的值.这样当你看完一本书后, 你就有编写小程序的感觉了. 记住,千万不要偷懒,不敲进去,自以为聪明, 能看懂, 或者直接从光盘复制.偷懒的代价是会花费更多的时间学习,最后还没有学会,给自

我的QT5学习之路(一)——浅谈QT的安装和配置

一.前言 说到Qt,不能不说到C++,这门伟大的语言.因为其面向对象的编程思想和陡峭的学习曲线,一开始学习起来很是吃力.Qt从QT4开始基本封装了很多C++的工具库和界面库,而且支持跨平台,这是它最大的优势.相比于古老的MFC和使用C#的WPF来说,我更喜欢Qt来进行C++的界面设计,这也是我从新开始拾起Qt学习之路的原因. 说完了感受和学习的原因,就开始介绍Qt5了.我这里只做简单的介绍,重要的还是在学习过程中体会Qt的编程逻辑和设计思想. Qt,坦白来说,并不只是一个界面库,他是C++编程思

Qt 学习之路 2 --- 读书笔记

一.文章来由 来自豆子老师非常好的一本Qt教程,但是只有网络版,所以用这个做笔记了,不动笔墨不读书嘛~~ 二.读书笔记 1.Qt 学习之路 2(2):Qt 简介 1.1 关于 Qt 的一站式解决 Qt 是一个著名的 C++ 应用程序框架.但并不只是一个 GUI 库,因为 Qt 十分庞大,并不仅仅是 GUI 组件.使用 Qt,在一定程度上你获得的是一个"一站式"的解决方案:不再需要研究 STL,不再需要 C++ 的,不再需要到处去找解析 XML.连接数据库.访问网络的各种第三方库,因为

一位Google程序员的算法学习之路(转)

关于 严格来说,本文题目应该是我的数据结构和算法学习之路,但这个写法实在太绕口——况且CS中的算法往往暗指数据结构和算法(例如算法导论指的实际上是数据结构和算法导论),所以我认为本文题目是合理的. 这篇文章讲了什么? 我这些年学习数据结构和算法的总结. 一些不错的算法书籍和教程. 算法的重要性. 初学 第一次接触数据结构是在大二下学期的数据结构课程.然而这门课程并没有让我入门——当时自己正忙于倒卖各种MP3和耳机,对于这些课程根本就不屑一顾——反正最后考试划个重点也能过,于是这门整个计算机专业本