By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,956 Members | 1,224 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,956 IT Pros & Developers. It's quick & easy.

mem_fun vs mem_fun_ref

P: n/a
What is the exact difference between mem_fun and mem_fun_ref, since in
all examples I looked at, they are used in exactly the same way?

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #1
Share this Question
Share on Google+
13 Replies


P: n/a
"Ioannis Vranos" <iv*@remove.this.grad.com> wrote...
What is the exact difference between mem_fun and mem_fun_ref, since in all
examples I looked at, they are used in exactly the same way?


They return objects of different types, mem_fun_t and mem_fun_ref_t,
whose member functions operator(), in turn, take different arguments,
the former takes T*, the latter takes T&. RTFM.

V
Jul 23 '05 #2

P: n/a
Ioannis Vranos wrote:
What is the exact difference between mem_fun and mem_fun_ref, since in
all examples I looked at, they are used in exactly the same way?


mem_fun returns an object that can be called with a pointer to an
object; mem_fun_ref returns an object that can be called with an object
or a reference to an object. Like this:

#include <functional>
#include <iostream>
using std::mem_fun; using std::mem_fun_ref;
using std::cout;

struct S
{
void f()
{
cout << "called S::f\n";
}
};

int main()
{
S s;
S *sp = &s;
mem_fun(&S::f)(sp);
mem_fun_ref(&S::f)(s);
return 0;
}

TR1's mem_fn doesn't require this early a decision; mem_fn(&S::f) can be
called with an object, a reference to an object, a pointer to an object,
or a smart pointer to an object.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 23 '05 #3

P: n/a
Ioannis Vranos wrote:
What is the exact difference between mem_fun and mem_fun_ref, since in all examples I looked at, they are used in exactly the same way?


The difference is how the object the member function is called on
is passed to the functor: for a functor returned from 'mem_fun()' a
pointer to the object is passed. For a functor returned from
'mem_fun_ref()' a reference to the object is passed. Although both
version could be folded into just one functor overloading the function
call operator, this could obscure certain problems.
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.contendix.com> - Software Development & Consulting

Jul 23 '05 #4

P: n/a
Thanks for the clarification fellows. However I can't make the following
to work (taken and modified from another message thread):
#include <vector>
#include <algorithm>
#include <functional>
class B {};
class C {};

class A
{
public:
virtual C foo(const B &) const { return C(); }
};

int main()
{
using namespace std;

A obj;
A &a = obj;

vector<B> in(42);

vector<C> out(in.size());

// Here's the problem
transform(in.begin(), in.end(), out.begin(),
(mem_fun_ref(&A::foo) (a));
}


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #5

P: n/a
"Ioannis Vranos" <iv*@remove.this.grad.com> wrote...
[..]
// Here's the problem
transform(in.begin(), in.end(), out.begin(),
(mem_fun_ref(&A::foo) (a));
What is "(a)" doing there? Did you mean to use 'bind1st'?
}


V
Jul 23 '05 #6

P: n/a
Ioannis Vranos wrote:
(mem_fun_ref(&A::foo) (a));


Since A::foo takes one argument you have to pass two arguments to the
function call operator of the object returned by mem_fun_ref -- one for
the object to call the member function with, and one for the explicit
argument. mem_fun_ref(&A::foo)(a) tries to call it with only one
argument. And even if it took only one, you wouldn't call its operator()
from here; transform will call it.

So back up a bit. mem_fun_ref in this case returns an object whose
function call operator takes two arguments. You want to *bind* the value
'a' to the *first* argument, and pass the argument provided by transform
as the second argument. To *bind* the *first* argument use bind1st:

bind1st(mem_fun_ref(&A::foo), obj)

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 23 '05 #7

P: n/a
Pete Becker wrote:
Since A::foo takes one argument you have to pass two arguments to the
function call operator of the object returned by mem_fun_ref -- one for
the object to call the member function with, and one for the explicit
argument. mem_fun_ref(&A::foo)(a) tries to call it with only one
argument. And even if it took only one, you wouldn't call its operator()
from here; transform will call it.

So back up a bit. mem_fun_ref in this case returns an object whose
function call operator takes two arguments. You want to *bind* the value
'a' to the *first* argument, and pass the argument provided by transform
as the second argument. To *bind* the *first* argument use bind1st:

bind1st(mem_fun_ref(&A::foo), obj)

Thanks for the reply however the code:

#include <vector>
#include <algorithm>
#include <functional>
class B {};
class C {};

class A
{
public:
virtual C foo(const B &) const { return C(); }
};

int main()
{
using namespace std;

A obj;
A &a = obj;

vector<B> in(42);

vector<C> out(in.size());

transform(in.begin(), in.end(), out.begin(),
bind1st(mem_fun_ref(&A::foo), obj) );
}

doesn't compile either:

C:\c>g++ temp.cpp -o temp.exe
C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/stl_f
unction.h: In instantiation of
`std::binder1st<std::const_mem_fun1_ref_t<C, A, c
onst B&> >':
temp.cpp:29: instantiated from here
C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/stl_f
unction.h:406: error: forming reference to reference type `const B&'
C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/stl_f
unction.h:412: error: forming reference to reference type `const B&'
C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/stl_a
lgo.h: In function `_OutputIterator std::transform(_InputIterator,
_InputIterato
r, _OutputIterator, _UnaryOperation) [with _InputIterator =
__gnu_cxx::__normal_
iterator<B*, std::vector<B, std::allocator<B> > >, _OutputIterator =
__gnu_cxx::
__normal_iterator<C*, std::vector<C, std::allocator<C> > >,
_UnaryOperation = st
d::binder1st<std::const_mem_fun1_ref_t<C, A, const B&> >]':
temp.cpp:29: instantiated from here
C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/stl_a
lgo.h:789: error: no match for call to
`(std::binder1st<std::const_mem_fun1_ref_
t<C, A, const B&> >) (B&)'

C:\c>

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #8

P: n/a
However this compiles:
#include <vector>
#include <algorithm>
#include <functional>
class B {};
class C {};

class A
{
public:
virtual C foo(const B) const { return C(); }
};

int main()
{
using namespace std;

A obj;
A &a = obj;

vector<B> in(42);

vector<C> out(in.size());

transform(in.begin(), in.end(), out.begin(),
bind1st(mem_fun_ref(&A::foo), obj) );
}


Isn't there any way to maintain the reference argument in foo?
--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #9

P: n/a
Ioannis Vranos wrote:
Pete Becker wrote:
Since A::foo takes one argument you have to pass two arguments to the
function call operator of the object returned by mem_fun_ref -- one
for the object to call the member function with, and one for the
explicit argument. mem_fun_ref(&A::foo)(a) tries to call it with only
one argument. And even if it took only one, you wouldn't call its
operator() from here; transform will call it.

So back up a bit. mem_fun_ref in this case returns an object whose
function call operator takes two arguments. You want to *bind* the
value 'a' to the *first* argument, and pass the argument provided by
transform as the second argument. To *bind* the *first* argument use
bind1st:

bind1st(mem_fun_ref(&A::foo), obj)


Thanks for the reply however the code:

#include <vector>
#include <algorithm>
#include <functional>
class B {};
class C {};

class A
{
public:
virtual C foo(const B &) const { return C(); }
};

int main()
{
using namespace std;

A obj;
A &a = obj;

vector<B> in(42);

vector<C> out(in.size());

transform(in.begin(), in.end(), out.begin(),
bind1st(mem_fun_ref(&A::foo), obj) );
}

You're looking at this backwards. mem_fun_ref will work on the members
of "in", which are B's, not A's. Therefore foo (returning a C) must be
a member function of B!!!!!! Second, A::foo, as currently implemented
takes a B as an object.

You're essentially writing

class B { };
class C { };
class A {
public:
C foo(const B&);
};

A obj;
B b;

C = b.foo(A);

Does that help a bit?
Jul 23 '05 #10

P: n/a
red floyd wrote:
You're looking at this backwards. mem_fun_ref will work on the members
of "in", which are B's, not A's. Therefore foo (returning a C) must be
a member function of B!!!!!!

Actually no. After the modification I made foo accepting const B objects
and not const B references, it works. However I did not say everything
is easy to understand completely.
Probably it will take many years until we become completely familiar in
the language. :-)

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #11

P: n/a
Ioannis Vranos wrote:

Isn't there any way to maintain the reference argument in foo?


Apparently not. <g> STL is pretty aggressive about dealing with
arguments by value.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 23 '05 #12

P: n/a
Pete Becker wrote:
Apparently not. <g> STL is pretty aggressive about dealing with
arguments by value.

OK, thanks for the info. However may you explain how this works?
class A
{
public:

virtual C foo(const B) const { return C(); }
};

// ...

transform(in.begin(), in.end(), out.begin(),
bind1st(mem_fun_ref(&A::foo), obj) );

A::foo() takes one argument. mem_fun_ref applies the member function to
the objects passed (usually the objects of the sequence). bind1st binds
an argument as the first argument of a *binary function*.
How does it end up working? :-)

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #13

P: n/a
Ioannis Vranos wrote:

A::foo() takes one argument. mem_fun_ref applies the member function to
the objects passed (usually the objects of the sequence). bind1st binds
an argument as the first argument of a *binary function*.
How does it end up working? :-)


A::foo() takes one explicit argument and an implicit 'this' pointer.
When you call mem_fun(&A::foo) or mem_fun_ref(&A::foo) you get back an
object that has a function call operator that take two arguments. The
first is the object that the member function should be applied to (which
provides the 'this' pointer) and the second is the explicit argument to
the member function.

For example:

A a;
A *ap = &a;
B b;

mem_fun_ref(&A::foo)(a, b) is equivalent to a.foo(b).
mem_fun(&A::foo)(ap, b) is equivalent to ap->foo(b).

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 23 '05 #14

This discussion thread is closed

Replies have been disabled for this discussion.