STL源码--函数对象

STL学习之路之仿函数 C++ STL functional 阅读详情

函数对象对于stl这个以迭代器为基石的库的重要性不言而喻


//函数对象的重要性不言而喻,尤其是对于stl这个以迭代器为基石的库

//定义一个函数对象,实现两数相加
template<class _Tp>
struct plus
{
	_Tp operator()(const _Tp& __x,const _Tp& __y){return __x+__y;}
};
//我们可以使用plus(x,y);
//假设我们需要的是-(x+y),怎么算?
template<class _Tp>
struct negative_plus
{
	_Tp operator()(const _Tp& __x,const _Tp& __y){return -(__x+__y);}
};
//对于这种非常简单的函数对象,我们可以重写,如果非常复杂的怎么办?这里就引出了配接器的概念,我们定义一个配接器
//它可以返回plus(x,y)的负数,当然它的参数就是plus函数对象:
template<class _Func>
struct negate
{
	//参数是什么?返回值是什么类型?怎么由plus对象得到_Tp?
};
//上述的问题是配接器的普遍问题,怎么解决?


//诚然自己写的函数对象也可以用,但是,却不能与已定义好的函数对象很好的兼容,尤其是与配接器的兼容性。如果要写出
//兼容性好的,并且能使用配接器的函数对象,就要遵循规范:函数对象继承于下面的两个类!
//一元函数对象的基类:参数类型和返回结果类型
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){return __x+__y;}
};

//配接器:
template<class _Function>
struct negate_binary:public binary_function<typename _Function::first_argument_type,
	  typename _Function::second_argument_type,typename _Function::result_type>
{
	explicit negate_binary(const _Function& __f):m_f(__f){}
	result_type operator()(const first_argument_type& __x,const second_argument_type& __y)const
	{return -(m_f(__x,__y));}
protected:
	_Function m_f;
};
//这样就可以实现各种类型的配接器了

//配接器类型二:将二元的函数对象转换为一元的函数对象,采用的方式是固定其中的一个参数,下面举例固定第一个参数
template<class _Function>
struct _bind1st:public unary_function<typename _Function::second_arugument_type,typename _Function::result_type>
{
protected:
	_Function m_function;
	typename _Function::first_arugument_type m_first;
public:
	 bind1st(const _Function& __f,const typename _Function::first_arugument_type& __x)
		:m_function(__f),m_first(__x){}
	result_type operator()(const argument_type& __y)const {return m_function(m_first,__y);}
};
//配接器类型三:组合函数对象,这是由简单的函数对象产生复杂函数对象的方法
//op1(op2(x)),op1(op2(x),op3(x)),op1(op2(x,y)),op1(op2(x),op3(y))四种,下面是第一种
//一元函数对象的组合:op1(op2(x))参数是op2的参数,结果是op1的结果
template<class _Function1,class _Function2>
struct compose1:public unary_function<typename _Function2::argument_type,typename _Function1::result_type>
{
protected:
	_Function1 m_function1;
	_Function2 m_function2;
public:
	compose(const _Function1& __f1,const _Function2& __f2)
		:m_function1(__f1),m_function2(__f2){}
	result_type operator()(const argument_type& __x) const{return m_function1(m_function2(__x));}
};

//至此,函数对象配接器的类型就结束了,但是stl为每个配接器都提供了一个函数使用接口,这个不知道为什么这样做。。
//例如:bind1st的函数接口:
template<class _Function>
inline _bind1st<_Function> bind1st(const _Function& __f,const typename _Function::first_argument_type& __x)
{return _bind1st<_Function>(__f,__x);}

//对于函数对象,有几个问题:
//1.函数指针,按理来说,对于用户,函数指针和函数对象的一样的,但是,stl中实现了很多将函数指针转化为函数对象的工具
//2,类成员函数的函数对象,这里是的使用方式是op(class),分四种情况:
//类成员函数有无参数?通过指针还是引用来调用?是否返回值?const还是non-const?
//举一例:
template <class _Ret, class _Tp>
class mem_fun_t : public unary_function<_Tp*,_Ret> {
public:
  explicit mem_fun_t(_Ret (_Tp::*__pf)()) : _M_f(__pf) {}
  _Ret operator()(_Tp* __p) const { return (__p->*_M_f)(); }
private:
  _Ret (_Tp::*_M_f)();
};

template <class _Ret, class _Tp>
class const_mem_fun_t : public unary_function<const _Tp*,_Ret> {
public:
  explicit const_mem_fun_t(_Ret (_Tp::*__pf)() const) : _M_f(__pf) {}
  _Ret operator()(const _Tp* __p) const { return (__p->*_M_f)(); }
private:
  _Ret (_Tp::*_M_f)() const;
};


template <class _Ret, class _Tp>
class mem_fun_ref_t : public unary_function<_Tp,_Ret> {
public:
  explicit mem_fun_ref_t(_Ret (_Tp::*__pf)()) : _M_f(__pf) {}
  _Ret operator()(_Tp& __r) const { return (__r.*_M_f)(); }
private:
  _Ret (_Tp::*_M_f)();
};

template <class _Ret, class _Tp>
class const_mem_fun_ref_t : public unary_function<_Tp,_Ret> {
public:
  explicit const_mem_fun_ref_t(_Ret (_Tp::*__pf)() const) : _M_f(__pf) {}
  _Ret operator()(const _Tp& __r) const { return (__r.*_M_f)(); }
private:
  _Ret (_Tp::*_M_f)() const;
};
//包装函数
template <class _Ret, class _Tp>
inline mem_fun_t<_Ret,_Tp> mem_fun(_Ret (_Tp::*__f)())
  { return mem_fun_t<_Ret,_Tp>(__f); }


每天精通一个C++核心技巧:STL函数对象实战教程(含完整源码 一个最简单的函数对象定义如下:上述Adder类通过重载operator()实现了一个加法操作。我们可以像调用函数一样使用其实例:Adder add;// 调用 add.operator()(3, 5)这看似只是一个语法糖,但背后蕴含的是强大的泛型机制。STL 算法如std::sort接受任何形式的“可调用对象”作为参数,而函数对象正是其中最基础且可控性最强的一种。进一步地,函数对象可以携带状态。 阅读详情

相关推荐

STL源码学习----函数对象

  STL中很多算法都要对迭代器范围内的元素做特定操作,这些操作是需要用户显示传递给迭代器,如何才能有效地传递这些操作呢?STL为我们提供了函数对象来解决这个问题。本文先简要介绍函数对象的概念,然后配合源代码介绍STL为我们提供的几种函数对象,最后介绍强大的函数对象适配器。   0 函数对象   标准库的很多算法需要一些指向序列的迭代器对该序列作操作,算法的参数除了迭代器以外还会需要用户指定...

weixin_34319111的博客 192

C++】运算符重载关于const的分析(超详细)

C++运算符重载重载运算符“+”第1个const第2个const第3个const重载运算符“-”重载运算符“-”(与上面的含义不同)重载运算符 “+=” 与 “-=”重载运算符 “==” 与 “!=”重载运算符 “++” 与 “--”重载 “<<" 与 “>>”完整源代码 C++里面的运算符重载细节特别多,这里用一个 Point 类来演示一下C++的运算符重载。(需要理解友...

萌宅鹿的技术小屋 1万+

STL的hasp_map学习笔记

 1.HASH函数的声明问题template class _Key, class _Tp, class _HashFcn = hash,class _EqualKey = equal_to,class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >class hash_map{ ...}也就是说,在上例中,有以下等同关系:...hash

kikikind的专栏 2714

C++ STL源码学习(仿函数篇)

QQ:2496088963          欢迎联系、交流

alpaca.blog 947

STL源码剖析——STL函数对象

本文介绍了STL中的函数对象,针对函数对象源码进行了剖析,在这里剖析了算术类函数对象、关系运算类函数对象和逻辑运算类函数对象

关注校招求职,微信号:job_campus 1981

STL算法】for_each源码刨析及函数对象本质刨析

通过追踪源码、刨析源码来学习STL中的容器、迭代器和算法。

仅以此博客记录日常学习工作中所思所得,水平有限,难登大雅,万望海涵。 2332

STL源码剖析笔记——仿函数函数对象

STL源码剖析笔记——仿函数函数对象

weixin_48956191的博客 1155

STL终极奥义❀解耦合思想的实现❀】函数对象、谓词与函数适配器——从for_each、transform、count_if、sort算法源码的角度分析

STL算法为我们提供了一些统一的算法模型,在这些算法模型中,只提供了一个统一的壳子,具体实现什么样的功能由我们通过函数对象或回调函数来实现。这是一种非常重要的思想,统一性思想,而统一的实现就是解耦合,如果不理解这个思想,那么学习STL就像背英语单词,将变得毫无意义。下面将通过for_each、transform、count_if、sort四个算法实例来一步步深入理解这种思想。

仅以此博客记录日常学习工作中所思所得,水平有限,难登大雅,万望海涵。 1341

重点难点,STL仿函数(函数对象)源码剖析

待续

董哥的黑板报 7965

STL源码剖析—仿函数函数对象

第七章 仿函数函数对象) 7.1 仿函数概观 什么是仿函数函数对象)? 就实现观点而言,仿函数实际上是一个“行为类似函数”的对象,为了能够“行为类似函数”,其类别定义中必须自定义(重载、重写)operator()运算符。 简单点说,仿函数就是一个对象,只不过是重载了operator()运算符,并且可以保存状态。 为什么要使用仿函数而不使用函数指针呢? 原因在于函数指针不能满足STL...

Zsj的博客 448

STL源码剖析 7、仿函数函数对象

仿函数概述 概念:又名函数对象,是一种具有函数特质的对象函数对象),可以像函数一样调用(仿函数) 编写:是一个class,重载了operator() 使用:有两种,用对象调用和临时对象调用 int main() { //用对象调用 greater<int>ig; ig(4, 6); //临时对象调用 greater<int>()(4, 6); } STL仿函数STL算法关系: 可配接性 ...

ziggy7的博客 182

仿函数(函数对象)——STL源码剖析笔记

仿函数是早起命名,C++标准规格定案后采用新名称函数对象,意即具体函数性质的对象STL的各种算法里经常用到仿函数,前几篇文章有提到,比如sort的第一个版本以operator

weixin_42853463的博客 189

STL源码剖析——仿函数函数对象

1 仿函数也称为函数对象,是一种具有函数特质的对象。调用者可以像函数一样的使用这些对象,例如在很多STL算法中,都可以看到,我们可以将一个方法作为模板内的参数传入到算法实现中,例如sort的时候我们可以根据我们传入的自定义的compare函数来进行比较排序。解决办法是使用函数指针,或者是将这个“操作”设计为一个所谓的仿函数,再用这个仿函数生成一个对象,并用这个对象作为算法的一个参数。

Smile&搁浅 1014

STL源码分析--仿函数 & 模板的模板参数 & 临时对象

STL源码分析—使用的一些特殊语法 关于泛型编程中用到的一些特殊语法,这些语法也适用于平常的模板编程 1、  类模板中使用静态成员变量 Static成员变量在类模板中并不是很特殊,同时这个变量不属于对象,属于实例化以后的这个类类型。每一个实例化对应一个static变量 2、  类模板中可以再有模板成员 3、  模板参数可以根据前一个模板参数而设定默认值 4、  类模板可以拥有非类型的模

鱼思故渊的专栏 1381

STL源码剖析 第七章 仿函数(函数对象)

函数对象:具有函数性质的对象 使得用户像使用函数一样使用它 一般函数提供两个版本,第一个版本使用operator < ;第二版本需要用户 指定某种操作 第二版本就是设计一个函数,将函数指针作为算法的一个参数;或者将函数操作设计成为一个仿函数,就语言层面是一个class,再以该仿函数产生一个对象,并以此对象作为算法的一个参数 函数指针就可以完成任务,为啥需要引入 函数对象呢?因为函数指针无法满足STL对抽象性的要求,也无法适配STL的其余组件(适配器)搭配,产生灵活的变化 仿函数就是行为类似函

CHYabc123456hh的博客 591

STL源码剖析》笔记-仿函数(函数对象)

上一篇:《STL源码剖析》笔记-算法

WizardtoH 468
上一篇: STL源码-traits的使用
下一篇: (三):初步寻找区分病人的最佳高频/低频阈值
wangyanphp
博客等级 码龄14年 90粉丝 51原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值