How to have multiple sort criteria on a struct?

S

Steve555

Hi,

Given a simple struct such as:

struct myStruct{
long id;
long length;
long width;
} ;

If I define this to use with std::sort() :
bool operator<(myStruct lhs, myStruct rhs)
{
return lhs.id < rhs.id;
}

How do I then sort by one of the other members such as length and
width?

I thought I could get around it by declaring
typedef myStruct myStructSortHeight;
typedef myStruct myStructSortWidth;
bool operator<(myStructSortHeight lhs, myStructSortHeight rhs)
bool operator<(myStructSortWidth lhs, myStructSortWidth rhs)

but my compiler complains of redefinition.

Thanks

Steve
 
K

Kai-Uwe Bux

Steve555 said:
Hi,

Given a simple struct such as:

struct myStruct{
long id;
long length;
long width;
} ;

If I define this to use with std::sort() :
bool operator<(myStruct lhs, myStruct rhs)
{
return lhs.id < rhs.id;
}

How do I then sort by one of the other members such as length and
width?

I thought I could get around it by declaring
typedef myStruct myStructSortHeight;
typedef myStruct myStructSortWidth;
bool operator<(myStructSortHeight lhs, myStructSortHeight rhs)
bool operator<(myStructSortWidth lhs, myStructSortWidth rhs)

but my compiler complains of redefinition.

The compiler is correct. A typedef only introduces a new name for the _same_
type. In particular, the old operator< still matches.

You have two options:

(a) [preferred]

Instead of using operator<, have multiple comparison functions:

bool compare_by_id ( myStruct const & lhs, myStruct const & rhs );

bool compare_by_length ( myStruct const & lhs, myStruct const & rhs );

bool compare_by_width ( myStruct const & lhs, myStruct const & rhs );

All standard algorithms that require a comparison also have a version that
allows the user to supply a comparison functor. Similarly, you can use
std::set and std::map with a user defined comparison. Those would be the
hooks for using the above functions.


(b) [only useful under special circumstances]

You can create new types by inheritance from myStruct. That allows you to
have operator< for each of those types. On the other hand, it introduces a
host of problems with collections since you cannot have objects of
different types in the same container.


Best

Kai-Uwe Bux
 
S

Steve555

Steve555 said:
Given a simple struct such as:
struct myStruct{
long  id;
long  length;
        long  width;
} ;
If I define this to use with std::sort() :
bool operator<(myStruct lhs, myStruct rhs)
{
return lhs.id < rhs.id;
}
How do I then sort by one of the other members such as length and
width?
I thought I could get around it by declaring
typedef myStruct myStructSortHeight;
typedef myStruct myStructSortWidth;
bool operator<(myStructSortHeight lhs, myStructSortHeight rhs)
bool operator<(myStructSortWidth lhs, myStructSortWidth rhs)
but my compiler complains of redefinition.

The compiler is correct. A typedef only introduces a new name for the _same_
type. In particular, the old operator< still matches.

You have two options:

(a) [preferred]

Instead of using operator<, have multiple comparison functions:

  bool compare_by_id ( myStruct const & lhs, myStruct const & rhs );

  bool compare_by_length ( myStruct const & lhs, myStruct const & rhs );

  bool compare_by_width ( myStruct const & lhs, myStruct const & rhs );

All standard algorithms that require a comparison also have a version that
allows the user to supply a comparison functor. Similarly, you can use
std::set and std::map with a user defined comparison. Those would be the
hooks for using the above functions.

(b) [only useful under special circumstances]

You can create new types by inheritance from myStruct. That allows you to
have operator< for each of those types. On the other hand, it introduces a
host of problems with collections since you cannot have objects of
different types in the same container.

Best

Kai-Uwe Bux

Thanks for the clear explanation Kai-Uwe, (a) is perfect for my needs.

Steve
 

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

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,812
Latest member
GracielaWa

Latest Threads

Top