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

<iframe align="top" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog01.html" frameborder="0" width="728" scrolling="no" height="90"></iframe>

boost::mem_fnstd::mem_funMSVC6.0上的表现<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

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_fnstd::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 t> void for_each(<p></p></class>
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

return 0;

}

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

// a similar example.

// void printName()

// {

// std::cout

// }

};

void main()

{

std::vector<stuff> v;<p></p></stuff>

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 stuff>::operator ()(class Stuff &amp;) const'</void>

原来是因为MSVCstl的实现为:

template<class _r class _ty><p></p></class>

class mem_fun_ref_t : public unary_function<_ty _r><p></p></_ty>

{

………….

_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;<p></p></storevals>

std::for_each(

v2.begin( ),

v2.end( ),

std::bind2nd (

std::mem_fun1<int storevals><p></p></int>

( &StoreVals::lessconst ),

5

)

);

return 0;

}

std::mem_funstd::mem_fun_ref支持的成员函数没有参数,而std::mem_fun1std::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

return 0;

}

};

void main()

{

std::vector<stuff> v;<p></p></stuff>

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 functionsCOM interface member functionsstd::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

}

};

void main()

{

std::vector<stuff> v;<p></p></stuff>

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;<p></p></storevals>

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;<p></p></storevals>

std::for_each(

v2.begin( ),

v2.end( ),

boost::bind(

&StoreVals::lessconst1 , _1, 5, 7

)

);

}

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

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

之流的。不知道为什么。

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

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

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

#include <boost><p></p></boost>

#include <boost></boost>

之前定义一个宏:

#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 [email protected]

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=12685


你可能感兴趣的:(windows,F#,Microsoft,Blog,Office)