I have trouble describing my problem so I'll give an example:
I have a class description that has a couple of variables in it, for example:
class A{
float a, b, c, d;
}
Now, I maintain a vector<A>
that contains many of these classes. What I need to do very very often is to find the object inside this vector that satisfies that one of it's parameters is maximal w.r.t to the others. i.e code looks something like:
int maxi=-1;
float maxa=-1000;
for(int i=0;i<vec.size();i++){
res= vec[i].a;
if(res > maxa) {
maxa= res;
maxi=i;
}
}
return vec[maxi];
However, sometimes I need to find class with maximal a
, sometimes with maximal b
, sometimes the class with maximal 0.8*a + 0.2*b
, sometimes I want a maximal a*VAR + b
, where VAR
is some variable that is assigned in front, etc. In other words, I need to evaluate an expression for every class, and take the max
. I find myself copy-pasting this everywhere, and only changing the single line that defines res
.
Is there some nice way to avoid this insanity in C++? What's the neatest way to handle this?
Thank you!
Sample of using max_element/min_element with custom functor
You could use the
std::max_element
STL algorithm providing a custom comparison predicate each time.With C++0x you can even use a lambda function for it for maximum conciseness:
I know this thread is old, but i find it quite useful to implement a powerful argmax function in C++.
However, as far as i can see, all the given examples above rely on std::max_element, which does comparison between the elements (either using a functor or by calling the operator<). this can be slow, if the calculation for each element is expensive. It works well for sorting numbers and handling simple classes, but what if the functor is much more complex? Maybe calculating a heuristic value of a chess position or something else that generate a huge tree etc.
A real argmax, as the thread starter mentioned, would only calculate its arg once, then save it to be compared with the others.
EDIT: Ok i got annoyed and had too much free time, so i created one < C++11 and one C++11 version with r-value references, first the C++11 version:
The non C++11 version is much simpler, only the template:
Note that neither version requires any template arguments, the only requirement is that the heuristic implements the unary_function class
This is what functors and STL are made for:
You can use the
std::max_element
algorithm with a custom comparator.It's easy to write the comparator if your compiler supports lambda expressions.
If it doesn't, you can write a custom comparator functor. For the simple case of just comparing a single member, you can write a generic "member comparator" function object, which would look something like this:
used as:
Is the expression always linear? You could pass in an array of four coefficients. If you need to support arbitrary expressions, you'll need a functor, but if it's just an affine combination of the four fields then there's no need for all that complexity.