tags:

views:

75

answers:

3

I have a vector of ordered container classes where I need to know the index of the container that has a given element

so, I would like to do the following, but this obviously doesn't work. I could create a dummy Container to house the date to find, but I was wondering if there was a nicer way.

struct FooAccDateComp 
{
  bool operator()(const Container& d1, const MyDate&  f1) const 
  { return   d1->myDate < f1; } 
};

class Container
{
   MyDate myDate;
   ...
};

vector<Container> mystuff; 
MyDate temp(2008, 3, 15);

//add stuff to variable mystuff

int index = int(upper_bound(events.begin(), events.end(),temp, FooAccDateComp())-events.begin());

EDIT: The container class can contain other dates.

+1  A: 

You don't necessarily need a special predicate, just enable comparison between Container and MyDate.

#include <vector>

struct MyDate {
   MyDate(int, int, int);
};

struct Container {
   MyDate myDate;
};

// enable comparison between Container and MyDate
bool operator<(Container const&, MyDate const&);
bool operator==(Container const&, MyDate const&);

std::vector<Container> v; 
//add stuff to variable mystuff
MyDate temp(2008, 3, 15);
std::vector<Container>::iterator i = std::lower_bound(v.begin(), v.end(), temp);
ptrdiff_t index = i != v.end() && *i == temp ? i - v.begin() : -1;
Maxim Yegorushkin
A dedicate predicate is much better, really. Consider the case where you have several dates within the `Container`, which one would you compare to ?
Matthieu M.
Add complexity only if you need to. In this example it seems unnecessary.
Maxim Yegorushkin
@maxim, there are actually other dates in the container. I'll update the question
Steve
in this case you do need a functor
Maxim Yegorushkin
A: 

You can use find_if if you don't mind degrading performance (you said that you have a vector of sorted Container, so binary search would be faster) Or you can add

struct Container {
    MyDate myDate;
    operator MyDate () {return myDate}; 
}
bool operator <(MyDate  const&, MyDate const&)
{
  return // your logic here
};    

Now you can use binary search functions

std::vector<Container>::iterator i = std::upper_bound(v.begin(), v.end(), MyDateObject);

Surely, it will work only if your vector is sorted by Container.myDate

a1ex07
I assume you mean `operator MyDate()`. It's usually best to avoid conversion operators if you can; they can mask errors that would otherwise be caught by the compiler. Also, this gives an unnecessary copy on each comparison.
Mike Seymour
Yeah, my bad. It definitely should have been `operator MyDate()`. Fixed. Thanks for pointing this
a1ex07
+3  A: 

upper_bound needs to be able to evaluate expressions like Comp(date,container), but you've only provided Comp(container,date). You'll need to provide both:

struct FooAccDateComp 
{
    bool operator()(const Container& c, const MyDate& d) const 
        { return c.myDate < d; } 

    bool operator()(const MyDate& d, const Container& c) const 
        { return d < c.myDate; } 
};

Remember that the vector must be sorted according to this comparison for upper_bound and friends to work.

Mike Seymour
Gasp, you've been faster :p I just wanted to add that `upper_bound` doesn't necessarily returns `Container` with the given date, it returns the first element with a date equals OR GREATER. You'll need to test, afterwards, if you reached the end and (if not) if the date is effectively what you wanted (there might not be such container in the vector).
Matthieu M.
Steve
@Steve: I did a quick test with GCC before answering, and all was fine. I don't have a copy of VS available, I'm afraid.
Mike Seymour