call_mem_fun

R

rile

I have this problem that I meet quite often.

I have a STL container with bunch of whatever objects. The container is
a member of a class that does something. Now, I want to apply a member
of this class to each of the contained objects.

mem_fun will CALL the given member function OF THE CONTAINED object,
but what I want is to call the given method of the CONTAINING object
with the argument being a contained object.

For example:


class Foo
{
public:
....
void doSomething(int i)
{
cout << i << endl;
}

void doSomethingWithEach()
{
for_each<myv.begin(), myv.end(), call_mem_fun(&Foo::doSomething,
this));
}


std::vector<int> myv;
};

NOTE:
call_mem_fun would call "doSomething" and pass to it each int from the
container.



================
So I created the "call_mem_fun" functor, but I'm not sure if I was
reinventing the wheel (just can not believe there is not such thing
already out there somewhere).


Any suggestions?
 
M

mlimber

rile said:
I have this problem that I meet quite often.

I have a STL container with bunch of whatever objects. The container is
a member of a class that does something. Now, I want to apply a member
of this class to each of the contained objects.

mem_fun will CALL the given member function OF THE CONTAINED object,
but what I want is to call the given method of the CONTAINING object
with the argument being a contained object.

For example:


class Foo
{
public:
...
void doSomething(int i)
{
cout << i << endl;
}

void doSomethingWithEach()
{
for_each<myv.begin(), myv.end(), call_mem_fun(&Foo::doSomething,
this));
}


std::vector<int> myv;
};

NOTE:
call_mem_fun would call "doSomething" and pass to it each int from the
container.



================
So I created the "call_mem_fun" functor, but I'm not sure if I was
reinventing the wheel (just can not believe there is not such thing
already out there somewhere).


Any suggestions?

std::tr1::bind does the same thing (cf. Boost.Bind).

Cheers! --M
 
R

rile

I read a bout bind, but I couldn't find the version that does what I
want...

Here is compilable example of the use-case I am looking for; could you
add using "bind" so the code is functionally the same?

Thanks!


#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
class Bar
{
public:
Bar(int n) : _n(n) {}
int getN() const { return _n; }
private:
int _n;
};
class Foo
{
public:
Foo()
{
for (int i = 0; i != 10; ++i)
bars.push_back(Bar(i));
}
void printABar(Bar const &bar) const
{
cout << bar.getN() << endl;
}
void printAllBars() const
{
for_each(bars.begin(), bars.end(), call_mem_fun(&Foo::printABar,
this));
}
private:
vector<Bar> bars;
};

.... in main:

Foo foo;
foo.printAllBars();

(RESULT: it prints out to the console numbers 0 to 9 each in a new
line)
 
D

Daniel T.

rile said:
I have this problem that I meet quite often.

I have a STL container with bunch of whatever objects. The container is
a member of a class that does something. Now, I want to apply a member
of this class to each of the contained objects.

mem_fun will CALL the given member function OF THE CONTAINED object,
but what I want is to call the given method of the CONTAINING object
with the argument being a contained object.

For example:


class Foo
{
public:
...
void doSomething(int i)
{
cout << i << endl;
}

void doSomethingWithEach()
{
for_each<myv.begin(), myv.end(), call_mem_fun(&Foo::doSomething,
this));
}


std::vector<int> myv;
};

NOTE:
call_mem_fun would call "doSomething" and pass to it each int from the
container.



================
So I created the "call_mem_fun" functor, but I'm not sure if I was
reinventing the wheel (just can not believe there is not such thing
already out there somewhere).


Any suggestions?

for_each( vec.begin(), vec.end(), bind1st( mem_fun(&Foo::bar), this ) );
 
P

Pete Becker

rile said:
void doSomethingWithEach()
{
for_each<myv.begin(), myv.end(), call_mem_fun(&Foo::doSomething,
this));
}

bind1st(mem_fun(&Foo::doSomething), this)

If you have TR1 you can make it a bit simpler:


bind(&Foo::doSomething, this, _1)

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
R

rile

Thank you for your replies.

bind1st(mem_fun(&Foo::bar), this))

was what I considered first, but it seems that it won't work if 'bar'
takes reference to argument type (like in my example above). At least
not on MS VS 2005.

well, here is my implementation for those who want to see the diff
(NOTE: I renamed my function "pass_to_mem_fun" because I thought it was
clearer than "call_mem_fun")

template <typename _Result, typename T, typename ArgT>
class pass_to_mem_fun_t : public std::unary_function<ArgT, _Result>
{
public:
explicit pass_to_mem_fun_t(_Result (T::*_Pm)(ArgT), T *pThis)
: _Pmemfun(_Pm), _this(pThis)
{
}

_Result operator()(ArgT _Pleft) const
{ // call function
return (_this->*_Pmemfun)(_Pleft);
}

private:
T *_this;
_Result (T::*_Pmemfun)(ArgT); // the member function pointer
};

template <typename _Result, typename T, typename ArgT>
class pass_to_const_mem_fun_t : public std::unary_function<ArgT,
_Result>
{
public:
explicit pass_to_const_mem_fun_t(_Result (T::*_Pm)(ArgT) const, T
const *pThis)
: _Pmemfun(_Pm), _this(pThis)
{
}

_Result operator()(ArgT _Pleft) const
{ // call function
return (_this->*_Pmemfun)(_Pleft);
}

private:
T const *_this;
_Result (T::*_Pmemfun)(ArgT) const; // the member function pointer
};
template <typename _Result, typename T, typename ArgT>
pass_to_mem_fun_t<_Result, T, ArgT>
pass_to_mem_fun(_Result (T::*pFn)(ArgT), T *pThis)
{
return pass_to_mem_fun_t<_Result, T, ArgT>(pFn, pThis);
}

template <typename _Result, typename T, typename ArgT>
pass_to_const_mem_fun_t<_Result, const T, ArgT>
pass_to_mem_fun(_Result (T::*pFn)(ArgT) const, T const*pThis)
{
return pass_to_const_mem_fun_t<_Result, const T, ArgT>(pFn, pThis);
}

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

in the foo-bar example I gave, the call would look like this:

for_each(bars.begin(), bars.end(), pass_to_mem_fun(&Foo::printABar,
this));

====

Anyhow, if you see that the "Foo bar" example I posted can be compiled
with any of the standard alternatives, I am eager to know it.

Thank you,

Aleksandar
 
S

Salt_Peter

rile said:
I have this problem that I meet quite often.

I have a STL container with bunch of whatever objects. The container is
a member of a class that does something. Now, I want to apply a member
of this class to each of the contained objects.

mem_fun will CALL the given member function OF THE CONTAINED object,
but what I want is to call the given method of the CONTAINING object
with the argument being a contained object.

For example:


class Foo
{
public:
...
void doSomething(int i)
{
cout << i << endl;
}

void doSomethingWithEach()
{
for_each<myv.begin(), myv.end(), call_mem_fun(&Foo::doSomething,
this));
}


std::vector<int> myv;
};

NOTE:
call_mem_fun would call "doSomething" and pass to it each int from the
container.



================
So I created the "call_mem_fun" functor, but I'm not sure if I was
reinventing the wheel (just can not believe there is not such thing
already out there somewhere).


Any suggestions?

As already mentioned: boost's lambda and bind
http://www.boost.org/libs/bind/bind.html

#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

template< typename T >
class Foo
{
std::vector< T > myv;
public:

void push_back(const T& r_t)
{
myv.push_back( r_t );
}

static void doSomething( const T& t ) {
std::cout << t << std::endl;
}

void doSomethingWithEach() const {
using boost::lambda::_1;
using boost::lambda::bind;
std::for_each( myv.begin(),
myv.end(),
bind(&doSomething, _1) );
}
};

int main()
{
Foo< int > foo;
foo.push_back(0);
foo.push_back(1);
foo.push_back(2);

foo.doSomethingWithEach();
}

/*
0
1
2
*/
 
P

Pete Becker

rile said:
bind1st(mem_fun(&Foo::bar), this))

was what I considered first, but it seems that it won't work if 'bar'
takes reference to argument type (like in my example above).

In your original example, the member function takes its argument by
value, not by reference.

STL in its original form passes just about everything by value, and
that's a limitation of mem_fun. The bind version works for references.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
R

rile

OK, boost::bind works!

for_each(bars.begin(), bars.end(), boost::bind(&Foo::doSomething, &foo,
_1));

boost::bind does it!

Thank you all for your replies.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top