mem_fun with template function

O

Old Wolf

I have a member function that acts on an object. I would also like to
have a member function that acts on a container of such objects,
using std::for_each. I tried:

#include <algorithm>
#include <functional>

struct bar {
template<typename T> void foo(T const &);
template<typename InIt> void foo(InIt begin, InIt end)
{ std::for_each(begin, end, foo); }
};

but got a compiler error (at the point of calling foo, not at the point
of declaration) because 'foo' was a pointer to member function, rather
than a pointer to function. So I tried:
std::for_each(begin, end, std::mem_fun(&foo));
but got the error:
Could not find a match for std::mem_fun<S,T>(void (bar::*)(const T &))

Finally I tried:
std::for_each(begin, end, std::mem_fun(&foo<typename InIt::value_type>));
but got an ICE.

What is the correct usage?

I have in fact solved the problem with:
{ for (; begin != end; ++begin) fo(*begin); }
but would like to know if it is possible with for_each anyway.
 
D

Daniel T.

I have a member function that acts on an object. I would also like to
have a member function that acts on a container of such objects,
using std::for_each. I tried:

#include <algorithm>
#include <functional>

struct bar {
template<typename T> void foo(T const &);
template<typename InIt> void foo(InIt begin, InIt end)
{ std::for_each(begin, end, foo); }
};

but got a compiler error (at the point of calling foo, not at the point
of declaration) because 'foo' was a pointer to member function, rather
than a pointer to function. So I tried:
std::for_each(begin, end, std::mem_fun(&foo));
but got the error:
Could not find a match for std::mem_fun<S,T>(void (bar::*)(const T &))

Finally I tried:
std::for_each(begin, end, std::mem_fun(&foo<typename InIt::value_type>));
but got an ICE.

What is the correct usage?

struct bar {
template < typename T >
void foo(const T) const { /* whatever */ }
template < typename InIt >
void foo(InIt begin, InIt end) const {
for_each(begin, end,
bind1st(mem_fun(&bar::foo<typename InIt::value_type>) ,this));
}
};

Note that foo no longer takes a 'const T&', it takes a 'const T'. This
is because of a problem with the language that you can't take a
reference to a reference. I think this is scheduled to be fixed in the
next version of C++?

I have in fact solved the problem with:
{ for (; begin != end; ++begin) foo(*begin); }
but would like to know if it is possible with for_each anyway.

I would write it:
{ while (begin != end) foo( *begin++ ); }
 
D

David Hilsee

Old Wolf said:
I have a member function that acts on an object. I would also like to
have a member function that acts on a container of such objects,
using std::for_each. I tried:

#include <algorithm>
#include <functional>

struct bar {
template<typename T> void foo(T const &);
template<typename InIt> void foo(InIt begin, InIt end)
{ std::for_each(begin, end, foo); }
};

but got a compiler error (at the point of calling foo, not at the point
of declaration) because 'foo' was a pointer to member function, rather
than a pointer to function. So I tried:
std::for_each(begin, end, std::mem_fun(&foo));
but got the error:
Could not find a match for std::mem_fun<S,T>(void (bar::*)(const T &))

Finally I tried:
std::for_each(begin, end, std::mem_fun(&foo<typename InIt::value_type>));
but got an ICE.

What is the correct usage?

I have in fact solved the problem with:
{ for (; begin != end; ++begin) fo(*begin); }
but would like to know if it is possible with for_each anyway.

This looks like a case where attempting to only use the functionality
provided by the standard library is difficult, if not impossible. You first
create an instance of mem_fun1_t<void, bar, const T&>. You need to bind the
first argument of the mem_fun1_t's operator() to this, so you need to create
a binder1st, which will expose an operator() which will declare a const T&&,
which is not allowed. The boost library may make this easier. However, I
wouldn't worry about it, because the for loop is much clearer.
 
T

tom_usenet

struct bar {
template < typename T >
void foo(const T) const { /* whatever */ }
template < typename InIt >
void foo(InIt begin, InIt end) const {
for_each(begin, end,
bind1st(mem_fun(&bar::foo<typename InIt::value_type>) ,this));
}
};

Note that foo no longer takes a 'const T&', it takes a 'const T'. This
is because of a problem with the language that you can't take a
reference to a reference. I think this is scheduled to be fixed in the
next version of C++?

The standard library technical report (due soon) includes
std::tr1::bind and std::tr1::mem_fn which sidestep these problems
without language changes. e.g.

bind(&bar::foo<typename InIt::value_type>, this)

and foo can take a reference parameter now.

Tom
 
O

Old Wolf

Daniel T. said:
I would write it:
{ while (begin != end) foo( *begin++ ); }

But that causes an object to be created and destroyed every time
around the loop (the return-value from operator++ I mean), if
the iterator is a class type? (as it usually will be in my
project, since this gets called for deques).
 
D

Daniel T.

But that causes an object to be created and destroyed every time
around the loop (the return-value from operator++ I mean), if
the iterator is a class type? (as it usually will be in my
project, since this gets called for deques).

*If* profiling shows this to be a performance hit, then change it...
What is being created is an iterator, not exactly the largest object in
the world.
 

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