By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,508 Members | 1,813 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,508 IT Pros & Developers. It's quick & easy.

Comparison function to sort()

P: n/a
I want to use sort() and supply my own comparison function, like

bool lessThan(const S& a, const S& b)
{
return value(a) < value(b);
}

and then sort by:

sort(a.begin(), a.end(), lessThan);

All trivial stuff, but I have several different metrics or value()
functions if you will. I could copy and paste 100 times so I get 100
functions like:

bool lessThan42(const S& a, const S& b)
{
return value42(a) < value42(b);
}

but isn't there an easier way? Can't I make lessThan a template function
that takes the metric (value() function) as a template argument or some
other smart thing that will save me from all that copying and pasting?

/David
Oct 21 '05 #1
Share this Question
Share on Google+
11 Replies


P: n/a
Hi

David Rasmussen wrote:
All trivial stuff, but I have several different metrics or value()
functions if you will. I could copy and paste 100 times so I get 100
functions like:

bool lessThan42(const S& a, const S& b)
{
return value42(a) < value42(b);
}

but isn't there an easier way? Can't I make lessThan a template function
that takes the metric (value() function) as a template argument or some
other smart thing that will save me from all that copying and pasting?


Indeed, one possibility is

template<typename Acc>
struct my_less_cmp
{
Acc acc;
my_less_cmp(Acc acc = Acc())
: acc(acc)
{}

bool operator()(const S& a, const S& b)
{
return acc(a) < acc(b);
}
};

[...]

std::sort(a.begin(), a.end(), my_less_cmp<some_accessor>());

Markus
Oct 21 '05 #2

P: n/a
Hi again

Markus Moll wrote:
bool operator()(const S& a, const S& b)


Um... yes, of course...

bool operator()(const S& a, const S& b) const

Markus
Oct 21 '05 #3

P: n/a
Markus Moll wrote:

Indeed, one possibility is

template<typename Acc>
struct my_less_cmp
{
Acc acc;
my_less_cmp(Acc acc = Acc())
: acc(acc)
{}

bool operator()(const S& a, const S& b)
{
return acc(a) < acc(b);
}
};

[...]

std::sort(a.begin(), a.end(), my_less_cmp<some_accessor>());


Okay, but then Acc/some_accessor will have to be a functor as well,
right? I mean, I can't just pass a function (pointer) as template argument?

/David
Oct 21 '05 #4

P: n/a

David Rasmussen wrote:
but isn't there an easier way? Can't I make lessThan a template function
that takes the metric (value() function) as a template argument or some
other smart thing that will save me from all that copying and pasting?


In addition to Markus's template solution, maybe a functor object may
help as well.

Something similar to this:

class test
{
public:
enum direction
{
ASCENDING,
DESCENDING
};

test( direction d = ASCENDING )
: d_( d )
{
}

bool operator() ( const int & a, const int & b )
{
if ( d_ == DESCENDING )
return a > b;

return a < b;
}

private:
direction d_;
};

....

sort( iv.begin(), iv.end(), test( test::DESCENDING ) );

Cheers,
Andre

Oct 21 '05 #5

P: n/a
Markus Moll wrote:

Indeed, one possibility is

template<typename Acc>
struct my_less_cmp
{
Acc acc;
my_less_cmp(Acc acc = Acc())
: acc(acc)
{}

bool operator()(const S& a, const S& b)
{
return acc(a) < acc(b);
}
};

[...]

std::sort(a.begin(), a.end(), my_less_cmp<some_accessor>());


Hmm. I don't understand how this could work.

My value functions are all of the form:

double value42(const S& s)
{
return bla bla bla;
}

double value67(const S& s)
{
return something else bla bla bla something else;
}

With your solution, I can't write:

std::sort(a.begin(), a.end(), my_less_cmp<value42>());

which is kind of what I want to do?

/David
Oct 21 '05 #6

P: n/a
Hi

David Rasmussen wrote:
Okay, but then Acc/some_accessor will have to be a functor as well,
right? I mean, I can't just pass a function (pointer) as template
argument?


Yes, you can. (Well, not exactly pass it as a template argument...)

int some_func(const S& s)
{
return s.x;
}

std::sort(a.begin(), a.end(), my_less_cmp<int (*)(const S&)>(some_func));

Markus

Oct 21 '05 #7

P: n/a
David Rasmussen wrote:
Markus Moll wrote:

Indeed, one possibility is

template<typename Acc>
struct my_less_cmp
{
Acc acc;
my_less_cmp(Acc acc = Acc()) : acc(acc)
{}

bool operator()(const S& a, const S& b)
{
return acc(a) < acc(b);
}
};

[...]

std::sort(a.begin(), a.end(), my_less_cmp<some_accessor>());


Hmm. I don't understand how this could work.

My value functions are all of the form:

double value42(const S& s)
{
return bla bla bla;
}

double value67(const S& s)
{
return something else bla bla bla something else;
}

With your solution, I can't write:

std::sort(a.begin(), a.end(), my_less_cmp<value42>());

which is kind of what I want to do?

/David

You can template on a function pointer, yes. That would go something like:
template <double (*fxn)(const int)>
bool compare_function(const int a, const int b) {
return (*fxn)(a) < (*fxn)(b);
}

If you want to template on the parameter to the function, you'll
probably have to say "template <typename T, double (*fxn)(T)>", and be
doomed to pass it the parameter type as well.
Oct 22 '05 #8

P: n/a
David Rasmussen wrote:

Okay, but then Acc/some_accessor will have to be a functor as well,
right? I mean, I can't just pass a function (pointer) as template
argument?


Yes, you can. But a function object is usually faster.

Oct 22 '05 #9

P: n/a
Rolf Magnus wrote:
David Rasmussen wrote:
Okay, but then Acc/some_accessor will have to be a functor as well,
right? I mean, I can't just pass a function (pointer) as template
argument?


Yes, you can. But a function object is usually faster.


How come?

/David
Oct 22 '05 #10

P: n/a
David Rasmussen wrote:
Okay, but then Acc/some_accessor will have to be a functor as well,
right? I mean, I can't just pass a function (pointer) as template
argument?


Yes, you can. But a function object is usually faster.


How come?


Because the function is called directly instead of through a pointer. The
compilers that I know never inline functions called through a pointer. If
the comparison function is very short (and comparison functions tend to be
short), inlining can make a big difference.

Oct 22 '05 #11

P: n/a
Rolf Magnus wrote:

Because the function is called directly instead of through a pointer. The
compilers that I know never inline functions called through a pointer. If
the comparison function is very short (and comparison functions tend to be
short), inlining can make a big difference.


I suspected an answer along those lines. Thanks.

/David
Oct 22 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.