M
Michael Klatt
I am trying to write an iterator for a std::set that allows the
iterator target to be modified. Here is some relvant code:
template <class Set> // Set is an instance of std::set<>
class Iterator
{
public :
typedef typename Set::value_type T;
typedef typename Set::iterator SetIterator;
Iterator(Set& container, const SetIterator& it);
Iterator& operator=(const Iterator& rhs);
T& operator*() { return m_proxy; }
T* operator->() { return &m_proxy; }
Iterator& operator++();
~Iterator() { sync(); }
private :
void sync();
Set& m_container;
SetIterator m_iterator;
T m_proxy;
};
template <class Set>
Iterator<Set>::Iterator(Set& container, const SetIterator& it) :
m_container(container),
m_iterator(it)
m_proxy(*it) {}
template <class Set>
Iterator<Set>& Iterator<Set>:perator++()
{
sync();
++m_iterator;
return *this;
}
template <class Set>
Iterator<Set>& Iterator<Set>:perator=(const Iterator& rhs)
{
sync();
m_container = rhs.m_contaner;
m_iterator = rhs.m_iterator;
m_proxy = rhs.m_proxy;
return *this;
}
template <class Set>
void Iterator<Set>::sync()
{
typedef Set::key_compare Compare;
if (Compare(*m_iterator, m_proxy) || Compare(m_proxy, *m_iterator))
{
// sort order will be changed
container.erase(m_iterator);
m_iterator = container.insert(m_proxy);
}
else
{
// modify set element directly (should be faster than having to do
// an insert)
const_cast<T&>(*m_iterator) = m_proxy;
}
return;
}
Am I on the right track with this, or is this a really bad idea? One
concern I have is concurrency. If more than one iterator points to
the same element it is possible for that element to get out of sync.
iterator target to be modified. Here is some relvant code:
template <class Set> // Set is an instance of std::set<>
class Iterator
{
public :
typedef typename Set::value_type T;
typedef typename Set::iterator SetIterator;
Iterator(Set& container, const SetIterator& it);
Iterator& operator=(const Iterator& rhs);
T& operator*() { return m_proxy; }
T* operator->() { return &m_proxy; }
Iterator& operator++();
~Iterator() { sync(); }
private :
void sync();
Set& m_container;
SetIterator m_iterator;
T m_proxy;
};
template <class Set>
Iterator<Set>::Iterator(Set& container, const SetIterator& it) :
m_container(container),
m_iterator(it)
m_proxy(*it) {}
template <class Set>
Iterator<Set>& Iterator<Set>:perator++()
{
sync();
++m_iterator;
return *this;
}
template <class Set>
Iterator<Set>& Iterator<Set>:perator=(const Iterator& rhs)
{
sync();
m_container = rhs.m_contaner;
m_iterator = rhs.m_iterator;
m_proxy = rhs.m_proxy;
return *this;
}
template <class Set>
void Iterator<Set>::sync()
{
typedef Set::key_compare Compare;
if (Compare(*m_iterator, m_proxy) || Compare(m_proxy, *m_iterator))
{
// sort order will be changed
container.erase(m_iterator);
m_iterator = container.insert(m_proxy);
}
else
{
// modify set element directly (should be faster than having to do
// an insert)
const_cast<T&>(*m_iterator) = m_proxy;
}
return;
}
Am I on the right track with this, or is this a really bad idea? One
concern I have is concurrency. If more than one iterator points to
the same element it is possible for that element to get out of sync.