user-defined iterator

Discussion in 'C++' started by vasili, Jun 15, 2007.

  1. vasili

    vasili Guest

    hello All,

    I have a simple issue.
    I defined a custom container, that encloses a std::list, which in turn
    holds objects that are a simple abstraction of a six position array.

    Now, i would like to serialize the whole newly-defined container, in
    order to copy the contents to another array. So i thought to define an
    iterator which represented a "pointer" to the container's data. But,
    when i feed these iterators to std::copy the compiler complains about
    a lot of types which are defined when a std::iterator is instanced.

    the code:

    //i leave all unnecessary stuff out just to be clear
    #include <list>

    using namespace std;

    class SixBytes{
    public: //i don't trash the example with any accessor methods
    char m_data[6];
    };

    class MyCont{
    list<SixBytes> m_list;
    public:
    class Iterator{
    const MyCont& m_cont;
    int m_index;
    public:
    Iterator(const MyCont& cnt, int index=0):m_cont(cnt),
    m_index(index){}
    Iterator operator++(int){//postfix? just placed this
    and the following methods to be "complete" //
    w.r.t. the requirements of the std::copy algorithm and to this example
    Iterator ret(*this);
    m_index++;
    return ret;
    }
    Iterator& operator++(){//prefix?
    m_index++;
    return *this;
    }
    char operator*(){
    //...return the byte that corresponds to the
    position m_
    index
    }
    };

    inline Iterator begin() const{ return Iterator(*this); }//the
    start of the serialization
    inline const Iterator end() const { return Iterator(*this,
    m_list.size()*6); }//it's end
    MyCont(){ m_list.push_back(SixBytes());
    m_list.push_back(SixBytes());}
    };

    int main(){
    char data[13];
    data[0] = 2;
    MyCont m;
    std::copy(m.begin(), m.end(), data+1);
    }//example ends here

    giving this to the compiler i get this:

    /usr/lib/gcc/i586-mandrake-linux-gnu/3.4.1/../../../../include/c++/
    3.4.1/bits/stl_iterator_base_types.h: In instantiation of
    `std::iterator_traits<MyCont::Iterator>':
    /usr/lib/gcc/i586-mandrake-linux-gnu/3.4.1/../../../../include/c++/
    3.4.1/bits/stl_algobase.h:305: instantiated from `_OutputIterator
    std::__copy_ni2(_InputIterator, _InputIterator, _OutputIterator,
    __false_type) [with _InputIterator = MyCont::Iterator, _OutputIterator
    = char*]'
    /usr/lib/gcc/i586-mandrake-linux-gnu/3.4.1/../../../../include/c++/
    3.4.1/bits/stl_algobase.h:327: instantiated from `_OutputIterator
    std::__copy_ni1(_InputIterator, _InputIterator, _OutputIterator,
    __false_type) [with _InputIterator = MyCont::Iterator, _OutputIterator
    = char*]'
    /usr/lib/gcc/i586-mandrake-linux-gnu/3.4.1/../../../../include/c++/
    3.4.1/bits/stl_algobase.h:358: instantiated from `_OutputIterator
    std::copy(_InputIterator, _InputIterator, _OutputIterator) [with
    _InputIterator = MyCont::Iterator, _OutputIterator = char*]'
    container.cpp:41: instantiated from here
    /usr/lib/gcc/i586-mandrake-linux-gnu/3.4.1/../../../../include/c++/
    3.4.1/bits/stl_iterator_base_types.h:129: error: no type named
    `iterator_category' in `class MyCont::Iterator'

    ....more ot those errors about value_type and all such things.

    Do i have to provide my implementation with these types?
    If yes, what about iterator_categoy?
    What about the simple char* parameters given to the std::copy
    algorithm ? why are they ok?

    thank you all,
    vasilis.
     
    vasili, Jun 15, 2007
    #1
    1. Advertising

  2. vasili wrote:
    > I have a simple issue.


    :)

    > I defined a custom container, that encloses a std::list, which in turn
    > holds objects that are a simple abstraction of a six position array.
    >
    > Now, i would like to serialize the whole newly-defined container, in
    > order to copy the contents to another array. So i thought to define an
    > iterator which represented a "pointer" to the container's data. But,
    > when i feed these iterators to std::copy the compiler complains about
    > a lot of types which are defined when a std::iterator is instanced.


    Since you want to use standard algorithm, it _may_ require that you
    specialize 'iterator_traits' for your custom iterator.

    >
    > the code:
    >
    > //i leave all unnecessary stuff out just to be clear
    > #include <list>
    >
    > using namespace std;
    >
    > class SixBytes{
    > public: //i don't trash the example with any accessor methods
    > char m_data[6];
    > };
    >
    > class MyCont{
    > list<SixBytes> m_list;
    > public:
    > class Iterator{
    > const MyCont& m_cont;
    > int m_index;
    > public:
    > Iterator(const MyCont& cnt, int index=0):m_cont(cnt),
    > m_index(index){}
    > Iterator operator++(int){//postfix? just placed this
    > and the following methods to be "complete" //
    > w.r.t. the requirements of the std::copy algorithm and to this example
    > Iterator ret(*this);
    > m_index++;
    > return ret;
    > }
    > Iterator& operator++(){//prefix?
    > m_index++;
    > return *this;
    > }
    > char operator*(){
    > //...return the byte that corresponds to the
    > position m_
    > index
    > }
    > };
    >
    > inline Iterator begin() const{ return Iterator(*this); }//the
    > start of the serialization
    > inline const Iterator end() const { return Iterator(*this,
    > m_list.size()*6); }//it's end
    > MyCont(){ m_list.push_back(SixBytes());
    > m_list.push_back(SixBytes());}
    > };
    >
    > int main(){
    > char data[13];
    > data[0] = 2;
    > MyCont m;
    > std::copy(m.begin(), m.end(), data+1);
    > }//example ends here
    >
    > giving this to the compiler i get this:
    >
    > /usr/lib/gcc/i586-mandrake-linux-gnu/3.4.1/../../../../include/c++/
    > 3.4.1/bits/stl_iterator_base_types.h: In instantiation of
    > `std::iterator_traits<MyCont::Iterator>':

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    That's the implicit specialisation the compiler attempts. And fails.

    > [..]
    >
    > Do i have to provide my implementation with these types?


    Yes, if you want your code to compile.

    > If yes, what about iterator_categoy?


    Yes

    > What about the simple char* parameters given to the std::copy
    > algorithm ? why are they ok?


    Yes, because the standard library most likely already contains the
    specialisation of 'itetator_traits' for built-in pointer types.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Jun 15, 2007
    #2
    1. Advertising

  3. On Fri, 15 Jun 2007 07:18:55 -0700, vasili wrote:
    >I have a simple issue.


    If it were simple it wouldn't be C++.

    >I defined a custom container, that encloses a std::list, which in turn
    >holds objects that are a simple abstraction of a six position array.


    AFAICS, you want to iterate over the list _and_ the 'six position
    array' with a new iterator (not just re-use the
    list<SixBytes>::iterator). In this case you need to define your own
    iterator with all required typedefs and functions. Look for 'custom
    STL iterator', e.g.
    http://www.stanford.edu/class/cs107l/handouts/02-Custom-Iterators.pdf
    http://www.oonumerics.org/tmpw00/becker.html


    --
    Roland Pibinger
    "The best software is simple, elegant, and full of drama" - Grady Booch
     
    Roland Pibinger, Jun 15, 2007
    #3
  4. vasili

    James Kanze Guest

    On Jun 15, 5:02 pm, "Victor Bazarov" <> wrote:
    > vasili wrote:
    > > I have a simple issue.


    > :)


    It takes a complicated language to solve complicated
    problems:).

    > > I defined a custom container, that encloses a std::list, which in turn
    > > holds objects that are a simple abstraction of a six position array.


    > > Now, i would like to serialize the whole newly-defined container, in
    > > order to copy the contents to another array. So i thought to define an
    > > iterator which represented a "pointer" to the container's data. But,
    > > when i feed these iterators to std::copy the compiler complains about
    > > a lot of types which are defined when a std::iterator is instanced.


    > Since you want to use standard algorithm, it _may_ require that you
    > specialize 'iterator_traits' for your custom iterator.


    He must do something to ensure that iterator_traits<Iterator>
    contains the proper typedefs. The generic implementation of
    this template supposes that there are corresponding typedef's in
    the Iterator class; the standard library also contains a partial
    specialization for pointers (since pointers obviously don't
    contain the necessary typedef's). He can thus either provide a
    custom specialization, with the necessary typedef's, or put the
    typedef's in his class. The latter is the classical solution,
    and the standard offers a class template, std::iterator, to help
    here. All he has to do is have his iterator derive (publicly)
    from the appropriate instantiation of std::iterator, and it
    should suffice.

    --
    James Kanze (Gabi Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 16, 2007
    #4
    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. Hendrik Maryns
    Replies:
    18
    Views:
    1,452
  2. Brett L. Moore
    Replies:
    3
    Views:
    1,983
    Glen Low
    Jul 15, 2003
  3. greg
    Replies:
    6
    Views:
    475
    Dietmar Kuehl
    Jul 17, 2003
  4. Oodini
    Replies:
    1
    Views:
    1,818
    Keith Thompson
    Sep 27, 2005
  5. Replies:
    1
    Views:
    530
    Sion Arrowsmith
    Jul 10, 2008
Loading...

Share This Page