|
Boost Users : |
Subject: [Boost-users] Multi-Index: custom iterator
From: Sensei (senseiwa_at_[hidden])
Date: 2014-08-25 09:48:12
Dear all,
I'm not yet satisfied with my MultiIndex games, so now I am trying to do
something that is purely cosmetic. However, I have *no idea* how I can
do this.
How can I build a custom iterator on a MultiIndex?
The objective is simple. As you may recall, I am building a MultiIndex
with 128 bits, indexing them by MSB, LSB, and HSB (in the middle). It
works like a charm.
Now I'd like to write something like this (or similar):
auto it = storage.myfind<byMSB>(MSB(value128bits));
for (; i != it.end(); i++)
In essence, I'd like to hide the get<> and everything I am using right
now (as shown below). So I need an iterator for this data structure:
typedef __uint128_t Storage;
// Indexing placeholders
struct byMSB { };
struct byHSB { };
struct byLSB { };
// Storage type with indexing
typedef boost::multi_index::multi_index_container<
Storage,
boost::multi_index::indexed_by<
// Hashed by subject/predicate/object
boost::multi_index::hashed_non_unique<boost::multi_index::tag<byMSB>,
boost::multi_index::global_fun<Storage, soSub, &Data::msb>>, // 0
boost::multi_index::hashed_non_unique<boost::multi_index::tag<byHSB>,
boost::multi_index::global_fun<Storage, soPre, &Data::hsb>>, // 1
boost::multi_index::hashed_non_unique<boost::multi_index::tag<byLSB>,
boost::multi_index::global_fun<Storage, soObj, &Data::lsb>> // 2
>
> DataStorage;
DataStorage storage_;
With your suggestions I've achieved to find all items by MSB, but
sincerely, now I don't know how to write a custom iterator for this type.
The code for finding elements is this:
//typedef typename DataStorage::template nth_index<0>::type
byHashedIndex;
//typedef typename DataStorage::template index<byMSB>::type
byHashedIndex;
//byHashedIndex &p = storage_.template get<byMSB>();
auto &p = storage_.template get<byMSB>();
auto q = p.equal_range(subject(v));
while (q.first != q.second)
{
std::cout << " EQID " << *(q.first) << " | " <<
msb(*(q.first)) << " | " << hsb(*(q.first)) << " | " << lsb(*(q.first))
<< std::endl;
l.push_back(*(q.first));
q.first++;
}
Note: I *have* written iterators, but they were much easier (for
instance char*). This is far too complex for making my way on my own!
From the code above, I guess I have begin() and end() point to an
equal_range output .first and .second. But what will the "pointer" I
need in the iterator will be?
Of course, my first attempt is a complete failure:
// Iterator
template <class T>
class iterator : public std::iterator<std::input_iterator_tag, Storage>
{
typedef typename DataStorage::template index<T>::type
byHashedIndex;
byHashedIndex &p;
// Default constructor
iterator() : p(storage_.get<T>()) { };
// Copy constructor
iterator(const iterator& i) : p(i.p) { };
// Pre-increment ++it
iterator& operator++() { ++p; return *this; };
// Post-increment it++
iterator operator++(int) {iterator tmp(*this); operator++();
return tmp; };
// Equality
bool operator==(const iterator& rhs) { return p == rhs.p; };
// Non-equality
bool operator!=(const iterator& rhs) { return p != rhs.p; };
// Access
Storage& operator*() { return *p; };
// Difference
iterator operator-(int i) { return iterator(p - i); };
// Addition
iterator operator+(int i) { return iterator(p + i); };
};
Can you point me in the right direction?
Thanks!
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net