foraidt
foraidt

Reputation: 5709

rbegin() of a boost::iterator_range

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_facadeand 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

Answers (1)

Dave S
Dave S

Reputation: 21123

  1. 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.

  2. 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

Related Questions