tags:

views:

52

answers:

4

Consider a class A having a member x and a std::vector< A >. Now its a common task to search for the maximal x among all elements inside the vector. Clearly I can only use std::max_element if there is an iterator on the x's. But I must write one by my own, or I just make a simple for loop.

maxSoFar = -std::numeric_limits< double >::max();
for( std::vector< A >::const_iterator cit = as.begin(); cit != as.end(); ++cit )
{
  if( cit->x > maxSoFar )
    maxSoFar = cit->x;
}

but it's so tedious, and I am so lazy.. Is there a better option?

+1  A: 

1) Change the 1st line to this :

maxSoFar = *(as.begin());

2) Implement a custom comparator, and use max_element (as you wanted) : http://www.cplusplus.com/reference/algorithm/max_element/

VJo
+3  A: 

If you can use boost then you can write a lambda expression for the binary predicate expected by max_element:

struct A
{
    A(int n): x(n)
    {
    }
    int x;
};

using namespace std;
using namespace boost::lambda;

int main()
{
    vector<A> as;
    as.push_back(A(7));
    as.push_back(A(5));
    as.push_back(A(3));

    vector<A>::iterator iter = max_element(as.begin(), as.end(), bind(&A::x, _2) > bind(&A::x, _1));
    int max = iter->x;
}
Naveen
Very great, it works like a charm, and this is really a short cut. I think I should more dig into the boost::lambda stuff :D, esp. its bind magic, thanks.
brubelsabs
A: 

You can pass a comparator to max_element. And if your compiler supports lambdas(it probably does), this is easy:

std::max_element(as.begin(), as.end(),
    [](A a, A b){ return a.x < b.x; });
PigBen
we using several GCC's here: 4.4.3, 4.3.x, 4.2.x (Mac OSX), MS Visual Studio 2008, and MinGW which is essentially also some GCC IIRC. At least my 4.4.3 under Ubuntu 10.04 gives me the error: "expected primary-expression before ‘[’ token" So which compiler did you have in mind?
brubelsabs
GCC 4.5.x and MSVC 2010. Latest MinGW comes with 4.5
PigBen
A: 

Implement operator< in your class, the call:

maxSoFar =  *(std::max_element(as.begin(), as.end()));
Nim
I am not really fond of implementing `operator<` just so an algorithm will work. The common drawbacks are that the semantics might not be the expected in other circumstances and you cannot do that for more than a single member. Consider a vector of cities with distances from your own town and time zone, if you want to find the closest you would overload `operator<` to work on distances, if you want to work time zone statistics you would overload for time zone, but you cannot get both. For a city, the most sensible interpretation of smaller is population, any other thing would be surprising.
David Rodríguez - dribeas
@David: I agree that in the case of a city, operator< is meaningless, but given the example above, with a single integral member - why not? I think a good measure of common sense is required here and as long as you don't break any preconceived ideas that a user has about the object you're modeling, I personally don't see any harm... I like the idea of the boost lambda expression (proposed above), however, there is a slight overhead to using them vs. a simpler approach such as a functor or the operators..
Nim