f



user-defined iterator

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.

0
6/15/2007 2:18:55 PM
comp.lang.c++ 49148 articles. 1 followers. Post Follow

3 Replies
362 Views

Similar Articles

[PageSpeed] 41

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 


0
v.Abazarov (13256)
6/15/2007 3:02:29 PM
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
0
rpbg123 (870)
6/15/2007 3:15:35 PM
On Jun 15, 5:02 pm, "Victor Bazarov" <v.Abaza...@comAcast.net> 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: james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34

0
james.kanze (9769)
6/16/2007 9:18:25 AM
Reply: