igor.sol
igor.sol

Reputation: 647

Is there a standard wrapper class providing unified interface over iterator and reverse_iterator?

I need to implement a class which is able iterator over container in the direction specified by parameter to class' constructor. Say that parameter is called direction.

My class will have method which will sometimes increment iterator depending on additional conditions not related to this question.

So my idea is to declare member field of type X which can contain return value of container's begin() or rbegin() method. That member filed will be initialized in the constructor.

But the question is what is type of X. I think I can implement wrapper classes providing common interface via virtual functions. But maybe there is standard implementation in standard library or in Boost?

Update: my setup is very well matches the code provided by @Rabbid76 in his answer. I cannot alter interface of struct Iterator or remove this class. So my question is if it is possible to replace IteratorBase/IteratorImpl with something from standard libraries.

Upvotes: 2

Views: 157

Answers (1)

Rabbid76
Rabbid76

Reputation: 211219

What about that:

template < typename T >
struct IteratorBase
{
    using value_type = typename T::value_type;
    virtual value_type& val() = 0;
    virtual void next() = 0;
    virtual bool end( T &container ) = 0;
};

template < typename T, bool reverse = false >
struct IteratorTempl    : IteratorBase< T >
{
    IteratorTempl( T &container ) : m_it( container.begin() ) {}
    value_type& val() override { return *m_it; }
    void next() override { m_it ++; }
    bool end( T &container ) override { return m_it == container.end(); }
    typename T::iterator m_it;
};

template < typename T >
struct IteratorTempl< T, true > : IteratorBase< T >
{
    IteratorTempl( T &container ) : m_it( container.rbegin() ) {}
    value_type& val() override { return *m_it; }
    void next() override { m_it ++; }
    bool end( T &container ) override { return m_it == container.rend(); }
    typename T::reverse_iterator m_it;
};

template < typename T >
struct Iterator
{
    using value_type = typename T::value_type;
    Iterator( T &container,  bool reverse ) 
    {
        if ( reverse )
            m_it = new IteratorTempl<T, true>( container );
        else
            m_it = new IteratorTempl<T, false>( container );
    }
    ~Iterator(){ delete m_it; }
    value_type& val() { return m_it->val(); }
    void next() { m_it->next(); }
    bool end( T &container ) { return m_it->end( container ); }
    IteratorBase<T> *m_it;
};

#include <vector>

int main()
{
    std::vector<int> v{ 1,2,3,4,5 };

    for ( int i = 0; i < 2; i ++ )
    {
        Iterator< std::vector<int> > it( v, i!=0 );
        while ( !it.end(v) )
        {
            cout << it.val() << " ";
            it.next();
        }
    }
    return 0;
}

Upvotes: 2

Related Questions