Topic: using std::bind2nd and std::mem_fun_ref


Author: Joel Reed <jreed@ddiworld.COM>
Date: 2000/01/01
Raw View
I'm using gcc-2.95.2 and am having problems with std::bind2nd.

it seems that gcc doesn't like:

 std::for_each(q.begin(), q.end(), std::bind2nd(std::mem_fun_ref(&person::mature), 2));

i think its because std::bind2nd takes a const Predicate. (really not sure though)
but gcc says...

/usr/lib/gcc-lib/i586-mandrake-linux/2.95.1/../../../../include/g++-3/stl_function.h: In method `void binder2nd<mem_fun1_ref_t<void,person,int> >::operator ()(const person &) const':
/usr/lib/gcc-lib/i586-mandrake-linux/2.95.1/../../../../include/g++-3/stl_algo.h:83:   instantiated from `for_each<reverse_iterator<_Deque_iterator<person,person &,person *,0> >, binder2nd<mem_fun1_ref_t<void,person,int> > >(reverse_iterator<_Deque_iterator<person,person &,person *,0> >, reverse_iterator<_Deque_iterator<person,person &,person *,0> >, binder2nd<mem_fun1_ref_t<void,person,int> >)'
tmp.cpp:30:   instantiated from here
/usr/lib/gcc-lib/i586-mandrake-linux/2.95.1/../../../../include/g++-3/stl_function.h:224: conversion from `const person' to `person &' discards qualifiers
/usr/lib/gcc-lib/i586-mandrake-linux/2.95.1/../../../../include/g++-3/stl_function.h:622: in passing argument 1 of `mem_fun1_ref_t<void,person,int>::operator ()(person &, int) const'

Is there a better way (one that compiles!) to do the above? I did discover that
if I make person::mature(int) a const & person::age a mutable that it compiles
and runs, but that seems pretty ugly.

i also tried q.rbegin() & q.rend() to make sure i was getting a iterator and
not a const_iterator (from q.begin()) but that didn't help.

here's the whole test program:

#include <iostream>
#include <algorithm>
#include <deque>
#include <functional>

struct person
{
 person(int a) : age(a) {}
 void mature(int i=0) { age+=i; }
 int age;
};

std::ostream& operator << (std::ostream& os, const person& p)
{
 os << "person " << (int)&p << " is " << p.age << " years old.\n";
 return os;
}

typedef std::deque<person> iq_t;

template <class T> T& element (T& t) { return t; };

void main()
{
 iq_t q;
 person p1(1), p2(2), p4(4), p8(8);
 q.push_back(p1); q.push_back(p2); q.push_back(p4); q.push_back(p8);

 std::copy(q.begin(), q.end(), std::ostream_iterator<person>(std::cout));
 std::for_each(q.begin(), q.end(), std::bind2nd(std::mem_fun_ref(&person::mature), 2));
 std::copy(q.begin(), q.end(), std::ostream_iterator<person>(std::cout));
}

thanks for any help,
jr


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Darin Adler <darin@bentspoon.com>
Date: 2000/01/02
Raw View
Joel Reed <jreed@ddiworld.COM> wrote:

> I'm using gcc-2.95.2 and am having problems with std::bind2nd.
>
> it seems that gcc doesn't like:
>
>     std::for_each(q.begin(), q.end(),
>     std::bind2nd(std::mem_fun_ref(&person::mature), 2));
>
> i think its because std::bind2nd takes a const Predicate. (really not sure
> though)

This is a flaw in the C++ Standard, not in gcc. There are no versions of
bind2nd and the related templates where the unbound parameters are
non-const. Thus, when you use mem_fun_ref with a non-const member function,
you get a function object that can't be used with bind2nd.

Bjarne Stroustrup noticed this problem and reported it to the C++ Standards
Committee. It is currently under consideration by the library working group
as issue #109, "Missing binders for non-const sequence elements"
<http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#109>.

Note that this comes up in Josuttis's C++ Library book as well. See the
section 8.2.2 part of <http://www.josuttis.com/libbook/errata1_3.html>.

    -- Darin



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]