$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
From: David Abrahams (dave_at_[hidden])
Date: 2006-02-22 12:36:16
Nico Galoppo <nico_at_[hidden]> writes:
> David Abrahams wrote:
>
>  > It's not a constness problem, exactly.  The problem is that the result
>  > of
>  >
>  >    *ab.begin()
>  >
>  > is an rvalue (i.e. returned by value, not by reference).  Yet the
>  > filter_iterator thinks it is iterating over lvalues: its reference
>  > type is Hybrid::Graph<node_traits>::const_node_ptr&, and the compiler
>  > is complaining that you can't initialize such a reference with a
>  > non-lvalue.  It's hard to come up with a complete analysis with the
>  > little information I have here, but I believe
>  >
>  >   Hybrid::Graph<Hybrid::ArticulatedModelNodeTraits<MyTypes> 
>  >::node_df_traversal_iterator
>  >
>  > is misreporting its reference type or its category.  An iterator whose
>  > operator* returns by value cannot be a forward iterator; it can only
>  > be an input iterator.
>  >
>  >
>
> I must admit, I'm only a novice at writing my own iterators. I've given it a try 
> (see below), but something must be doing something wrong as you said. 
Novices should not write their own iterators without the help of
boost::iterator_facade or iterator_adaptor.  There are too many ways
to get it wrong.
> I think 
> operator*() returns a reference now, but I could be wrong.
"Now" meaning you juste fixed it, or has it always been returning a
reference?
BTW, I also wonder if building your own graph classes is the best
course of action when Boost provides a Graph library.
> -------------------------------------------------------------------------------
>
>      class node_df_traversal_iterator : public 
> std::iterator<std::forward_iterator_tag,node_type>
> {
>      protected:
>
>        node_ptr           m_node;   ///< Current node being visited in traversal.
>        node_ptr_container m_queue;  ///< Remaining unvisited nodes in traversal.
>
>      public:
>
>        node_df_traversal_iterator(node_ptr node)
>          : m_node(node)
>        {
>          if(node)
>            m_queue.push_back(node);
>        }
>
>        bool operator== ( node_df_traversal_iterator const & other ) const{ 
> return (other.m_node==m_node); }
>        bool operator!= ( node_df_traversal_iterator const & other ) const{ 
> return !((*this)==other); }
>        node_type & operator*() {return (*m_node);}
Yep, looks like a reference.
>        node_ptr operator->() {return m_node;}
>        node_type const & operator*() const  {return (*m_node);}
This is where your problem is.  The const-ness of an iterator should
never affect the constness of the elements it traverses.
I suggest, strongly, that you go through the tutorial at
http://www.boost.org/libs/iterator/doc/iterator_facade.html#tutorial-example
and build your iterators around that.
HTH,
-- Dave Abrahams Boost Consulting www.boost-consulting.com