分享
 
 
 

boost::mem_fn和std::mem_fun在MSVC6.0上的表现

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

boost::mem_fn和std::mem_fun在MSVC6.0上的表现

Article last modified on 2002-8-7

----------------------------------------------------------------

The information in this article applies to:

- C/C++

- Microsoft Visual C++ 6.0(SP5)

----------------------------------------------------------------

boost::mem_fn的简单介绍:

boost::mem_fn是std::mem_fun系列的一个扩展。它的文档链接为:

http://www.boost.org/libs/bind/mem_fn.html

mem_fn最为人所熟知的作用是,将一个成员函数作用在一个容器上,就像这样std::for_each(v.begin(), v.end(), boost::mem_fn(&Shape::draw))就可以让容器vector中的每一个元素都执行一遍draw方法。

第二个用法是,它可以帮助把一个函数指针模拟得像一个函数实体(function object)。比如:

template<class It, class R, class T> void for_each(

It first,

It last,

R (T::*pmf) () )

{

std::for_each(first, last, boost::mem_fn(pmf) );

}

这样,你就可以这么调用:

for_each(v.begin(), v.end(), &Shape::draw);

但是仅就这些功能,是不足以让开发者舍弃std::mem_fun[_ref]。有什么理由吗?

std::mem_fun[_ref]在MSVC6.0中的编译错误:

第一个问题:std::mem_fun为什么非要成员函数有返回值呢?

试验代码:

class Stuff

{

public:

std::string m_Name;

// This function works under VC6, because it returns a value from the function.

// Note: there is nothing special about returning an int; it could be any data

// type.

int printName()

{

std::cout << m_Name << std::endl;

return 0;

}

// This function would not work under VC6, although Josuttis provides

// a similar example.

// void printName()

// {

// std::cout << m_Name << std::endl;

// }

};

void main()

{

std::vector<Stuff> v;

Stuff s1;

s1.m_Name = "Brandon";

v.push_back(s1);

std::for_each(v.begin(), v.end(), std::mem_fun_ref(&Stuff::printName));

}

编译结果:

只有把printname成员函数声明为有返回值的形式,才能编译通过;

如果声明为void printname(),则会出现下面的编译错误:

f:\program files\microsoft visual studio\vc98\include\functional(263) : error C2562: '()' : 'void' function returning a value

f:\program files\microsoft visual studio\vc98\include\functional(262) : see declaration of '()'

f:\program files\microsoft visual studio\vc98\include\functional(263) : while compiling class-template member function 'void __thiscall std::mem_fun_ref_t<void,class Stuff>::operator ()(class Stuff &) const'

原来是因为MSVC的stl的实现为:

template<class _R, class _Ty>

class mem_fun_ref_t : public unary_function<_Ty, _R>

{

………….

_R operator()(_Ty& _X) const

{return ((_X.*_Ptr)()); }

}

也就是说,operator()非要将成员函数的返回值作为它的返回值,而不管这个成员函数是否有返回值。

暂且不管这种做法是否有道理,它确实会带来不便。

第二个问题:std::mem_fun最多只能支持成员函数有一个参数

试验代码:

class StoreVals

{

int val;

public:

StoreVals ( ) { val = 0; }

int lessconst ( int k , int m) {val -= k + m; return val; }

};

int main(int argc, char* argv[])

{

std::vector <StoreVals* > v2;

std::for_each(

v2.begin( ),

v2.end( ),

std::bind2nd (

std::mem_fun1<int, StoreVals,int>

( &StoreVals::lessconst ),

5

)

);

return 0;

}

std::mem_fun和std::mem_fun_ref支持的成员函数没有参数,而std::mem_fun1和std::mem_fun1_ref支持的成员函数只有一个参数,然后就到此为止了。

如果我们有这样一个函数int lessconst ( int k , int m) {val -= k + m; return val; },就没办法利用std::mem_fun了。

第三个问题:std::mem_fun不支持智能指针

std::mem_fun只能处理raw pointer,而无法处理smart pointer。

第四个问题:std::mem_fun不支持__stdcall的调用约定

试验代码:

class Stuff

{

public:

std::string m_Name;

int __stdcall printName()

{

std::cout << m_Name << std::endl;

return 0;

}

};

void main()

{

std::vector<Stuff> v;

Stuff s1;

s1.m_Name = "Brandon";

v.push_back(s1);

std::for_each(v.begin(), v.end(), std::mem_fun_ref(&Stuff::printName));

}

编译结果:

error C2664: 'mem_fun_ref' : cannot convert parameter 1 from 'int (__stdcall Stuff::*)(void)' to 'int (__thiscall Stuff::*)(void)'

Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

这样,你就无法让Windows API functions,COM interface member functions和std::mem_fun一起使用了。

第五个问题:有std::mem_fun和std::mem_fun_ref,还有 std::mem_fun1、std::mem_fun1_ref等等,使用起来复杂

怎么样?看到std::mem_fun[_ref]的局限性了吧。下面我们来看看boost:;mem_fn[_ref]是怎样改进的。

boost::mem_fn[_ref]的改进:

第一个问题:boost::mem_fn允许成员函数没有返回值

试验代码:

class Stuff

{

public:

std::string m_Name;

void printName()

{

std::cout << m_Name << std::endl;

}

};

void main()

{

std::vector<Stuff> v;

Stuff s1;

s1.m_Name = "Brandon";

v.push_back(s1);

std::for_each(v.begin(), v.end(), boost::mem_fn(&Stuff::printName));

}

编译通过。

第二个问题:boost::mem_fn最多只能支持成员函数有8个参数

试验代码:

mem_fn(&X::g8)(sp, 1, 2, 3, 4, 5, 6, 7, 8);

如果还要把一个多参数成员函数作用于一个容器的话,好像就用不了boost::mem_fn了。我试了试,只有下面这种不是成员函数的情况能编译通过。

class StoreVals

{

int val;

public:

StoreVals ( ) { val = 0; }

friend int lessconst( StoreVals* _sto, int k , int m);

};

int lessconst( StoreVals* _psto, int k , int m)

{

_psto->val -= k + m;

return _psto->val;

}

void main()

{

std::vector <StoreVals* > v2;

std::for_each(

v2.begin( ),

v2.end( ),

boost::bind(

lessconst , _1, 5, 7

)

);

}

如果把lessconst声明为成员函数,就编译不过去了,如下所示:

class StoreVals

{

int val;

public:

StoreVals ( ) { val = 0; }

int lessconst1 ( StoreVals* _psto, int k , int m)

{

_psto->val -= k + m;

return _psto->val;

}

}

void main()

{

std::vector <StoreVals* > v2;

std::for_each(

v2.begin( ),

v2.end( ),

boost::bind(

&StoreVals::lessconst1 , _1, 5, 7

)

);

}

出来一大堆莫名其妙的错误(57个),像

error C2780: 'class boost::_bi::bind_t<R,class boost::_mfi::dm<R,T>,class boost::_bi::list1<class boost::_bi::value<R> > > __cdecl boost::bind(R T::*,A1)' : expects 2 arguments - 4 provided

之流的。不知道为什么。

第三个问题:boost::mem_fn支持智能指针

第四个问题:boost::mem_fn支持__stdcall的调用约定

要想让boost::mem_fn支持__stdcall调用约定,必须在

#include <boost/bind.hpp>

#include <boost/mem_fn.hpp>

之前定义一个宏:

#define BOOST_MEM_FN_ENABLE_STDCALL

请注意,必须在这两个头文件include之前定义宏,否则仍然会有这样的编译错误:

error C2665: 'mem_fn' : none of the 2 overloads can convert parameter 1 from type 'int (__stdcall Stuff::*)(void)'

第五个问题:无论什么情况,只用一个boost:mem_fn即可

所以,你可以这样,也可以那样,但是请记住boost::mem_fn吧。

本文档所包含的信息代表了在发布之日,ZhengYun 对所讨论问题的当前看法,Zhengyun 不保证所给信息在发布之日以后的准确性。

本文档仅供参考。对本文档中的信息,Zhengyun 不做任何明示或默示的保证。

Written by zhengyun@tomosoft.com

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有