STL list::iterator problem

J

jayesah

Hi All,

List and its iterator work as following way :

list<int> mylist;
list<int>::iterator itr;
itr = mylist.begin();
cout << (*itr);

But I want something like this:

list<int> mylist;
MyIterator itr(mylist);
cout<< (*itr);


So I wrote MyIterator following way :

template <class T> class MyIterator : public list<T>::iterator
{
public:
MyIterator() { };

~MyIterator() { };

MyIterator(list<T>& mylist) {

/* What I should write here */
};
};

int main()
{
list<int> mylist;
mylist.push_back(1);
mylist.push_back(2);

/* I want to support following construct */

MyIterator iter(mylist);
cout <<*mylist;

return 0;
}

Can anybody please guide me what I should write in one parameter
constructor ? Or do you have all together different solution ?

The reason I derived MyIterator from list<T>::iterator is that I want
to support all the overloaded operator that list<T>::iterator supports.

Thanks
Jayesh Shah
 
M

Markus Moll

Hi

List and its iterator work as following way :

list<int> mylist;
list<int>::iterator itr;
itr = mylist.begin();
cout << (*itr);

But I want something like this:

list<int> mylist;
MyIterator itr(mylist);
cout<< (*itr);

What is the difference? MyIterator will need to be some template, as
otherwise you cannot distinguish different element types. So it would
probably be MyIterator<int>. I can't see any difference to
list<int>::iterator.

Markus
 
K

Kai-Uwe Bux

Hi All,

List and its iterator work as following way :

list<int> mylist;
list<int>::iterator itr;
itr = mylist.begin();
cout << (*itr);

But I want something like this:

list<int> mylist;
MyIterator itr(mylist);
cout<< (*itr);

Why? Looks like a BadIdea(tm) to me.


So I wrote MyIterator following way :

template <class T> class MyIterator : public list<T>::iterator

Note: there is no guarantee that list<T>::iterator is inheritable. However,
this will not be a problem in practice since, as far as I know, all widely
used implementations implement list<>::iterator as a class without
finalizing trickery.

{
public:
MyIterator() { };

~MyIterator() { };

MyIterator(list<T>& mylist) {

/* What I should write here */
};

You need to construct the base:

MyIterator ( list<T> & mylist )
: list<T>::iterator( mylist.begin() )
{}

(untested)
};

int main()
{
list<int> mylist;
mylist.push_back(1);
mylist.push_back(2);

/* I want to support following construct */

MyIterator iter(mylist);
cout <<*mylist;

return 0;
}

And how do you intend to use these iterators in a loop:

MyIterator itr ( mylist );
while ( itr != ??? ) {
...
++itr;
}

Can anybody please guide me what I should write in one parameter
constructor ? Or do you have all together different solution ?

Yes: use mylist.begin() and mylist.end().

[snip]


Best

Kai-Uwe Bux
 
E

eriwik

Hi All,

List and its iterator work as following way :

list<int> mylist;
list<int>::iterator itr;
itr = mylist.begin();
cout << (*itr);

But I want something like this:

list<int> mylist;
MyIterator itr(mylist);
cout<< (*itr);

I'll admit that I have not tested this but I'm quite sure that
STL-iterators have a copy-constructor so something like this ought to
work:

#include <list>
#include <iostream>

typedef MyList std::list<int>
typedef MyIterator std::list<int>::iterator

MyList l;
MyIterator itr(l.begin());
std::cout << *itr;
template <class T> class MyIterator : public list<T>::iterator
{
public:
MyIterator() { };

~MyIterator() { };

MyIterator(list<T>& mylist) {

/* What I should write here */
};

};

If you realy want to do it your way I think you need to initialize the
base of your derived class like this (again, untested):

#include <list>
#include <iostream>

template <class T> class MyIterator : public list<T>::iterator
{
MyIterator (std::list<T>& l)
: std::list<T>::iterator(l.begin())
{ };
};

int main()
{
std::list<int> l;
l.push_back(2);
MyIterator<int> iter(l);
std::cout << *iter;
return 0;
}

Notice the template parameter, like Markus pointed out, when creating
an instance of the MyIterator-class.
 
D

Daniel T.

Hi All,

List and its iterator work as following way :

list<int> mylist;
list<int>::iterator itr;
itr = mylist.begin();
cout << (*itr);

But I want something like this:

list<int> mylist;
MyIterator itr(mylist);
cout<< (*itr);

Why? What problem does this solve? I can understand writing algorithms
that take whole containers rather than 'begin' and 'end' but this? I
don't get it.
So I wrote MyIterator following way :

template <class T> class MyIterator : public list<T>::iterator
{
public:
MyIterator() { };

~MyIterator() { };

MyIterator(list<T>& mylist) {

/* What I should write here */
};
};

int main()
{
list<int> mylist;
mylist.push_back(1);
mylist.push_back(2);

/* I want to support following construct */

MyIterator iter(mylist);
cout <<*mylist;

return 0;
}

Can anybody please guide me what I should write in one parameter
constructor ? Or do you have all together different solution ?

The reason I derived MyIterator from list<T>::iterator is that I want
to support all the overloaded operator that list<T>::iterator supports.

What about all the other iterators? Anything you write in MyIterator
should work just as well with any other bi-directional iterator yet you
only derived from list<T>::iterator. That seems quite limiting.

I have an idea though...

template < typename Con >
class MyIterator
{
Con& container;
typename Con::iterator pos;
public:
typedef typename Con::reference reference;

MyIterator( Con& c ): container( c ), pos( c.begin() ) { }

reference operator*() {
return *pos;
}
};

int main() {
list<int> myList;
MyIterator<list<int> > itr( myList );
cout << (*itr);
}
 
J

Jim Langston

Hi All,

List and its iterator work as following way :

list<int> mylist;
list<int>::iterator itr;
itr = mylist.begin();
cout << (*itr);

But I want something like this:

list<int> mylist;
MyIterator itr(mylist);
cout<< (*itr);


So I wrote MyIterator following way :

template <class T> class MyIterator : public list<T>::iterator
{
public:
MyIterator() { };

~MyIterator() { };

MyIterator(list<T>& mylist) {

/* What I should write here */
};
};

int main()
{
list<int> mylist;
mylist.push_back(1);
mylist.push_back(2);

/* I want to support following construct */

MyIterator iter(mylist);
cout <<*mylist;

return 0;
}

Can anybody please guide me what I should write in one parameter
constructor ? Or do you have all together different solution ?

The reason I derived MyIterator from list<T>::iterator is that I want
to support all the overloaded operator that list<T>::iterator supports.

Thanks
Jayesh Shah

I think the problem you're going to run into is that mylist really doesn't
know what it is. That is, you really want:
MyIterator iter(mylist);
to expand to
MyIterator iter(list<int>);
or the like (although that above won't compile I"m sure).

I understand why you want to do this, and it would be nice, but I really
don't think it's possible The way I deal with it is by using typedef.

typedef list<int> DataList;

DataList MyList;
DataList::iterator it = MyList.begin();
std::cout << (*itr);

I don't really think you can generically create an iterator off a generic
container. It would be nice if you could, but still, what if it's a map?
Then you have .first() and .second() which a list doesn't have, etc...
 
J

jayesah

Kai-Uwe Bux said:
Hi All,

List and its iterator work as following way :

list<int> mylist;
list<int>::iterator itr;
itr = mylist.begin();
cout << (*itr);

But I want something like this:

list<int> mylist;
MyIterator itr(mylist);
cout<< (*itr);

Why? Looks like a BadIdea(tm) to me.


So I wrote MyIterator following way :

template <class T> class MyIterator : public list<T>::iterator

Note: there is no guarantee that list<T>::iterator is inheritable. However,
this will not be a problem in practice since, as far as I know, all widely
used implementations implement list<>::iterator as a class without
finalizing trickery.

{
public:
MyIterator() { };

~MyIterator() { };

MyIterator(list<T>& mylist) {

/* What I should write here */
};

You need to construct the base:

MyIterator ( list<T> & mylist )
: list<T>::iterator( mylist.begin() )
{}

(untested)
};

int main()
{
list<int> mylist;
mylist.push_back(1);
mylist.push_back(2);

/* I want to support following construct */

MyIterator iter(mylist);
cout <<*mylist;

return 0;
}

And how do you intend to use these iterators in a loop:

MyIterator itr ( mylist );
while ( itr != ??? ) {
...
++itr;
}

Can anybody please guide me what I should write in one parameter
constructor ? Or do you have all together different solution ?

Yes: use mylist.begin() and mylist.end().

[snip]


Best

Kai-Uwe Bux

Thanks a lot Bux.
You said there is no guarantee that list<T>::iterator is inheritable.
Is it defined in spec ?
How come you implement a iterator without the class since you have lots
of operator to overload ?
 
K

Kai-Uwe Bux

Thanks a lot Bux.
You said there is no guarantee that list<T>::iterator is inheritable.
Is it defined in spec ?

By "spec" you mean the C++ standard? No, it's not defined in the standard.
That's why there is no guarantee. The type list<T>::iterator is marked
as "implementation defined".

For std::vector<T>, for instance, an implementation is free to use T* as an
iterator. In that case, std::vector<T>::iterator would not be a class.

For std::list<T>, an implementation is free to use trickery (using virtual
base classes) to prevent inheritance. (Although, to my knowledge, no
implementation actually does that.)

How come you implement a iterator without the class since you have lots
of operator to overload ?

Huh? I do not understand, and I think that sentence just does not parse. I
am not a native speaker of English, so my parser has little tolerance and
is very limited with regard to error correction.


Best

Kai-Uwe Bux
 
J

jayesah

Daniel said:
Why? What problem does this solve? I can understand writing algorithms
that take whole containers rather than 'begin' and 'end' but this? I
don't get it.


What about all the other iterators? Anything you write in MyIterator
should work just as well with any other bi-directional iterator yet you
only derived from list<T>::iterator. That seems quite limiting.

I have an idea though...

template < typename Con >
class MyIterator
{
Con& container;
typename Con::iterator pos;
public:
typedef typename Con::reference reference;

MyIterator( Con& c ): container( c ), pos( c.begin() ) { }

reference operator*() {
return *pos;
}
};

int main() {
list<int> myList;
MyIterator<list<int> > itr( myList );
cout << (*itr);
}


Absolutely a brilliant solution.....

You suggested the usage as :
MyIterator<list<int> > itr( myList );

But I want to use as

MySlistIterator itr(list); // I can not change this usage

So what I thought is

template<class T> typedef MyIterator<list< T > > MySlisIterator<T>;

but this is not supported in c++..what can be the alternative ??

Thanks a lot again..........
 
D

Daniel T.

You suggested the usage as :
MyIterator<list<int> > itr( myList );

But I want to use as

MySlistIterator itr(list); // I can not change this usage

Why? What problem does this solve?
 
D

Daniel T.

I am replacing existing code, which has the syntax, I described.

And you have to maintain the same interface? In that case, show me the
interface of MySlistIterator and I'll see if I can help.
 
J

jayesah

Daniel said:
And you have to maintain the same interface? In that case, show me the
interface of MySlistIterator and I'll see if I can help.


MySlistIterator itr(list);

while( itr() )
{
cout << *itr;

}
 
D

Daniel T.

MySlistIterator itr(list);

while( itr() )
{
cout << *itr;
}

That isn't an interface. What are the public member-functions that
MySlistIterator must support? What does the existing MySlistIterator
class look like?

class MySlistIterator
{
public:
// what's here?
};
 
J

jayesah

Daniel said:
That isn't an interface. What are the public member-functions that
MySlistIterator must support? What does the existing MySlistIterator
class look like?

class MySlistIterator
{
public:
// what's here?
};

MySlistIterator is implemented in a custom library which source code is
not available. Thats why I have only the usage interface and nothing
much.

So I planned to create a iterator class for each collection. But I
liked your solution: one iterator for all collection. Unfortunately I
am not allowed to change the existing source code, and template typedef
syntax is not supported in C++, I am not able to use your solution.
 
D

Daniel T.

MySlistIterator is implemented in a custom library which source code
is not available. Thats why I have only the usage interface and
nothing much.

I'm not asking for the source code. Post the class definition from the
header.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top