stl中容易出错的一个地方
哎...一个不起眼的地方折磨了我好长时间。。。
先看一个可以正常编译的程序
我们再来看另外一个同样的例子,只不过这次先定义一个真正的函数lessthan(),然后再通过ptr_fun将其变成一个函数对象,那么理所当然的ptr_fun(lessthan)就应该等价于LessThan(),事实上下面这段代码的确也可以编译通过
先来到ptr_fun,看下它的代码:
恩,继续,看pointer_to_binary_function的定义
第三个程序就是在第二个的基础上加了个not2,看来是not2这个函数适配器出问题了。
看not2的定义:
哈哈,看出原因了吗? 就在运算符()重载上除了点问题,它的参数是const typename _Fn2::first_argument_type& _Left,而我们的ptr_fun(lessthan)中的first_argument_type为const int &,那么相当与_left被定义的类型为const int & &,而在c++中没有引用的引用这种类型,所以编译器就报错啦。。
把我们的程序稍微改一下就可以了(把lessthan的定义中const int&改为int即可)
先看一个可以正常编译的程序
#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
class LessThan : public binary_function<int,int,bool> {
public:
bool operator()(const int& a,const int& b) const{
return a<b;
}
};
int main(){
int a[]={6,5,8,9,10};
vector<int> v(a,a+5);
vector<int>::iterator i=adjacent_find(v.begin(),v.end(),not2(LessThan()));
cout<<*i<<endl;
cout<<*++i<<endl;
}
可以看到LessThan类是一个函数对象,由于要用到not2这个函数适配器,因此必须要继承自类binary_function这个模板类, binary_function也是非常的简单,就是定义了函数适配器所需要的一些typedef,我们看看标准库functional中的代码:#include <functional>
#include <algorithm>
using namespace std;
class LessThan : public binary_function<int,int,bool> {
public:
bool operator()(const int& a,const int& b) const{
return a<b;
}
};
int main(){
int a[]={6,5,8,9,10};
vector<int> v(a,a+5);
vector<int>::iterator i=adjacent_find(v.begin(),v.end(),not2(LessThan()));
cout<<*i<<endl;
cout<<*++i<<endl;
}
// TEMPLATE STRUCT binary_function
template<class _Arg1,class _Arg2,class _Result>
struct binary_function
{ // base class for binary functions
typedef _Arg1 first_argument_type;
typedef _Arg2 second_argument_type;
typedef _Result result_type;
};
可以看到,这个类就是把函数的2个参数和返回值类型typedef到了类里面。template<class _Arg1,class _Arg2,class _Result>
struct binary_function
{ // base class for binary functions
typedef _Arg1 first_argument_type;
typedef _Arg2 second_argument_type;
typedef _Result result_type;
};
我们再来看另外一个同样的例子,只不过这次先定义一个真正的函数lessthan(),然后再通过ptr_fun将其变成一个函数对象,那么理所当然的ptr_fun(lessthan)就应该等价于LessThan(),事实上下面这段代码的确也可以编译通过
#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
bool lessthan(const int& a,const int& b){
return a<b;
}
int main(){
int a[]={6,5,8,9,10};
vector<int> v(a,a+5);
vector<int>::iterator i=adjacent_find(v.begin(),v.end(),ptr_fun(lessthan));
cout<<*i<<endl;
cout<<*++i<<endl;
}
但是我们现在是要对lessthan的结果进行取反,那么就应该是not2(ptr_fun(lessthan))喽。嗯,试一下。#include <functional>
#include <algorithm>
using namespace std;
bool lessthan(const int& a,const int& b){
return a<b;
}
int main(){
int a[]={6,5,8,9,10};
vector<int> v(a,a+5);
vector<int>::iterator i=adjacent_find(v.begin(),v.end(),ptr_fun(lessthan));
cout<<*i<<endl;
cout<<*++i<<endl;
}
#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
bool lessthan(const int& a,const int& b){
return a<b;
}
int main(){
int a[]={6,5,8,9,10};
vector<int> v(a,a+5);
vector<int>::iterator i=adjacent_find(v.begin(),v.end(),not2(ptr_fun(lessthan)));
cout<<*i<<endl;
cout<<*++i<<endl;
}
天啊!!!编译不通过。。。到底是什么原因呢。。。 我们到头文件functional中去找!!#include <functional>
#include <algorithm>
using namespace std;
bool lessthan(const int& a,const int& b){
return a<b;
}
int main(){
int a[]={6,5,8,9,10};
vector<int> v(a,a+5);
vector<int>::iterator i=adjacent_find(v.begin(),v.end(),not2(ptr_fun(lessthan)));
cout<<*i<<endl;
cout<<*++i<<endl;
}
先来到ptr_fun,看下它的代码:
template<class _Arg1,class _Arg2,class _Result>
inline pointer_to_binary_function<_Arg1, _Arg2, _Result, _Result(__cdecl *)(_Arg1, _Arg2)>
ptr_fun(_Result (__cdecl *_Left)(_Arg1, _Arg2))
{ // return pointer_to_binary_function functor adapter
return (std::pointer_to_binary_function<_Arg1, _Arg2, _Result, _Result (__cdecl *)(_Arg1, _Arg2)>(_Left));
}
可以看到ptr_fun简单调用了pointer_to_binary_function的构造函数(参数_Left),在这个例子中我们调用 ptr_fun(lessthan),所以_Arg1,_Arg2为const int&,_Result为bool,_Left为lessthaninline pointer_to_binary_function<_Arg1, _Arg2, _Result, _Result(__cdecl *)(_Arg1, _Arg2)>
ptr_fun(_Result (__cdecl *_Left)(_Arg1, _Arg2))
{ // return pointer_to_binary_function functor adapter
return (std::pointer_to_binary_function<_Arg1, _Arg2, _Result, _Result (__cdecl *)(_Arg1, _Arg2)>(_Left));
}
恩,继续,看pointer_to_binary_function的定义
// TEMPLATE CLASS pointer_to_binary_function
template<class _Arg1,
class _Arg2,
class _Result,
class _Fn = _Result (*)(_Arg1, _Arg2)>
class pointer_to_binary_function
: public binary_function<_Arg1, _Arg2, _Result>
{ // functor adapter (*pfunc)(left, right)
public:
explicit pointer_to_binary_function(_Fn _Left)
: _Pfun(_Left)
{ // construct from pointer
}
_Result operator()(_Arg1 _Left, _Arg2 _Right) const
{ // call function with operands
return (_Pfun(_Left, _Right));
}
protected:
_Fn _Pfun; // the function pointer
};
ok 了,这个类就是个函数对象,继承自binary_function,保存了一些typedef,即first_argument_type, second_argument_type都为const int&,result_argument_type为bool,一些正常,所以第2个程序可以编译通过。template<class _Arg1,
class _Arg2,
class _Result,
class _Fn = _Result (*)(_Arg1, _Arg2)>
class pointer_to_binary_function
: public binary_function<_Arg1, _Arg2, _Result>
{ // functor adapter (*pfunc)(left, right)
public:
explicit pointer_to_binary_function(_Fn _Left)
: _Pfun(_Left)
{ // construct from pointer
}
_Result operator()(_Arg1 _Left, _Arg2 _Right) const
{ // call function with operands
return (_Pfun(_Left, _Right));
}
protected:
_Fn _Pfun; // the function pointer
};
第三个程序就是在第二个的基础上加了个not2,看来是not2这个函数适配器出问题了。
看not2的定义:
// TEMPLATE FUNCTION not2
template<class _Fn2> inline
binary_negate<_Fn2> not2(const _Fn2& _Func)
{ // return a binary_negate functor adapter
return (std::binary_negate<_Fn2>(_Func));
}
恩,返回binary_negate类的实例,那么继续去找binary_negate的代码:template<class _Fn2> inline
binary_negate<_Fn2> not2(const _Fn2& _Func)
{ // return a binary_negate functor adapter
return (std::binary_negate<_Fn2>(_Func));
}
// TEMPLATE CLASS binary_negate
template<class _Fn2>
class binary_negate
: public binary_function<typename _Fn2::first_argument_type,
typename _Fn2::second_argument_type, bool>
{ // functor adapter !_Func(left, right)
public:
explicit binary_negate(const _Fn2& _Func)
: _Functor(_Func)
{ // construct from functor
}
bool operator()(const typename _Fn2::first_argument_type& _Left,
const typename _Fn2::second_argument_type& _Right) const
{ // apply functor to operands
return (!_Functor(_Left, _Right));
}
protected:
_Fn2 _Functor; // the functor to apply
};
template<class _Fn2>
class binary_negate
: public binary_function<typename _Fn2::first_argument_type,
typename _Fn2::second_argument_type, bool>
{ // functor adapter !_Func(left, right)
public:
explicit binary_negate(const _Fn2& _Func)
: _Functor(_Func)
{ // construct from functor
}
bool operator()(const typename _Fn2::first_argument_type& _Left,
const typename _Fn2::second_argument_type& _Right) const
{ // apply functor to operands
return (!_Functor(_Left, _Right));
}
protected:
_Fn2 _Functor; // the functor to apply
};
哈哈,看出原因了吗? 就在运算符()重载上除了点问题,它的参数是const typename _Fn2::first_argument_type& _Left,而我们的ptr_fun(lessthan)中的first_argument_type为const int &,那么相当与_left被定义的类型为const int & &,而在c++中没有引用的引用这种类型,所以编译器就报错啦。。
把我们的程序稍微改一下就可以了(把lessthan的定义中const int&改为int即可)