Boost logo

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