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 

Iterators and policy definition for iteration type

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





PostPosted: Sun Apr 24, 2005 3:43 pm    Post subject: Iterators and policy definition for iteration type Reply with quote



I've wrote an iterator for my class "Seg" and and the class has an member
typedef that defines that iterator

typedef SegIter iterator;

Everything used the standard way of definining iterator from STL

SegIter is defined like this :

class SegIter : public std::iterator<std::bidirectional_iterator_tag, Seg*>
{
.....
}
Seg objects are segment from an interval tree.

When defining a region to iterate from, let's say seg1->begin() to
Seg2->end(), you can so such with an unrolled loop

Seg::iterator iter;
for(iter = seg1->begin(), iter != seg2->End(), iter++)
{
.....
}

Currently, operator++() from the iterator is hardcored to do a depth-first
from the start to the end of the segment. However, I would like to customize
the traversal algorithm through a policy class

teamplate <class TraversePolicy>
class SegIter : public TraversePolicy
{
...
}

SegIter would then require the policy class to implement the method "bool
advance(SegIter*). The This pointer is passed as pointer to the policy class
... At this point I'm not sure if this is the right usage of policies (I just
read the book Modern C++ seems like Policies is appropriate for that).

Doing so implies that the policy is not reponsible for implementing the
traversal, but instead the iterator itself. How can I tell the iterator
which algorithm to use then? I though about how STL use compile time
polymorphism and function overloading to determine the right algorithm to
use depending on the type of iterator. I thought doing the same, by defining
a bunch of classes,

struct linear_traverse_type_tag
{};
struct hierarchical_traverse_tag
{};
struct depth_first_traverse_tag :
public hierarchical_traverse_tag
{};
struct breadth_first_traverse_tag :
public hierarchical_traverse_tag
{};
struct parent_chain_traverse_tag :
public hierarchical_traverse_tag
{};

And having the iterator implementing different overloaded version of Advance

SegIter& advance(depth_first_traverse_tag &);
SegIter& advance(breadth_first_traverse_tag &);
SegIter& advance(parent_chain_traverse_tag &);

For each Policy class that I would define, they would define a typedef
_traversal with the right type mentioned above. Even better, I could have
the policy class being a template class and the argument being the traversal
tag.

template<class traversal>
class SegIter : public GenericTraversePolicy<SegIter, traversal>
{

}

In this cass, GenericTraversePolicy class is not really a policy class but
simply a templatized class that knows with overloaded Advance from the
iterator to call.

I'm really not sure if what i'm describing above is the right way of solving
this problem. My first concern is STL which expect an iterator of a class to
be of one type. That iterator cannot be templatized. Otherwize, how STL
determine with iterator to use?
I'm not so sure also if the use of STL here is the right approach too. I've
been reading the Range Concept from the Book "Imperfect C++" and it seems
like Range may also offer a better way of solving this problem.

Any feedback how to solve this problem is appreciated,

Regards,
-Charles








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

Back to top
Alberto Barbati
Guest





PostPosted: Sun Apr 24, 2005 8:55 pm    Post subject: Re: Iterators and policy definition for iteration type Reply with quote



Charles Bissonnette wrote:
Quote:
I've wrote an iterator for my class "Seg" and and the class has an member
typedef that defines that iterator

typedef SegIter iterator;

Everything used the standard way of definining iterator from STL

SegIter is defined like this :

class SegIter : public std::iterator<std::bidirectional_iterator_tag, Seg*
{
....
}
Seg objects are segment from an interval tree.

.....hmmm, is Seg the value type or the container type? It looks like, and
so I assume it is, the value (actually it is Seg*). The interval tree is
therefore the container, right?

Quote:

When defining a region to iterate from, let's say seg1->begin() to
Seg2->end(), you can so such with an unrolled loop

Ops! If Seg is the value type, how come it has begin() and end()
members???? They should belong to the container instead.

Moreover, a valid range is defined by two iterators "pointing to" places
in the same container, so the range should be either "seg1->begin(),
seg1->end()" or "seg2->begin(), seg2-end()". You can't take the begin
from one container and the end of another container and pretend they
describe a range. If you need to do that, then either you are very
confused or the iterator concept is not suitable for you.

Quote:

Seg::iterator iter;

This makes Seg looks like it is indeed the container type... I'm lost!

Quote:
for(iter = seg1->begin(), iter != seg2->End(), iter++)
{
....
}

For custom iterators it is usally preferrable to use ++iter instead of
iter++. Dumb compilers may produce suboptimal code in presence of iter++
because they may not be able to optimize away the presence of an
unneeded temporary.

Quote:

Currently, operator++() from the iterator is hardcored to do a depth-first
from the start to the end of the segment. However, I would like to customize
the traversal algorithm through a policy class

teamplate <class TraversePolicy
class SegIter : public TraversePolicy
{
...
}

Ouch. Things are getting more complex then. If you want to stick with
the iterator approach, you end up having different iterator classes.
This approach as certain advantages, for example you won't inadventently
mix iterators with different traversal algorithms. I hope you realize,
however, that you will need to templatize function begin() and end() also:

class ???? // is it Seg or whatever?
{
template SegIter<TraversePolicy> begin();

template <class TraversePolicy>
SegIter<TraversePolicy> end();
};

and the syntax will now change in the above example:

//Seg::iterator iter; you can no longer use this Sad
SegIter<traversal> iter;
for(iter = seg1->begin<traversal>(),
iter != seg1->end<traversal>(), ++iter)
{
....
}

Quote:

SegIter would then require the policy class to implement the method "bool
advance(SegIter*). The This pointer is passed as pointer to the policy class
.. At this point I'm not sure if this is the right usage of policies (I just
read the book Modern C++ seems like Policies is appropriate for that).

Doing so implies that the policy is not reponsible for implementing the
traversal, but instead the iterator itself.

I don't follow you... If advance() takes a SegIter* then the traversal
is implemented by the policy. Yet you say it isn't. Please notice that
there is nothing (in the language, nor in the STL) that prevents you to
implement the traversal either in the policy or in the iterator or in
the container class or in any another place. You just have to decide
which place is better for you.

Quote:
traversal, but instead the iterator itself. How can I tell the iterator
which algorithm to use then? I though about how STL use compile time
polymorphism and function overloading to determine the right algorithm to
use depending on the type of iterator. I thought doing the same, by defining
a bunch of classes,

struct linear_traverse_type_tag
{};
struct hierarchical_traverse_tag
{};
struct depth_first_traverse_tag :
public hierarchical_traverse_tag
{};
struct breadth_first_traverse_tag :
public hierarchical_traverse_tag
{};
struct parent_chain_traverse_tag :
public hierarchical_traverse_tag
{};

And having the iterator implementing different overloaded version of Advance

SegIter& advance(depth_first_traverse_tag &);
SegIter& advance(breadth_first_traverse_tag &);
SegIter& advance(parent_chain_traverse_tag &);


You are making it more complicated than it should. Why don't you just
define the traversal in the policy class itself? Like this:

struct linear_traverse
{
static void advance(SegIter<linear_traverse>& iter);
};

struct depth_first_traverse
{
static void advance(SegIter<depth_first_traverse>& iter);
};

// ...

then the iterator is implemented like this:

template <class TraversePolicy>
class SegIter<TraversePolicy>
{
//...
SegIter& operator++()
{
TraversePolicy::advance(*this);
return *this;
}
};

(this is in fact a template-based application of the GoF Strategy pattern)

Quote:
For each Policy class that I would define, they would define a typedef
_traversal with the right type mentioned above. Even better, I could have
the policy class being a template class and the argument being the traversal
tag.

template class SegIter : public GenericTraversePolicy {

}

Another unnecessary complication, IMHO.

Quote:

I'm really not sure if what i'm describing above is the right way of solving
this problem. My first concern is STL which expect an iterator of a class to
be of one type. That iterator cannot be templatized. Otherwize, how STL
determine with iterator to use?

Why do you say that iterators cannot be templatized? The only problem
with templatized iterators is that you lose the possibility to write:

typedef SegIter iterator;

but nobody will yell at you if you don't provide that. It's just
syntactic sugar and that's not what makes a class an iterator class ;-)

Quote:
I'm not so sure also if the use of STL here is the right approach too. I've
been reading the Range Concept from the Book "Imperfect C++" and it seems
like Range may also offer a better way of solving this problem.

I didn't read the book so I can't help you here. Of course there may be
other concepts that may suit you better than the iterator concept.
Programming means making choices, you know. Most of the times they are
not black vs. white choices, there are a lot of shades of grey ;-)

Alberto

[ 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.