C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Generic object with a member whose type is the iterator type

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
rawhide
Guest





PostPosted: Mon Jul 03, 2006 1:36 am    Post subject: Generic object with a member whose type is the iterator type Reply with quote



I started working on a custom container class which would hold objects
which have iterators back to the container. I can't figure out how to
write it, not that its even possible. Here is uncompilable code which
illustrates the problem.

template <class T, class I>
class Item
{
T object_;
I iterator_;//this is the iterator back into the Item's container
};

template<class T>
class Container
{
//impossible to compile yet illustrates my conundrum
typedef Item<T, ContainerType::iterator> ItemType;
typedef std::list<ItemType> ContainerType;

ContainerType container_;
};

If possible, how can I get Item to know of its container's iterator
type?

Thanks!


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Carl Barron
Guest





PostPosted: Mon Jul 03, 2006 4:13 pm    Post subject: Re: Generic object with a member whose type is the iterator Reply with quote



rawhide <mark.rollins (AT) yahoo (DOT) com> wrote:

Quote:
I started working on a custom container class which would hold objects
which have iterators back to the container. I can't figure out how to
write it, not that its even possible. Here is uncompilable code which
illustrates the problem.

template <class T, class I
class Item
{
T object_;
I iterator_;//this is the iterator back into the Item's container
};

template<class T
class Container
{
//impossible to compile yet illustrates my conundrum
typedef Item<T, ContainerType::iterator> ItemType;
typedef std::list<ItemType> ContainerType;

ContainerType container_;
};

If possible, how can I get Item to know of its container's iterator
type?

provide nested typedefs to provide nested types of the template

parameters like:

template <class T,class I>
Class Item
{
public:
typedef T object_type;
typedef I iterator_type;
private:
T object__;
I iterator_;
// ...
public:
// ...
// get a copy of iterator_
I get_iterator() const {return iterator_;}
}

template <class Data>
void foo(Data &x)
{
typename Data::iterator_type it = x.get_iterator();
// use it.
if

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Lourens Veen
Guest





PostPosted: Tue Jul 04, 2006 2:24 am    Post subject: Re: Generic object with a member whose type is the iterator Reply with quote



rawhide wrote:

Quote:
I started working on a custom container class which would hold
objects
which have iterators back to the container. I can't figure out how
to
write it, not that its even possible. Here is uncompilable code
which illustrates the problem.

snip

If possible, how can I get Item to know of its container's iterator
type?

I ran into the same problem some time ago, and I solved it using a
forward declaration and a wrapper around one of the types, which
passes itself as an extra template argument. I didn't use inheritance
and didn't recognise it as the/a curiously recurring template
pattern, but thinking about it again, it's very similar. At least it
uses the same trick.

Using your example, and with inheritance to show its CRTP-ness:

template <class T, class CT>
class Item;

template <class T, class CT>
struct CTypeBase {
typedef std::list<Item<T, CT> > type;
};

template <class T>
struct CType :
public CTypeBase<T, CType<T> > {
};

template <class T, class CT>
class Item
{
T object_;
typename CT::type::iterator iterator_;
};

template <class T>
class Container
{
typedef typename CType<T>::type ContainerType;
typedef Item<T, CType<T> > ItemType;

ContainerType container_;
};


Lourens


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Vladimir Marko
Guest





PostPosted: Tue Jul 04, 2006 7:52 pm    Post subject: Re: Generic object with a member whose type is the iterator Reply with quote

rawhide wrote:
Quote:
I started working on a custom container class which would hold objects
which have iterators back to the container. I can't figure out how to
write it, not that its even possible. Here is uncompilable code which
illustrates the problem.
[...]

Well, you can try using some standard containers, say std::list :

template <typename T>
struct Container{
struct ItemType{
T value;
typename std::list<ItemType>::iterator i; // (*)
};
std::list<ItemType> items;
};

Depending on the implementation this may or may not compile.
The problem is that in (*) you need to instantiate std::list with the
incomplete type ItemType. The standard says that instantiating
any template class from the standard library results in undefined
behaviour, but those implementations which allow it in this case
will produce the desired result.

If you want to write a container to serve as the std::list in my
example, you must bear in mind that you must be able to instantiate
both the container and its iterator with incomplete types. This
actually isn't that hard. For a list start with this:

struct ListNodeBase{
ListNodeBase* Next;
ListNodeBase* Prev;
};

template <typename T>
struct ListNode : ListNodeBase{
T Value;
};

template <typename T>
struct List{
struct iterator{
explicit iterator(ListNodeBase* p) : Ptr(p) { }
T& operator*(){
return static_cast<ListNode<T>*>(Ptr)->Value;
}
private:
ListNodeBase* Ptr;
};

List() { Head.Next=Head.Prev=&Head; } // empty list
iterator begin() { return iterator(Head.Next); }
iterator end() { return iterator(&Head); }
private:
ListNodeBase Head;
std::size_t Size; // cached size
};

List<T> will contain a doubly linked list with Size+1 nodes in a
circle. One of the nodes is Head other nodes shall actually be
ListNode<T> nodes. Functions begin(), end() and iterator::operator*()
are provided to show how this works, you'll need to write the rest
yourself.

Note that neither List<T> nor List<T>::iterator contains an object
of type T. So implicitly instantiating List<T> and List<T>::iterator
with incomplete type T is OK. T must be a complete type before you
instantiate all the important member functions though.

Cheers
Vladimir Marko


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.