views:

40

answers:

1

I have a container like this:

// Sort functor
struct SortByTime :
  std::binary_function<const TimeSortableData &, const TimeSortableData &, bool>
{
    bool operator()(const TimeSortableData & a, const TimeSortableData & b) const
    {
        return a.GetTime() < b.GetTime();
    }
};

// Container that sorts by time
typedef std::multiset<TimeSortableData, SortByTime> TimeSortedData;

Now if I want to get the last data object before time t, I could create a dummy object and call upper_bound():

TimeSortableData dummy(t);
TimeSortedData::const_iterator it = mySortedData.upper_bound(dummy);
--it;
// result = *it;

This gives me logarithmic search complexity.
Aside from looking clumsy, this approach is problematic if such a dummy object is very hard to create (not wrt. run-time performance but coding effort).

I've looked at std::multiset::key_comp but I don't see how I could use it..
Both std::multiset::find() and std::binary_search() want me to give them the container's key_type, i.e. TimeSortableData objects...

How can I search eficiently without having to create a dummy object?

Update from comments:
There is also find_if(): It would spare me the effort of creating a dummy object but at the price of O(n) complexity.

+3  A: 

I suppose that if your keys are so expensive to construct that you worry about creating a temporary dummy key, you can always change your code to use an std::multimap instead. Let the key be something cheap to construct, such as an integer or time_t or whatever GetTime() returns, and then the data_type could be the larger data.

typedef std::multimap<time_t, TimeSortableData> TimeSortedData;
TimeSortedData mySortedData;

...

time_t dummy = [whatever];
TimeSortedData::const_iterator it = mySortedData.upper_bound(dummy);
if (it != mySortedData.begin()) --it; // Check that iterator isn't at beginning
result = it->second;
Charles Salvia
@Charles I guess my first comment was a bit too early... Changing the container type breaks a lot of existing code and is impractical in my situation.
mxp
However, your suggestion appears to be the Right Thing to do. I'll accept it as answer but continue to use the crutch of constructing dummy objects...
mxp