Reputation: 5709
I refactored a class that used a single list of elements so it now uses a list of such lists.
To minimize the changes in derived classes, I implemented a custom iterator
using boost::iterator_facade
and also a method to get a boost::iterator_range<iterator>
that can be used for iterating instead of the original list.
This appears to work except in one place where rbegin()
is used. boost::iterator_range
does not appear to support something like that.
What would be a simple way of getting the range's last element?
I'm using VS2008 SP1, i.e. only some C++11 support in std::tr1, and boost is obviously available, too.
typedef std::deque<MyData> DataList;
class MyClass : private boost::noncopyable
{
public:
void AppendData(DataList* newData
private:
typedef std::deque<DataList*> ListOfDatatLists;
/**
* Custom iterator.
* The content is not meant to be modified so this iterator operates on const lists only.
*/
class iterator
: public boost::iterator_facade <
iterator,
MyData,
boost::forward_traversal_tag // Only forward iteration necessary
>
{
public:
static boost::iterator_range<iterator> range(const ListOfDataLists * pListOfLists);
private:
friend class boost::iterator_core_access;
iterator(const ListOfDataLists * pListOfLists = NULL) : m_pListOfLists(pListOfLists) {}
/// \name Implementations for boost base class
//{@
bool equal(iterator const & other) const;
MyData & dereference() const;
void increment();
difference_type distance_to(const iterator & other) const;
//@}
const ListOfDataLists * m_pListOfLists;
ListOfDataLists::const_iterator m_listIt; ///< The current list of data items
DataList::const_iterator m_dataIt; ///< An iterator of the current list
};
ListOfResultLists m_dataLists;
protected:
typedef std::tr1::shared_ptr<CLockedResults> SpLockedResults;
/// For use by derived classes instead of the former single list
boost::iterator_range<iterator> GetData() const;
};
Upvotes: 0
Views: 853
Reputation: 21123
One solution, if possible, is to allow bidirectional or random access traversal. This would allow you to get call range.end() --
(assuming the range isn't empty). This would also allow you to reverse the range using the reversed
boost range adaptor.
The other solution is to obtain the iterators from the range using begin()/end()
and using std::distance
to determine the distance between the two iterators. You could then use std::advance
the beginning iterator one less than the distance to move to the last element.
Upvotes: 2