今天看到STL(标准模板库)里的一个函数,也就是一个约束器--bind2nd(x, y),这个是一个模板函数,stl里面不止这么一个约束器,比如bind1st(x, y),相对而言bind2nd复杂一点,就谈一下这个函数这里。
在看这篇文章之前,建议先看看相关的资料,要求了解类模板及函数模板,容器,拟函数(仿函数或者称为函数对象),如果不了解基本的c++知识,那就不要看了,我用msvc讲解,sgi stl的stl其实差不多。
先看两个定义:
图1:
template<class_Arg,class_Result>
structunary_function{
typedef_Argargument_type;
typedef_Resultresult_type;
};
template<class_Arg1,class_Arg2,class_Result>
structbinary_function{
typedef_Arg1first_argument_type;
typedef_Arg2second_argument_type;
typedef_Resultresult_type;
};
这里unary_function和binary_function是我们后面要讲到的,而且stl里面的约束器,适配器等很多东西都用到这定义。
接着是约束器的定义,在functional头文件里面, 如下:
图2:
//TEMPLATEFUNCTIONbind2nd
template<class_Fn2,
class_Ty>inline
binder2nd<_Fn2>bind2nd(const_Fn2&_Func,const_Ty&_Right)
...{//returnabinder2ndfunctoradapter
typename_Fn2::second_argument_type_Val(_Right);
return(std::binder2nd<_Fn2>(_Func,_Val));
}
std::binder2nd<_Fn2>是一个类定义,也在同一个头文件下面,定义如下:
图3:
template<class_Fn2>
classbinder2nd
:publicunary_function<typename_Fn2::first_argument_type,
typename_Fn2::result_type>
...{//functoradapter_Func(left,stored)
public:
typedefunary_function<typename_Fn2::first_argument_type,
typename_Fn2::result_type>_Base;
typedeftypename_Base::argument_typeargument_type;
typedeftypename_Base::result_typeresult_type;
binder2nd(const_Fn2&_Func,
consttypename_Fn2::second_argument_type&_Right)
:op(_Func),value(_Right)
...{//constructfromfunctorandrightoperand
}
result_typeoperator()(constargument_type&_Left)const
...{//applyfunctortooperands
return(op(_Left,value));
}
result_typeoperator()(argument_type&_Left)const
...{//applyfunctortooperands
return(op(_Left,value));
}
protected:
_Fn2op;//thefunctortoapply
typename_Fn2::second_argument_typevalue;//therightoperand
};
说到这里
template<class _Fn2>
class binder2nd
: public unary_function<typename _Fn2::first_argument_type,
typename _Fn2::result_type> 就要注意了,binder2nd类由unary_function类派生, 用到了_Fn2,而_Fn2一般的就是用到前面的binary_function类定义。
说到这里,都还没有接触到约束器bind2nd(x,y),那就再等一会,再看看拟函数的一个使用,实例一:
图4:
structclub...{
stringss;
club(stringa="ohyeah"):ss(a)...{}
~club()...{}
booloperator()(clubc)...{
returnc.ss==ss;
}
friendostream&operator<<(ostream&os,club&c);
};
ostream&operator<<(ostream&os,club&c)...{
returnos<<c.ss;
}
intmain()...{
list<club>a;
list<club>b[2];
a.push_back(st("a11"));
a.push_back(st("a22"));
a.push_back(st("a33"));
a.push_back(st("a44"));
list<club>::iteratorp=find_if(a.begin(),a.end(),club());
//p++;
for(;p!=a.end();p++)...{
cout<<*p<<endl;
}
}
看看find_if函数定义(头文件algorithm中):
图5:
template<class_InIt,
class_Pr>inline
_InIt_Find_if(_InIt_First,_InIt_Last,_Pr_Pred)
...{//findfirstsatisfying_Pred
_DEBUG_RANGE(_First,_Last);
_DEBUG_POINTER(_Pred);
for(;_First!=_Last;++_First)
if(_Pred(*_First))
break;
return(_First);
}
template<class_InIt,
class_Pr>inline
_InItfind_if(_InIt_First,_InIt_Last,_Pr_Pred)
...{//findfirstsatisfying_Pred
_ASSIGN_FROM_BASE(_First,
_Find_if(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Pred));
return(_First);
}
看看这一部分就晓得了:
for(;_First!=_Last;++_First)
if(_Pred(*_First))
break;
return(_First);
find_if的第三个参数被用作,拟函数调用
上面的代码我想研究过stl的都明白是什么意思,我定义了一个club类,再find_if函数里面的第三个参数就是一个类对象,临时的,当iterator p移动到a.begin(), a.end()之间时,find_if函数就会调用club类里面定义的operator ()重载,调用拟函数,而且给拟函数传入(*p),这里是一个club对象,这里要记住一点,就是拟函数的参数需要传值,由调用函数传值!
在看了一个简短的拟函数的使用后,我们进入约束器的使用,实例二:
图6:
#include<iostream>
#include<list>
#include<algorithm>
#include<string>
#include<functional>
usingnamespacestd;
intmain()...{
list<int>a;
a.push_back(11);
a.push_back(22);
list<int>::iteratorp=find_if(a.begin(),a.end(),bind2nd(less<int>(),7));
}
代码中的bind2nd(less<int>(), 7)在图2处过后就变成了
图7
list<int>::iteratorp=find_if(a.begin(),a.end(),bind2nd(less<int>(),7))
||
||
list<int>::iteratorp=find_if(a.begin(),a.end(),binder2nd<**>(less<int>(),7))
这里binder2nd<**>(less<int>,7)其实就是一个binder2nd类临时对象,打星星符号的地方是表示binder2nd类使用的模板类型,这个要通过后面的模板类型推断。
在图3中可以看到binder2nd的构造函数:
binder2nd(const_Fn2&_Func,
consttypename_Fn2::second_argument_type&_Right)
:op(_Func),value(_Right)
...{//constructfromfunctorandrightoperand
}
less<int>()传值给op,一个_Fn2类型的变量,7传值给value,一个int型值。
看less类定义,来推断_Fn2的具体类型。
图8:
template<class_Tp>
structless:publicbinary_function<_Tp,_Tp,bool>
...{
booloperator()(const_Tp&__x,const_Tp&__y)const
...{
return__x<__y;
}
}
由此推断,_Tp是int型
那么图7里面的binder2nd< ** >(less<int>(), 7)可以推断为
binder2nd<_Fn2<int, int, bool> > >(less<int>(), 7), 应该要知道,这个就是一个临时对象,这个临时对象里面的op = less<int> (), value = 7,那么它就要调用binder2nd里面的拟函数:
result_typeoperator()(argument_type&_Left)const
.........{//applyfunctortooperands
return(op(_Left,value));
}
_Left有外界传入值,也就是开始的find_if(……)函数传入。
那么这个函数返回之后变成了:
find_if(a.begin(),a.end(),op(_Left,7))//op用less<int>()对象替换之后
||
find_if(a.begin(),a.end(),less<int>()(_Left,7))
less<int>()(_Left,7)又是一个拟函数,又要调用相应的operator()操作符。
这个操作符号在头文件<functional>里面定义,图8里面有。
booloperator()(const_Tp&__x,const_Tp&__y)const
...{
return__x<__y;
}
设p为a.begin(),a.end(),之间一个指针,那么find_if(a.begin(),a.end(),less<int>()(_Left,7))
在此演变为:
find_if(a.begin(),a.end(),less<int>()(*p,7))
再次演变为:
find_if(a.begin(),a.end(),less<int>::operator()(*p,7)
到此就分解到最原始的状态了,也就很简单了,就是一个简简单单的拟函数的问题了。
水平有限,多多指教!
分享到:
相关推荐
STL介绍 3 1、STL简介 3 2、算法 3 3、容器 3 4、迭代器 4 5、使用注意 4 一、stack 堆栈 5 成员函数: 5 实例程序: 5 二、queue 队列 6 成员函数: 6 实例程序: 6 三、Priority Queues 优先队列 7 成员函数: 7 ...
.stl有两种格式:二进制和ASCII,请注意区分。本资源为c# 解析二进制.stl模型,分享一个demo,希望各位网友下载能用得上。
STL源码解析中文版
解析STL文件并在opengl中显出出来模型,环境是QT。
STL = Standard Template Library,首先他是一个 Library,也就是一个函数 库,就像大家以前用的函数sin/random等来自数学库,printf/fopen/fread/fwrite 等来自 io 库, strcpy/strcmp/strcat 等来自己字符串库。 每...
STL实例源码,有blog:http://blog.csdn.net/ouyangshima/article/details/8462569
西门子plc案例,stl学习
STL forward pause reverse.zip三菱PLC编程案例源码资料编程控制器应用通讯通信例子程序实例STL forward pause reverse.zip三菱PLC编程案例源码资料编程控制器应用通讯通信例子程序实例STL forward pause reverse....
C++ STL实用例子大全,里面包含了很多的很有用的STL模版的例子
STL Tutorial and Reference Guide, 2nd Edition
一些C++STL 用法的实例。如vector list.
C++ STL迭代器机制剖析 -- C++经典书籍哦
本实例中定义了STL文件中的基本数据结构,采用普通文件读取和内存映射文件读取两种方式,并对二者效率进行对比
这个实例介绍了每种STL容器的使用,包括Map/Vector/List/Queque/Set/MultiMap和各种STL算法的使用。供初学者参考使用
STL入门 STL入门 STL入门 STL入门 STL入门 STL入门
STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,S,STL源码解析,简体中文扫描版,带目录TL源码解析,简体中文扫描版,带目录,STL源码解析,...
STL 入门学习 源代码, 简单明了 几个简单的实例.来自教程 Initialization Demo To demonstrate initialization of STL vectors
关于STL源码的详细解析,看过收获很大.特来与大家共享!
STL v2.03 解析工程文件,供学习STL源码使用。里面是一个vs2013的工程文件。
8.4.2 对参数进行系结(绑定):bind1st, bind2nd 451 8.4.3 用于函数合成:compose1, compose2(未纳入标准) 453 8.4.4 用于函数指针:ptr_fun 454 8.4.5 用于成员函数指针:mem_fun, mem_fun_ref 456 附录A ...