Using different iterator types in subclasses without breaking theinheritance mechanism

Discussion in 'C++' started by Alfredo Di Napoli, Feb 17, 2012.

  1. Hi everyone!

    Lately I am facing a problem with templates and iterators, but first
    let me describe what I'm trying to do, so that my question is clearer.

    I have one common class, MemoryObj<T>, and every memory management
    class derive from it.

    Now, I need to define two different classes: a "buffer" and a
    "fundamental type". The first one, Buffer<T>, is a list of
    MemoryChunk<T> stored as a std::vector< MemoryChunk<T>* >, while
    Fundamental<T> is a wrapper to fundamental types (e.g., int, long,
    double, ...), and for compatibility, it inherits from MemoryObj<T>, as
    I already said.

    The hard part: I want to implement iterator support for these classes.
    So, I tried to add a simple iterator facility in my classes:



    template<typename T, class Iterator = typename
    std::vector<T>::iterator>
    class MemoryObj
    {
    public:
    typedef Iterator iterator;
    virtual Iterator begin() = 0;
    virtual Iterator end() = 0;
    private:
    };


    Then, my memory chunk class will simply use std::vector<T>::iterator
    to access its elements:



    template <typename T, class Iterator = typename
    std::vector<T>::iterator>
    class MemoryChunk: public MemoryObj<T, Iterator>
    {
    public:
    MemoryChunk(const std::vector<T>& vector): b_(vector) { }

    size_t const size() const { return b_.size(); }
    T& operator[](size_t i){ return b_; }
    const T& operator[](size_t i) const{ return b_; }

    typedef Iterator iterator;

    iterator begin() { return b_.begin(); }
    iterator end() { return b_.end(); }
    private:
    std::vector<T> b_;
    };


    And finally, my custom iterator for Buffer<T>:



    template <typename T>
    class BufferIterator: public std::vector<T>::iterator
    {
    public:
    BufferIterator() { /* Code */ }
    BufferIterator operator=( const BufferIterator& rhs ) { /* Code
    */ }

    BufferIterator static begin(std::vector<MemoryChunk<T>*>& v) { /*
    Code */ }
    BufferIterator static end(std::vector<MemoryChunk<T>*>& v) { /*
    Code */ }

    T& operator*() { /* Code */ }
    BufferIterator operator++(int) { /* Code */ }
    BufferIterator& operator++() { /* Code */ }
    BufferIterator operator+(const int n) { /* Code */ }
    bool operator!=(const BufferIterator& b) const { /* Code */ }
    private:
    int currentChunk_;
    int globalCounter_;
    int stepCounter_;
    T currentValue_;
    std::vector<MemoryChunk<T> *>* vec_;
    };

    template <typename T, class Iterator = BufferIterator<T> >
    class Buffer: public MemoryObj<T,Iterator>
    {
    public:
    Buffer() { }

    void push_back(MemoryChunk<T>& c) { chunks_.push_back(&c); }

    size_t const size() const
    {
    size_t s = 0;
    for (int i = 0; i < chunks_.size(); i++) {
    s += chunks_->size();
    }
    return s;
    }

    MemoryChunk<T>& chunks(size_t idx) { return *chunks_[idx]; }

    typedef Iterator iterator;

    iterator begin(){ return iterator::begin(chunks_); }
    iterator end(){ return iterator::end(chunks_); }
    private:
    std::vector<MemoryChunk<T>*> chunks_;
    };



    The iterators works fine... until I try to use functions that, as a
    generic as I want my code to be, take as argument a MemoryObj<T>&, and
    pass to these a Buffer<T>:



    template <typename T>
    void static genericFunction(MemoryObj<T>& obj)
    {
    typename MemoryObj<T>::iterator i = obj.begin();
    std::cout << "The generic value is: " << *(i) << std::endl;
    }

    int main()
    {
    //Data creation
    std::vector<int> v1(6,23);
    std::vector<int> v2(4,18);
    MemoryChunk<int> m1(v1);
    MemoryChunk<int> m2(v2);

    Buffer<int> b1;
    b1.push_back(m1); b1.push_back(m2);

    //Attempts with iterators over Buffer<T> work like a charm!
    Buffer<int>::iterator it = b1.begin();
    std::cout << "Simple access with operator* : ";
    for (int i = 0; i < b1.size(); i++) {
    int tmp = (*it);
    std::cout << tmp << " ";
    it++;
    }
    std::cout << std::endl;

    //Invoke a generic function HUGE FAILURE!
    std::cout << "Calling the generic function on MemoryChunk : " <<
    std::endl;
    genericFunction(m1); // This works just fine

    std::cout << "Calling the generic function on Buffer : " <<
    std::endl;
    genericFunction(b1); //---> THIS FAILS

    return 0;
    }


    Compiling the code, I get an error which I can't decrypt:

    candidate function [with T = int] not viable: no known conversion
    from 'Buffer<int>' to 'MemoryObj<int> &' for 1st argument [3]

    I suspect the problem is related to the BufferIterator, cause
    MemoryObj and MemoryChunk use a different iterator type (a
    std::vector<T>::iterator), so the compiler doesn't know how to perform
    the conversion. What am I doing wrong with my classes?

    I am puzzled by this, and any help will be deeply appreciated!

    You can download the source code on SourceForge at the following URL:

    http://sourceforge.net/p/laetus/code/132/tree/branches/buffer-iterators/laetus-iterators/iterators/


    Thanks a lot!
    Alfredo
    Alfredo Di Napoli, Feb 17, 2012
    #1
    1. Advertising

  2. Alfredo Di Napoli

    LR Guest

    Re: Using different iterator types in subclasses without breakingthe inheritance mechanism

    Alfredo Di Napoli wrote:
    > Hi everyone!


    > I have one common class, MemoryObj<T>, and every memory management
    > class derive from it.
    >
    > Now, I need to define two different classes: a "buffer" and a
    > "fundamental type". The first one, Buffer<T>, is a list of
    > MemoryChunk<T> stored as a std::vector< MemoryChunk<T>* >, while
    > Fundamental<T> is a wrapper to fundamental types (e.g., int, long,
    > double, ...), and for compatibility, it inherits from MemoryObj<T>, as
    > I already said.
    >
    > The hard part: I want to implement iterator support for these classes.
    > So, I tried to add a simple iterator facility in my classes:


    It's not clear to me how the code you posted solves your problem. I
    think it might be easier to take a class and add some typedefs including
    iterator and const_iterator and some begin and end methods.

    I don't think it will solve your problem, but you may want to chance this
    > template <typename T, class Iterator = BufferIterator<T> >
    > class Buffer: public MemoryObj<T,Iterator>


    to

    template<
    typename T,
    class BehaveLikeThisIterator = BufferIterator<T>,
    class InheritFromThisObject = MemoryObj<T,BehaveLikeThisIterator>
    >

    class Buffer: public InheritFromThisObject

    and put this in the class,

    typedef BehaveLikeThisIterator iterator;

    As I say, I don't think it will solve your problem, but it may point you
    in the right direction.


    And,
    > int main()


    change,
    >
    > Buffer<int> b1;


    to
    Buffer<int, std::vector<int>::iterator> b1;

    There will be a couple of other things to change.

    > You can download the source code on SourceForge at the following URL:
    >
    > http://sourceforge.net/p/laetus/code/132/tree/branches/buffer-iterators/laetus-iterators/iterators/


    I didn't look there. But this may be useful,
    http://www.parashift.com/c -faq-lite/how-to-post.html#faq-5.8

    HTH
    LR, Feb 17, 2012
    #2
    1. Advertising


  3. > It's not clear to me how the code you posted solves your problem.  I
    > think it might be easier to take a class and add some typedefs including
    > iterator and const_iterator and some begin and end methods.


    I need different iterators because a Buffer is an aggregation of
    MemoryChunk, so
    iterating over a Buffer means iterating over different MemoryChunk,
    each one physically
    stored in non contiguous portion of memory. So I need a specific
    iterator for the class.


    > > template <typename T, class Iterator = BufferIterator<T> >
    > > class Buffer: public MemoryObj<T,Iterator>

    >
    > to
    >
    > template<
    >     typename T,
    >     class BehaveLikeThisIterator = BufferIterator<T>,
    >     class InheritFromThisObject = MemoryObj<T,BehaveLikeThisIterator>
    >
    > class Buffer: public InheritFromThisObject
    >
    > and put this in the class,
    >
    >      typedef BehaveLikeThisIterator iterator;
    >
    > As I say, I don't think it will solve your problem, but it may point you
    > in the right direction.


    I can't figure out how your tips can solve problem, it seems to make
    it even more complex, though.

    >
    > And,
    >
    > > int main()

    >
    > change,
    >
    >
    >
    > >     Buffer<int> b1;

    >
    > to
    >       Buffer<int, std::vector<int>::iterator> b1;
    >
    > There will be a couple of other things to change.


    I can't change this, the Buffer iterator type must be a
    BufferIterator, it's a constraint of my domain.

    >
    > > You can download the source code on SourceForge at the following URL:

    >
    > >http://sourceforge.net/p/laetus/code/132/tree/branches/buffer-iterato...

    >
    > I didn't look there. But this may be useful,http://www.parashift.com/c -faq-lite/how-to-post.html#faq-5.8


    Sorry if I haven't adhered to the netiquette, but it's my first post
    on this group, and I thought that
    a properly highlighted code posted as a separate URL would have been
    better than a plain text email :)

    >
    > HTH


    Thanks anyway,
    A.
    Alfredo Di Napoli, Feb 17, 2012
    #3
  4. Alfredo Di Napoli

    LR Guest

    On Feb 17, 11:39 am, Alfredo Di Napoli <>
    wrote:


    > I can't change this, the Buffer iterator type must be a
    > BufferIterator, it's a constraint of my domain.


    Then maybe you can change genericFunction to something like:


    template <typename T, typename Iterator>
    void static someOtherGenericFunction(MemoryObj<T,Iterator> &obj)
    {}

    I think your problem is that Buffer inherits from
    MemoryObj<T,Iterator> but the Buffer's default Iterator template
    argument is not the same as MemoryObj<T>'s default Iterator template
    argument.

    IOW
    MemoryChunk<int> inherits from MemoryObj<int>
    MemoryObj<int> is MemoryObj<int,std::vector<int>::iterator>>
    but
    Buffer<int> inherits from MemoryObj<int,BufferIterator<int>>
    LR, Feb 17, 2012
    #4

  5. > template <typename T, typename Iterator>
    > void static someOtherGenericFunction(MemoryObj<T,Iterator> &obj)
    > {}
    >


    Thank you. The solution was so easy that I wonder how I couldn't think
    about it before.
    Regards,
    Alfredo
    Alfredo Di Napoli, Feb 19, 2012
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andrey Brozhko
    Replies:
    0
    Views:
    396
    Andrey Brozhko
    Dec 21, 2004
  2. Amy
    Replies:
    0
    Views:
    459
  3. Koen
    Replies:
    1
    Views:
    489
  4. Marcus Alanen
    Replies:
    1
    Views:
    318
    Alf P. Steinbach
    Sep 7, 2003
  5. Ulrich Hobelmann
    Replies:
    9
    Views:
    396
    Ulrich Hobelmann
    Jul 3, 2006
Loading...

Share This Page