Boost logo

Boost Users :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2007-02-15 22:03:25


Scott Meyers wrote:
> The mem_fn documentation is clear that there may be problems using
> mem_fn with the standard binders:
>
>> mem_fn is not 100% compatible with the standard adaptors, although
>> it comes pretty close. In particular, mem_fn does not return
>> objects of type std::[const_]mem_fun[1][_ref]_t, as the standard
>> adaptors do, and it is not possible to fully describe the type of
>> the first argument using the standard argument_type and
>> first_argument_type nested typedefs. Libraries that need adaptable
>> function objects in order to function might not like mem_fn.
>
> Fair enough. The program below fails to compile with VC8 and g++
> 4.1.1, and the VC8 error message (which I find much more readable
> than the g++ one) suggests that I'm running into the problem
> mentioned above. However, the program DOES compile using Comeau
> 4.3.8, and that's what confuses me. Does anybody have any insights
> into whether this code is supposed to compile?

I've no idea how it could work with Comeau 4.3.8. mem_fn(&Point::rotate)
defines its ::first_argument_type as Point*. libcomo 3.5's binder2nd takes a
first_argument_type:

  typename _Operation::result_type
  operator()(const typename _Operation::first_argument_type& __x) const {
    return op(__x, value);
  }

so it should fail.

> I'm especially
> interested in any remarks about whether it should compile using
> std::tr1::mem_fn, should there be any differences between that and
> boost::mem_fn.

tr1::mem_fn is mostly the same. The only difference is that it's required to
derive from std::binary_function<Point*,int, void> in this case, instead of
just defining the typedefs. This requirement wasn't present in the original
proposal.

In any event, having access to boost/tr1::mem_fn also implies that you have
access to boost/tr1::bind:

   std::for_each( vp.begin(), vp.end(),
                 boost::bind( &Point::rotate, _1, 10 ) );

so there is little practical reason to attempt to use bind2nd with mem_fn.

> #include <vector>
> #include <algorithm>
> #include <functional>
> #include "boost/mem_fn.hpp"
>
> struct Point {
> void rotate(int degrees);
> };
>
> int main()
> {
> std::vector<Point> vp;
>
> std::for_each(vp.begin(), vp.end(),
> std::bind2nd(boost::mem_fn(&Point::rotate), 10));
> }


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net