开发者

stl predicate with different types

开发者 https://www.devze.com 2023-01-12 05:33 出处:网络
I have a vector of ordered container classes where I need to know the index of the container that has a given element

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 oper开发者_如何学编程ator()(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.


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.


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;


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


Your example is broken in several trivial ways: the class Container should be defined before FooAccDateComp in order for it to be used there, you should make myDate a public member of Container, access that member in the comparison method using .myDate rather than ->myDate, and finally decide whether to call your vector mystuff or events, but not mix both. I'll suppose that appropriate corrections have been made.

You should have defined your comparison function to take a Date parameter as first argument and a Container parameter as second; the opposite to what you did. Or you could use std::lower_bound instead of std::upper_bound if that would suit you purpose (since you don't say what you are going to do with index it is hard to tell) as the choice made in the question is adapted to that. Contrary to what the currently accepted answer says you do not need both if you are only using std::upper_bound or only std::lower_bound (though you would need both if using std::equal_range, or when using both std::upper_bound and std::lower_bound).

You can find these at first sight a bit strange specifications in the standard, but there is a way to understand without looking it up why they have to be like this. When using lower_bound, you want to find the point that separates the Container entries that are (strictly) less than your given Date from those that are not, and this requires calling the comparison function with that Date argument in second position. If however you ask for an upper_bound (as you are), you want to find the point that separates the entries that are not strictly greater than your given Date from those that are, and this requires calling the comparison function with that Date argument in first position (and negating the boolean result it returns). And for equal_range you of course need both possibilities.

0

精彩评论

暂无评论...
验证码 换一张
取 消