 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
rawhide Guest
|
Posted: Mon Jul 03, 2006 1:36 am Post subject: Generic object with a member whose type is the iterator type |
|
|
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
|
Posted: Mon Jul 03, 2006 4:13 pm Post subject: Re: Generic object with a member whose type is the iterator |
|
|
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
|
Posted: Tue Jul 04, 2006 2:24 am Post subject: Re: Generic object with a member whose type is the iterator |
|
|
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
|
Posted: Tue Jul 04, 2006 7:52 pm Post subject: Re: Generic object with a member whose type is the iterator |
|
|
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 |
|
 |
|
|
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
|
|