Assigning a new value to a iterator of a intrusive container

278 views Asked by At

While working boost intrusive container splay_set, i have to reset local iterator member variables. Please see sample code below -

#include <boost/intrusive/splay_set.hpp>

using namespace boost::intrusive;

class Obj
{
    public:
        Obj(){};
        ~Obj(){};

        boost::intrusive::list_member_hook<boost::intrusive::link_mode<boost::intrusive::normal_link> > m_memberHook;
    private:
        int a;
};

typedef splay_set<Obj, compare<greater<Obj> >, member_hook<Obj, 
                splay_set_member_hook<boost::intrusive::link_mode<boost::intrusive::normal_link> >,
                &Obj::m_memberHook> > StorageSSet;
typedef StorageSSet::iterator   StorageSSetIter;

class Storage
{
    public:

        bool init(StorageSSet& sset)
        {
            // Error: "no match for operator= in ..."
            m_curIter = sset.begin();  ////<<<<------------- How to set new iterator
            m_endIter = sset.end();    ////<<<<------------- How to set new iterator
        }

    protected:

        StorageSSetIter     m_curIter;
        StorageSSetIter     m_endIter;
};

Intrusive container doesn't support assignment i suppose. I also cannot initialize splay_set iterator via member initializer list. There is so limited example on boost and other site. None gives clear answer to this question.

My question is what should i do to assign a new value to a splay_set iterator (and in general sense to a intrusive container.)

1

There are 1 answers

4
sehe On BEST ANSWER

The reason why you get const_iterators mostly is because modifying fields may break container invariants.

E.g. when building a set across elements of struct { int key; std::string value; };, modifying the key field through the iterator would lead to [Undefined Behaviour]

The clean way to update things would be to first remove, then reinsert the modified item.

If this really hurts performance too badly

  1. reconsider your design (consider mutable members for non-key fields, consider including the non-key data by reference)
  2. punch a hole in the abstraction by using const_cast<> to cast away the const. DANGER Don't pass this reference to any other party, because they will break the container invariants since they might not know to leave the key fields alone