Connecting Tech Pros Worldwide Forums | Help | Site Map

Member function as parameter of STL algorithm

many_years_after
Guest
 
Posts: n/a
#1: Jul 17 '07
Hi, cppers:

I am studying cpp recently. As is said, member funciton can be as
one parameter of stl algorithm. BUT when I pass member function whose
parameter is instance of the class, it doesn't work. For example:

class Point
{
public:
int x; int y;
Point(int xx, int yy)
{
x = xx;
y = yy;
}
friend ostream& operator<<(ostream& out,const Point& p)
{
out << p.x << " "<< p.y << endl;
return out;
}
bool LargeThan(const Point& p)
{

return (x p.x)|| ((x==p.x) && (y p.y));
}
void print()
{
cout << x << " " << y;
}
void printWithPre(const char* s)
{
cout << s << " " << x;
}
};
int main()
{
vector<Pointvec;

for (int i = 0; i < 10; i++)
vec.push_back(Point(i, i));
for_each(
vec.begin(),
vec.end(),
bind2nd(mem_fun_ref(&Point::printWithPre),"hello:" )
); //OK

for_each(
vec.begin(),
vec.end(),
mem_fun_ref(&Point::print)); // OK
sort(vec.begin(), vec.end(), mem_fun_ref(&Point::LargeThan)); //
ERROR WHEN COMPILING


return 0;
}

I don't know why it does not work. What's the reasong?


Juha Nieminen
Guest
 
Posts: n/a
#2: Jul 17 '07

re: Member function as parameter of STL algorithm


many_years_after wrote:
Quote:
sort(vec.begin(), vec.end(), mem_fun_ref(&Point::LargeThan)); //
ERROR WHEN COMPILING
Member functions cannot be called without an object of the class type.
You can think of member functions as if they took a pointer to an object
of that class type as a hidden parameter. (And this is, in practice,
actually the case. The name of that pointer is called "this" inside the
function.)

What you can do is create a regular function (or a static member
function) which takes two const references of the class type and returns
the result of the comparison, and then give that to std::sort().
(Or you could also create a functor, ie. a class/struct which behaves
like such a function by overloading operator().)
Robert Bauck Hamar
Guest
 
Posts: n/a
#3: Jul 17 '07

re: Member function as parameter of STL algorithm


Juha Nieminen wrote:
Quote:
many_years_after wrote:
Quote:
> sort(vec.begin(), vec.end(), mem_fun_ref(&Point::LargeThan)); //
>ERROR WHEN COMPILING
>
Member functions cannot be called without an object of the class type.
You can think of member functions as if they took a pointer to an object
of that class type as a hidden parameter. (And this is, in practice,
actually the case. The name of that pointer is called "this" inside the
function.)
>
What you can do is create a regular function (or a static member
function) which takes two const references of the class type and returns
the result of the comparison, and then give that to std::sort().
(Or you could also create a functor, ie. a class/struct which behaves
like such a function by overloading operator().)
Yes. The idea behind mem_fun_ref() is to create such a functor. It returns
an object, call it o, capable of transforming o(a, b) to o.fun(b) for some
pointer to member function given as argument.

--
rbh
Robert Bauck Hamar
Guest
 
Posts: n/a
#4: Jul 18 '07

re: Member function as parameter of STL algorithm


many_years_after wrote:
Quote:
Hi, cppers:
>
I am studying cpp recently. As is said, member funciton can be as
one parameter of stl algorithm. BUT when I pass member function whose
parameter is instance of the class, it doesn't work. For example:
>
class Point
{
public:
int x; int y;
Point(int xx, int yy)
{
x = xx;
y = yy;
}
friend ostream& operator<<(ostream& out,const Point& p)
error: ostream not declared. Yes it's easy to fix, but if you want help,
posting compilable code (or in this case, code that has no other errors)
will help.
Quote:
{
out << p.x << " "<< p.y << endl;
IMHO, you should remove the endl. There are two reasons:
1) endl provokes a flush. If the user wants a flush, the user can flush on
his/her own. 2) endl sends an '\n'. This will make this operator useless in
most cases. Try to use it to output tabular data, for instance.
Quote:
return out;
}
bool LargeThan(const Point& p)
bool LargeThan(const Point& p) const
Quote:
{
>
return (x p.x)|| ((x==p.x) && (y p.y));
}
void print()
void print() const
Quote:
{
cout << x << " " << y;
}
This does exactly what (parts of) operator<<(ostream&, const Point&) does,
and IMO what operator << should have done.
Quote:
void printWithPre(const char* s)
void printWithPre(const char* s) const
Quote:
{
cout << s << " " << x;
}
};
int main()
{
vector<Pointvec;
>
for (int i = 0; i < 10; i++)
vec.push_back(Point(i, i));
for_each(
vec.begin(),
vec.end(),
bind2nd(mem_fun_ref(&Point::printWithPre),"hello:" )
); //OK
>
for_each(
vec.begin(),
vec.end(),
mem_fun_ref(&Point::print)); // OK
sort(vec.begin(), vec.end(), mem_fun_ref(&Point::LargeThan)); //
ERROR WHEN COMPILING
Here, mem_fun_ref returns a functor with

bool operator()(Point& a, const Point& b) const, and this calls
a.LargeThan(b). Not that LargeThan is non-const on a. The standard
specifies:
It is assumed that comp [the comparator] will not apply any non-constant
function through the dereferenced iterator.

On g++ 4.2.0 it compiles only if the comparator is called with two
references to const objects. Is this a bug?
Quote:
return 0;
}
>
I don't know why it does not work. What's the reasong?
If a member function doesn't modify the object, consider making it const.

--
rbh
int2str@gmail.com
Guest
 
Posts: n/a
#5: Jul 19 '07

re: Member function as parameter of STL algorithm


On Jul 17, 7:42 am, many_years_after <shua...@gmail.comwrote:
Quote:
Hi, cppers:
>
I am studying cpp recently. As is said, member funciton can be as
one parameter of stl algorithm. BUT when I pass member function whose
parameter is instance of the class, it doesn't work. For example:
It won't work. std::sort() either needs a predicate function
(functor), or it simply needs the < (less than) operator to work
correctly.

The latter case is the easiest. Let's make your code work...


#include <iostream>
#include <ostream>
#include <algorithm>
#include <vector>

using namespace std;

Quote:
class Point
{
public:
int x; int y;
Point(int xx, int yy)
{
x = xx;
y = yy;
}
friend ostream& operator<<(ostream& out,const Point& p)
{
out << p.x << " "<< p.y << endl;
return out;
}
bool LargeThan(const Point& p)
bool LargerThan(const Point& p) const // const is IMPORTANT
here...
Quote:
{
>
return (x p.x)|| ((x==p.x) && (y p.y));
}
void print()
{
cout << x << " " << y;
}
void printWithPre(const char* s)
{
cout << s << " " << x;
}
bool operator< (const Point& p ) const
{
return !LargerThan(p);
}
Quote:
};
>
int main()
{
vector<Pointvec;
>
for (int i = 0; i < 10; i++)
vec.push_back(Point(i, i));
for_each(
vec.begin(),
vec.end(),
bind2nd(mem_fun_ref(&Point::printWithPre),"hello:" )
); //OK
>
for_each(
vec.begin(),
vec.end(),
mem_fun_ref(&Point::print)); // OK
sort(vec.begin(), vec.end(), mem_fun_ref(&Point::LargeThan)); //
ERROR WHEN COMPILING
Now that the operator is defined, simply use:

sort(vec.begin(), vec.end());
Quote:
>
return 0;
>
}
>
I don't know why it does not work. What's the reasong?

James Kanze
Guest
 
Posts: n/a
#6: Jul 19 '07

re: Member function as parameter of STL algorithm


many_years_after wrote:
Quote:
I am studying cpp recently. As is said, member funciton can be as
one parameter of stl algorithm. BUT when I pass member function whose
parameter is instance of the class, it doesn't work. For example:
Quote:
class Point
{
public:
[...]
Quote:
bool LargeThan(const Point& p)
[...]
Quote:
void print()
[...]
Quote:
};
int main()
{
vector<Pointvec;
[...]
Quote:
for_each(
vec.begin(),
vec.end(),
mem_fun_ref(&Point::print)); // OK
sort(vec.begin(), vec.end(), mem_fun_ref(&Point::LargeThan)); //
ERROR WHEN COMPILING
Quote:
return 0;
}
Quote:
I don't know why it does not work. What's the reasong?
mem_fun_ref doesn't work when the function argument is a
reference. I'd consider it a defect in the standard. At any
rate, the next version of the standard will contain some more
advanced tools for this sort of thing, based on boost::bind. In
the meantime, use boost::bind.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Pete Becker
Guest
 
Posts: n/a
#7: Jul 19 '07

re: Member function as parameter of STL algorithm


On 2007-07-19 04:54:02 -0400, James Kanze <james.kanze@gmail.comsaid:
Quote:
>
mem_fun_ref doesn't work when the function argument is a
reference. I'd consider it a defect in the standard. At any
rate, the next version of the standard will contain some more
advanced tools for this sort of thing, based on boost::bind. In
the meantime, use boost::bind.
Also, std::mem_fn (which I think is also in boost) is a simpler
template than bind, pretty much a drop-in replacement for mem_fun and
mem_fun_ref. For details, see chapter 7 of my book, "The Standard C++
Library Extensions".

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

Closed Thread