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

Is It Possible...?

92 views
Skip to first unread message

Mike Copeland

unread,
Dec 28, 2013, 9:31:50 AM12/28/13
to
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

---
This email is free from viruses and malware because avast! Antivirus protection is active.
http://www.avast.com

Marcel Müller

unread,
Dec 28, 2013, 9:59:56 AM12/28/13
to
On 28.12.13 15.31, Mike Copeland wrote:
> 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

Paavo Helde

unread,
Dec 28, 2013, 10:57:54 AM12/28/13
to
mrc...@cox.net (Mike Copeland) wrote in
news:MPG.2d288ec04...@news.eternal-september.org:

> 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

Not sure if this is what you want, but here is an example demonstrating
sorting the same vector by different sorting criteria, which are passed
as template arguments:


#include <string>
#include <iostream>
#include <vector>
#include <algorithm>

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

struct SortByTotalTime {
bool operator()(const RelayTeamType& a, const RelayTeamType& b) {
return a.totalTime<b.totalTime;
}
};

struct SortByTeamName {
bool operator()(const RelayTeamType& a, const RelayTeamType& b) {
return a.rtTeamName<b.rtTeamName;
}
};

template<class SORTER>
void ProcessMyTeams(std::vector<RelayTeamType>& teams) {

std::sort(teams.begin(), teams.end(), SORTER());

for (size_t i=0; i<teams.size(); ++i) {
std::cout << " " << teams[i].rtTeamName
<< ", total time " << teams[i].totalTime << "\n";
}
}

int main() {

RelayTeamType example_data[] =
{
{100, 2, 3, 4, 5, "red", "Alpha"},
{50, 2, 3, 4, 5, "green", "Gamma"},
{150, 2, 3, 4, 5, "red", "Beta"},
};

std::vector<RelayTeamType> teams(example_data,
example_data+sizeof(example_data)/sizeof(example_data[0]));

std::cout << "\nProcessing in order of total times:\n";
ProcessMyTeams<SortByTotalTime>(teams);

std::cout << "\nProcessing in order of names:\n";
ProcessMyTeams<SortByTeamName>(teams);

}

--- Output is: ---

Processing in order of total times:
Gamma, total time 50
Alpha, total time 100
Beta, total time 150

Processing in order of names:
Alpha, total time 100
Beta, total time 150
Gamma, total time 50

Thomas Flynn

unread,
Dec 29, 2013, 7:18:45 PM12/29/13
to
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>);


Luca Risolia

unread,
Jan 2, 2014, 9:55:39 PM1/2/14
to
Thomas Flynn wrote:

> 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));

0 new messages