stl predicate with different types
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.
精彩评论