You should probably just use std::find
from <algorithm>
, together with reverse iterators from the first index:
unsigned long searchByTimestamp(Time_t timestamp)
{
auto& idIndex = myCont.get<0>();
auto itTime = std::find_if(
idIndex.rbegin(), idIndex.rend(),
[=](MyData const& item) { return item.timestamp == timestamp; }
);
if (itTime == idIndex.rend())
return 0;
return itTime->id;
}
Note: If you want to "project" a reverse iterator to a (forward) iterator, use .base()
on the reverse iterator.
See it Live On Coliru
Now, I don't really know what you needed the continue searching from the "current" position
funcitonality for (I mean, find either returns the match, or rend()
, so there would be nothing to continue for). However, otherwise, you could do stuff like (see it Live On Coliru as well :)
unsigned long searchByTimestamp(Time_t timestamp)
{
auto& idIndex = myCont.get<0>();
auto current = std::find_if(idIndex.rbegin(), idIndex.rend(),
[=](MyData const& item) { return item.timestamp >= timestamp; });
if (current != idIndex.rend())
{
bool some_extra_condition = current->timestamp == timestamp; // exact match?
if (some_extra_condition)
return current->id; // we have an exact match
} else
{
// otherwise look for the next item that has an id divisible by 3 (3,6,9,...)
auto alternative = std::find_if(current, idIndex.rend(),
[=](MyData const& item) { return (item.id % 3) == 0; });
if (alternative != idIndex.rend())
return alternative->id;
}
return 0;
}
I made up fully silly examples of 'alternative' matching predicates. As you can see, it's all run-of-the-mill STL algorithm usage. This is possible due to algorithms being decoupled from containers by way of iterators.
Full Code
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
using namespace boost::multi_index;
static int idgen = 0;
enum Time_t { last_month, last_week, yesterday, today, tomorrow };
std::ostream& operator<<(std::ostream& os, Time_t tt) {
switch(tt)
{
case last_month: return os << "last_month";
case last_week: return os << "last_week";
case yesterday: return os << "yesterday";
case today: return os << "today";
case tomorrow: return os << "tomorrow";
default: return os << "?";
};
}
struct MyData
{
int id = ++idgen;
MyData(Time_t timestamp) : timestamp(timestamp) {}
Time_t timestamp;
friend std::ostream& operator<<(std::ostream& os, MyData const& md)
{
return os << "(id:" << md.id << ", timestamp:" << md.timestamp << ")";
}
};
typedef multi_index_container<
MyData,
indexed_by<
random_access<>, // keep insertion order
ordered_non_unique< member<MyData, Time_t, &MyData::timestamp> >
>
> myContType;
typedef myContType::nth_index<1>::type myContType_by_time;
myContType myCont;
unsigned long searchByTimestamp(Time_t timestamp)
{
auto& idIndex = myCont.get<0>();
auto itTime = std::find_if(
idIndex.rbegin(), idIndex.rend(),
[=](MyData const& item) { return item.timestamp == timestamp; }
);
if (itTime == idIndex.rend())
return 0;
return itTime->id;
}
#include <iostream>
int main()
{
myCont.emplace_back(Time_t(last_week));
myCont.emplace_back(Time_t(tomorrow));
myCont.emplace_back(Time_t(last_month));
myCont.emplace_back(Time_t(yesterday));
std::cout << "Insertion order:\n";
for (auto const& item : myCont)
std::cout << item << "\n";
std::cout << searchByTimestamp(today) << "\n";
std::cout << searchByTimestamp(last_month) << "\n";
}