: Amit Bhatia wrote:
....
: > class B{
: > //other stuff;
: > list<A> mylist;
....
: > Now I would like to sort the elements of mylist according to some
: > criteria. My question is how can I do it? I know stl list provides
built
: > in sort function:
Just a note to the OP, as others implicitly pointed out:
an std::list can only be sorted using its member function
'sort', unlike random access containers (like std::vector
or std::queue) on which you use std::sort found in <algorithm>.
: > where do I need to write/define this function so that I
: > can call something like:
: > mylist.sort(); ?
: >
: > The class A is a concrete class. Do I need to define something the
: > function in class A?
: > thanks,
:
: You have several options:
:
: a) define a member function
:
: class A {
: ...
: bool operator< ( A const & rhs ) const {
: }
:
: }
:
: b) define a free-standing (friend) operator:
:
: bool operator< ( A const & lhs, A const & rhs ) {
: }
Of these two options, I always use b).
Reasons for this? :
- writing the implementation of b) is clearer,
more symmetric, and less error prone.
- implicit conversions: when using a), implicit
convertions to A will only be performed on the
rhs, but not on the lhs. Think of having a
BigInt class having a non-explicit constructor
from 'int', with a) you would not be able to
compile: bool b = 5 < myBigIntValue.
b) can directly be implemented within the class
body as follows:
friend bool operator<( A const& a, A const& b )
{ return a.m < b.m; }
: c) add a specialization to std::less<>:
:
: namespace std {
:
: template <>
: struct less< A > : binary_predicate< A > {
:
: bool operator() ( A const & lhs, A const & rhs ) {
: }
:
: };
I have trouble envisioning why one would want to write
this. IMO std::less still implies a natural, default
ordering of the operands, and if this is the case,
I'd rather provide the comparison operator <.
This is delicate to get right, and as far as I know,
there is no "binary_predicate" template in the standard
(you'd have to use binary_function<A,A,bool>).
: d) define a free standing (friend) predicate
:
: bool is_less ( A const & lhs, A const & rhs ) {
: }
:
: and pass this as a parameter:
:
: mylist.sort( is_less );
An alternative to this d) is to provide a predicate object:
struct AByName {
bool operator()( A const& a, A const& b )
{ return a.name < b.name; }
};
Passing it as:
mylist.sort( AByName() );
This may be more verbose, but has advantages:
- parameters can be provided to the comparison object
(and stored as data members), for example to indicate
which data member is to be used.
- I'm not sure this remains the case, but compilers used
to be more apt at inlining a predicate object than
a function provided by pointer ( = faster performance ).
So personally, I would only consider one of these 2 (or 3)
options:
- if there is a natural ordering, define operator < (as per b) )
- if there is none, use a predicate function or object
( d) or my last suggestion above )
Kind regards,
Ivan