Is It Possible...?

M

Mike Copeland

To "template-ize" a class/struct sort override? I have the following
structure:
struct RelayTeamType
{
time_t totalTime; // Total Time
int bib1, bib2; // Bib# #1 & Bib# #2
int numFins; // # Finishers
char ttc; // Team Type Code
string rtCode, rtTeamName;
string sortKey; // derived sort key
bool operator<(const RelayTeamType &a) const
{
return sortKey < a.sortKey;
}
} extern rtWork;
extern vector<RelayTeamType> rtVect;
extern vector<RelayTeamType>::iterator relIter;

Currently, I'm constructing the "sortKey" variable by passing through
the entire vector and using different variables in the struct (e.g.
"rtCode" or "totalTime", etc.), followed by the sort. This is simple
enough, but it takes processing time I want to avoid.
I'd like to be able to sort the vector on different fields, and it
would be nice if I could do it via a "template" interface. Is this
possible somehow? TIA
 
M

Marcel Müller

I'd like to be able to sort the vector on different fields, and it
would be nice if I could do it via a "template" interface. Is this
possible somehow? TIA

Your sort function should take a comparer that compare two instances of
your vector's element type. std::sort will do exactly this job for you.
It uses a predicate that checks whether the two elements passed to it
are already in correct order. This is usually simply the < operator.

E.g.:

bool OrderedQ_numFins(const RelayTeamType& l, const RelayTeamType& r)
{ return l.numFins < r.numFins;
}

std::sort(rtVect, OrderedQ_numFins);

If you have C++11, you could make this look even more neat by using lambdas.


Marcel
 
T

Thomas Flynn

Mike said:
To "template-ize" a class/struct sort override? I have the following
structure:
struct RelayTeamType
{
time_t totalTime; // Total Time
int bib1, bib2; // Bib# #1 & Bib# #2
int numFins; // # Finishers
char ttc; // Team Type Code
string rtCode, rtTeamName;
string sortKey; // derived sort key
bool operator<(const RelayTeamType &a) const
{
return sortKey < a.sortKey;
}
} extern rtWork;
extern vector<RelayTeamType> rtVect;
extern vector<RelayTeamType>::iterator relIter;

Currently, I'm constructing the "sortKey" variable by passing through
the entire vector and using different variables in the struct (e.g.
"rtCode" or "totalTime", etc.), followed by the sort. This is simple
enough, but it takes processing time I want to avoid.
I'd like to be able to sort the vector on different fields, and it
would be nice if I could do it via a "template" interface. Is this
possible somehow? TIA

Another way to go is like this:

struct RelayTeamType
{
time_t totalTime; // Total Time
int bib1, bib2; // Bib# #1 & Bib# #2
int numFins; // # Finishers
char ttc; // Team Type Code
string rtCode, rtTeamName;
string sortKey; // derived sort key

};

template<typename T, T RelayTeamType::*memb>
bool cmp(const RelayTeamType & lhs,
const RelayTeamType & rhs){
return (lhs).*(memb) < (rhs).*(memb);
}


Here the cmp function is templatized on the member variable you want to
sort by.

You can compare two elements q u like

cmp<time_t,&RelayTeamType::totalTime>(q,u);
cmp<string,&RelayTeamType::rtTeamName>(q,u);

and sort the vector like

std::sort(rtVect.begin(),rtVect.end(),
cmp<string, &RelayTeamType::rtTeamName>);
 
L

Luca Risolia

Thomas said:
template<typename T, T RelayTeamType::*memb>
bool cmp(const RelayTeamType & lhs,
const RelayTeamType & rhs){
return (lhs).*(memb) < (rhs).*(memb);
}


Here the cmp function is templatized on the member variable you want to
sort by.

You can compare two elements q u like

cmp<time_t,&RelayTeamType::totalTime>(q,u);
cmp<string,&RelayTeamType::rtTeamName>(q,u);

and sort the vector like

std::sort(rtVect.begin(),rtVect.end(),
cmp<string, &RelayTeamType::rtTeamName>);

This is easier to use, as you don't need to specify any template arguments for
the comparator:

template<class C, class T>
struct cmp_ {
T C::*m;
constexpr cmp_(T C::*m) noexcept : m{m} { }
bool operator()(RelayTeamType const& a, RelayTeamType const& b) const
noexcept {
return (a.*m) < (b.*m);
}
};

template <class C, class T>
auto cmp(T C::*m) noexcept -> cmp_<C, T> {
return m;
}

std::sort(std::begin(rtVect), std::end(rtVect),
cmp(&RelayTeamType::rtTeamName));
 

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,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top