Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Predicates and sorting?

0 views
Skip to first unread message

Jonathan M. Gilligan

unread,
Oct 1, 1999, 3:00:00 AM10/1/99
to
I want to sort a list by the absolute value of the elements. I write the
following code:

============= begin code snippet =====================
#include <iostream>
#include <list>

using namespace std;

struct Foo
{
int m_nValue;
Foo(int val = 0) : m_nValue(val) {}
bool operator >(const Foo& rhs_) const;
bool operator <(const Foo& rht_) const;
bool greater_mag(const Foo& rht_) const;
};

bool Foo::operator <(const Foo& rhs_) const
{
return m_nValue < rhs_.m_nValue;
}

bool Foo::operator >(const Foo& rhs_) const
{
cerr << "Called >" << endl;
return (m_nValue > rhs_.m_nValue);
}

bool Foo::greater_mag(const Foo& rhs_) const
{
cerr << "Called greater_mag" << endl;
return abs(m_nValue) > abs(rhs_.m_nValue);
}

template <class T_> struct greater_magnitude : public greater<T_>
{
bool operator()(const T_& x, const T_& y) const {
return (x.greater_mag(y));
}
};

int main(int argc, char* argv[])
{
list<Foo> flist;
flist.push_back(Foo(1));
flist.push_back(Foo(-2));
flist.push_back(Foo(3));

flist.sort(greater_magnitude<Foo>());
list<Foo>::const_iterator it = flist.begin();
while (it != flist.end())
cout << it++ ->m_nValue << " ";
cout << endl;
return 0;
}

============= end code snippet =====================

And when I run it, the result is:

=========
Called >
Called >
3 1 -2
=========

The result I want is "3 -2 1".

In other words, STL seems to be ignoring my predicate and calling
greater<Foo>::operator() rather than greater_magnitude<Foo>::operator(). Is
there any way to get the MS version of STL to sort on a predicate other than
operator< or operator>?

The library reference says that if the translator does not support member
template functions, predicates are replaced by greater, but searching the
MSDN for "member template function" does not turn up anything to tell me
about translator support or lack thereof. Can anyone here give me some
clarification.

Are there any other suggestions for how to sort a std::list using a sort
criterion chosen at runtime from a list of several? Should I just implement
my own quicksort function specialized to work on lists of Foo?

Thanks,
Jonathan

P.J. Plauger

unread,
Oct 1, 1999, 3:00:00 AM10/1/99
to
Jonathan M. Gilligan wrote in message ...

>In other words, STL seems to be ignoring my predicate and calling
>greater<Foo>::operator() rather than greater_magnitude<Foo>::operator(). Is
>there any way to get the MS version of STL to sort on a predicate other than
>operator< or operator>?

Yes, change list::sort from:

void sort(_Pr3 _Pr)

to:

template<class _Pr3>
void sort(_Pr3 _Pr)

Member templates got better since the library was packaged. You
can now get away with turning several member functions into
member templates, as they should be to better conform.

HTH,

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com


Doug Harrison

unread,
Oct 1, 1999, 3:00:00 AM10/1/99
to
Jonathan M. Gilligan wrote:

>Are there any other suggestions for how to sort a std::list using a sort
>criterion chosen at runtime from a list of several? Should I just implement
>my own quicksort function specialized to work on lists of Foo?

Repost follows:

Subject: Re: User-defined predicates
From: Doug Harrison <dHar...@worldnet.att.net>
Message-ID: <#W1Sr6rB$GA.197@cppssbbsa03>
Newsgroups: microsoft.public.vc.stl
Date: Fri, 24 Sep 1999 11:57:36 -0700

William McKenzie wrote:

>You are right about including the parens (presumably to instantiate your
>class), on the call. This however does not produce the desired result. In
>fact, if you do so, you will find that you cannot even set a break point in
>the operator() code of your predicate class. this is because it is never
>linked. No matter what you do, std::greater<class T> gets used. This is
>why it insists on operator> on your class, because it never uses your
>predicate class. Something is fishy here, and i think its the microsoft
>compiler.

VC's std::list lacks the member template forms of sort and merge. If you
don't mind modifying system headers, you can change <list> as follows:

Change:

void sort(_Pr3 _Pr)

typedef greater<_Ty> _Pr3;
void merge(_Myt& _X, _Pr3 _Pr)

to:

template<class _Pr3>
void sort(_Pr3 _Pr)

template<class _Pr3>
void merge(_Myt& _X, _Pr3 _Pr)

(Delete the _Pr3 typedef.)

You should also update sort as described at:

http://www.dinkumware.com/vc_fixes.html

--
Doug Harrison
dHar...@worldnet.att.net
Visual C++ MVP


Jonathan M. Gilligan

unread,
Oct 2, 1999, 3:00:00 AM10/2/99
to
Thanks, P.J. Plauger and Doug Harrison, for sharing your expertise and
clearing things up for me.

Best,
Jonathan

0 new messages