Converting from const to non-const with iterator_adaptor

Hi,
I'm stuck trying to use iterator_adaptor from the CVS head. I simply want
to derive a non-const iterator from a const one derived from
iterator_facade, as shown in the code below. When I compile it with VC7.1,
the line marked "/* *ERROR* */" generates one of those impenetratable error
messages that starts with:
cannot convert from 'const Node' to
'boost::iterator_facade
boost_const_iterator;
class const_iterator : public boost_const_iterator { public: const_iterator() {} const_iterator(const iterator& it) : m_pNode(it.base().m_pNode) {} explicit const_iterator(const Node* pNode) : m_pNode(pNode) {} friend class iterator; friend class boost::iterator_core_access; private: // Interface required by iterator_facade: reference dereference() const { return *m_pNode; } void increment() { m_pNode = m_pNode->next(); } void decrement() { m_pNode = m_pNode->prev(); } bool equal(const_iterator it) const { return m_pNode == it.m_pNode; } protected: const Node* m_pNode; }; // Read-write, bidirectional iterator, // adapted from const_iterator: typedef boost::iterator_adaptor< iterator, const_iterator, Node /* *ERROR* */
iterator_base;
class iterator : public iterator_base { public: iterator() {} explicit iterator(Node* pNode) : iterator_base(const_iterator(pNode)) {} }; const_iterator begin() const { return const_iterator(m_pChild); } const_iterator end() const { return const_iterator(NULL); } iterator begin() { return iterator(m_pChild); } iterator end() { return iterator(NULL); } private: Node* m_pChild; Node* m_pPrev; Node* m_pNext; }; /* ========================= Code Ends ========================= */

"Keith MacDonald"
Hi,
I'm stuck trying to use iterator_adaptor from the CVS head. I simply want to derive a non-const iterator from a const one derived from iterator_facade, as shown in the code below.
Answer: don't do that. Making iterators by derivation from other iterators is almost always an error (and in your case also: for example the return type of operator++ is wrong on the derived iterator). Make a new constant iterator type with iterator_facade. If you do it right, it will interoperate properly with your mutable iterator.
When I compile it with VC7.1, the line marked "/* *ERROR* */" generates one of those impenetratable error messages that starts with:
cannot convert from 'const Node' to 'boost::iterator_facade
::reference'
Compile with GCC; you'll get better error messages. The type
'boost::iterator_facade
If I delete that line, so the default is used, dereferencing a non-const iterator returns a const Node. This seems such a simple requirement that there must be an easy way to do it. What am I doing wrong?
Looks like a job for iterator_adaptor:
// untested
template <class V>
struct iter
: boost::iterator_adaptor

I may have misunderstood the purpose of boost::iterator: I was expecting it
to make it easy to add standard conforming iterators to any container, but
the complexity of the proposed solution, (using iterator_adaptor, which I
can't get to compile), is making me doubt that. In an earlier release of
the library, I was able to declare the const_iterator using iterator_facade,
then simply adapt it to a non-const iterator using iterator_adaptor, as
shown in my original posting. I've not followed the discussions that led up
to the current implementation, so don't know what its advantages are, but if
it can't provide a simple solution to the simplest case, has something
important been thrown out with the bath water?
My working solution is now to use iterator_facade to declare instances of
const_iterator and iterator, which are independent of each other, except
that a const_iterator can be constructed from an iterator. Instinctively,
this does not seem to the intended way to do it, but it would probably be
quicker to write the iterators from scratch than work that out from the
documentation. Can I make a plea for an example to be included with the
library, which shows how best to add plain vanilla iterators to a container
class?
Thanks,
Keith MacDonald
"David Abrahams"
Looks like a job for iterator_adaptor:
// untested template <class V> struct iter : boost::iterator_adaptor
boost::bidirectional_traversal_tag>
{ typedef boost::iterator_adaptor
super; iter() {}
template <class V2> iter(iter<V2> x, boost::enable_if_convertible
::type* = 0) : super(x.base()) friend class iterator; friend class boost::iterator_core_access;
private: void increment() { base() = base()->next(); }
void decrement() { base() = base()->prev(); } };
typedef iter<Node> iterator; typedef iter<Node const> const_iterator;
HTH,
-- Dave Abrahams Boost Consulting www.boost-consulting.com

"Keith MacDonald"
I may have misunderstood the purpose of boost::iterator
Do you mean the Boost.Iterator library? There's no boost::iterator component.
I was expecting it to make it easy to add standard conforming iterators to any container
Containers are sort of irrelevant. It makes it easy to build conforming iterators and adapt existing iterators.
but the complexity of the proposed solution
?? it's way simpler than what you posted ??
(using iterator_adaptor, which I can't get to compile)
<sigh> Fine, here's a complete, compilable example.
#include
is making me doubt that. In an earlier release of the library, I was able to declare the const_iterator using iterator_facade
You still can, but you have to do more work with iterator_facade. Why declare the dereference member if you don't need to?
then simply adapt it to a non-const iterator using iterator_adaptor, as shown in my original posting.
Is that what your posting was doing? And you think that's simpler than what I did above?
I've not followed the discussions that led up to the current implementation, so don't know what its advantages are, but if it can't provide a simple solution to the simplest case, has something important been thrown out with the bath water?
I don't know what you mean. There was no iterator_facade in any earlier design which was substantially different from what's there now.
My working solution is now to use iterator_facade to declare instances of const_iterator and iterator, which are independent of each other, except that a const_iterator can be constructed from an iterator. Instinctively, this does not seem to the intended way to do it, but it would probably be quicker to write the iterators from scratch than work that out from the documentation.
We're working on the docs; we apologize for the delay.
Can I make a plea for an example to be included with the library, which shows how best to add plain vanilla iterators to a container class?
OK. What do you mean by "plain vanilla?" -- Dave Abrahams Boost Consulting www.boost-consulting.com

You have proposed a very elegant solution, but I would defy anyone who does
not understand the library inside out to arrive at that solution. The
documentation (iterator/doc/index.html#iterator-facade-and-adaptor) states:
"It is common to define a new iterator which behaves like another iterator,
but which modifies some aspect of its behavior. For that purpose, the
library supplies the iterator_adaptor class template, which is specially
designed to take advantage of as much of the underlying iterator's behavior
as possible."
In this case, I can't see what the underlying iterator is, so don't
understand how iteration can proceed. For example, if you add the statement
"++x;" to your example, it fails to compile.
To return to my point about the purpose of a software library, my approach
is generally to ask if it will allow me to implement code more quickly and
reliably than without it. I got to the point of thinking, I've now got to
implement a straightforward iterator, sigh, so will the boost library help
me? I didn't expect to have to develop a deep understanding of template
metaprogramming and the curiously recurring template pattern, before I could
move on. Hence my plea for an example of a plain vanilla iterator, by which
I meant something similar to those used for the std library containers.
That would make a much more satisfactory introduction than trying to plough
through the impenetrable documentation.
Thanks for your time and, possibly, for an extremely useful library!
Keith MacDonald
"David Abrahams"
"Keith MacDonald"
writes: I may have misunderstood the purpose of boost::iterator
Do you mean the Boost.Iterator library? There's no boost::iterator component.
I was expecting it to make it easy to add standard conforming iterators to any container
Containers are sort of irrelevant. It makes it easy to build conforming iterators and adapt existing iterators.
but the complexity of the proposed solution
?? it's way simpler than what you posted ??
(using iterator_adaptor, which I can't get to compile)
<sigh> Fine, here's a complete, compilable example.
#include
struct Node { Node* next(); Node* prev(); Node const* next() const; Node const* prev() const; };
template <class V> struct iter : boost::iterator_adaptor
{ typedef boost::iterator_adaptor super; iter() {}
template <class V2> iter(iter<V2> const& x, typename boost::enable_if_convertible
::type* = 0) : super(x.base()) {} friend class boost::iterator_core_access;
private: void increment() { base() = base()->next(); }
void decrement() { base() = base()->prev(); } };
int main() { typedef iter<Node> iterator; typedef iter<Node const> const_iterator;
iterator x; const_iterator y; y = x; }
is making me doubt that. In an earlier release of the library, I was able to declare the const_iterator using iterator_facade
You still can, but you have to do more work with iterator_facade. Why declare the dereference member if you don't need to?
then simply adapt it to a non-const iterator using iterator_adaptor, as shown in my original posting.
Is that what your posting was doing? And you think that's simpler than what I did above?
I've not followed the discussions that led up to the current implementation, so don't know what its advantages are, but if it can't provide a simple solution to the simplest case, has something important been thrown out with the bath water?
I don't know what you mean. There was no iterator_facade in any earlier design which was substantially different from what's there now.
My working solution is now to use iterator_facade to declare instances of const_iterator and iterator, which are independent of each other, except that a const_iterator can be constructed from an iterator. Instinctively, this does not seem to the intended way to do it, but it would probably be quicker to write the iterators from scratch than work that out from the documentation.
We're working on the docs; we apologize for the delay.
Can I make a plea for an example to be included with the library, which shows how best to add plain vanilla iterators to a container class?
OK. What do you mean by "plain vanilla?"
-- Dave Abrahams Boost Consulting www.boost-consulting.com

"Keith MacDonald"
You have proposed a very elegant solution, but I would defy anyone who does not understand the library inside out to arrive at that solution. The documentation (iterator/doc/index.html#iterator-facade-and-adaptor) states:
We're working on the docs. That document is the standards proposal, but the Boost (user-level) docs aren't complete yet.
"It is common to define a new iterator which behaves like another iterator, but which modifies some aspect of its behavior. For that purpose, the library supplies the iterator_adaptor class template, which is specially designed to take advantage of as much of the underlying iterator's behavior as possible."
In this case, I can't see what the underlying iterator is, so don't understand how iteration can proceed.
I quote: The iterator_adaptor class template adapts some Base 3 type to create a new iterator. Instantiations of iterator_adaptor are derived from a corresponding instantiation of iterator_facade and implement the core behaviors in terms of the Base type. In essence, iterator_adaptor merely forwards all operations to an instance of the Base type, which it stores as a member. [3] The term "Base" here does not refer to a base class and is not meant to imply the use of derivation. We have followed the lead of the standard library, which provides a base() function to access the underlying iterator object of a reverse_iterator adaptor. The user of iterator_adaptor creates a class derived from an instantiation of iterator_adaptor and then selectively redefines some of the core member functions described in the table above. The Base type need not meet the full requirements for an iterator. It ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ need only support the operations used by the core interface functions of iterator_adaptor that have not been redefined in the user's derived class.
For example, if you add the statement "++x;" to your example, it fails to compile.
Umm, sorry. I whipped that one off without too much testing. I've enclosed a fixed one.
To return to my point about the purpose of a software library, my approach is generally to ask if it will allow me to implement code more quickly and reliably than without it. I got to the point of thinking, I've now got to implement a straightforward iterator, sigh, so will the boost library help me? I didn't expect to have to develop a deep understanding of template metaprogramming and the curiously recurring template pattern, before I could move on.
Why would you need to develop either of those? You just follow the formula.
Hence my plea for an example of a plain vanilla iterator, by which I meant something similar to those used for the std library containers.
I'm sorry, I need you to be more specific. Is the example of your node iterator good enough? -- Dave Abrahams Boost Consulting www.boost-consulting.com

That's just what I needed! It makes much more sense now that you have
explained that iterator_adaptor adapts a base class, rather than an
iterator, as originally documented. The concept is amazingly powerful, and
now that I've cleared the first hurdle, I'm much more inclined to explore
other uses.
I've adapted your example to implement begin() and end() methods, with a
little test, and have attached the code. I hope you can include such an
example with the library.
Thanks again for your help.
Keith MacDonald
"David Abrahams"
"Keith MacDonald"
writes: You have proposed a very elegant solution, but I would defy anyone who does not understand the library inside out to arrive at that solution. The documentation (iterator/doc/index.html#iterator-facade-and-adaptor) states:
We're working on the docs. That document is the standards proposal, but the Boost (user-level) docs aren't complete yet.
"It is common to define a new iterator which behaves like another iterator, but which modifies some aspect of its behavior. For that purpose, the library supplies the iterator_adaptor class template, which is specially designed to take advantage of as much of the underlying iterator's behavior as possible."
In this case, I can't see what the underlying iterator is, so don't understand how iteration can proceed.
I quote:
The iterator_adaptor class template adapts some Base 3 type to create a new iterator. Instantiations of iterator_adaptor are derived from a corresponding instantiation of iterator_facade and implement the core behaviors in terms of the Base type. In essence, iterator_adaptor merely forwards all operations to an instance of the Base type, which it stores as a member.
[3] The term "Base" here does not refer to a base class and is not meant to imply the use of derivation. We have followed the lead of the standard library, which provides a base() function to access the underlying iterator object of a reverse_iterator adaptor.
The user of iterator_adaptor creates a class derived from an instantiation of iterator_adaptor and then selectively redefines some of the core member functions described in the table above. The Base type need not meet the full requirements for an iterator. It ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ need only support the operations used by the core interface functions of iterator_adaptor that have not been redefined in the user's derived class.
For example, if you add the statement "++x;" to your example, it fails to compile.
Umm, sorry. I whipped that one off without too much testing. I've enclosed a fixed one.
---------------------------------------------------------------------------- ----
To return to my point about the purpose of a software library, my approach is generally to ask if it will allow me to implement code more quickly and reliably than without it. I got to the point of thinking, I've now got to implement a straightforward iterator, sigh, so will the boost library help me? I didn't expect to have to develop a deep understanding of template metaprogramming and the curiously recurring template pattern, before I could move on.
Why would you need to develop either of those? You just follow the formula.
Hence my plea for an example of a plain vanilla iterator, by which I meant something similar to those used for the std library containers.
I'm sorry, I need you to be more specific. Is the example of your node iterator good enough?
-- Dave Abrahams Boost Consulting www.boost-consulting.com
---------------------------------------------------------------------------- ----
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
begin 666 baz2.cpp
M+R\@8F%Z,BYC<' Z($)I9&ER96-T:6]N86P@:71E

"Keith MacDonald"
That's just what I needed! It makes much more sense now that you have explained that iterator_adaptor adapts a base class, rather than an iterator, as originally documented.
I was quoting the same documentation you referred to.
The concept is amazingly powerful, and now that I've cleared the first hurdle, I'm much more inclined to explore other uses.
Glad to know it's useful.
I've adapted your example to implement begin() and end() methods, with a little test, and have attached the code. I hope you can include such an example with the library.
I'd love to. If I'm to use your code wholesale, I'll need you to add the standard boost copyright and license reference. -- Dave Abrahams Boost Consulting www.boost-consulting.com

I was quoting the same documentation you referred to.
OK, but my quote came from the front page (index.html), so I read that first. Perhaps that section should be rewritten.
I'd love to. If I'm to use your code wholesale, I'll need you to add the standard boost copyright and license reference.
I've done that, and attach the new source. However, I hereby relinquish all
rights over baz2.cpp, so feel free to do whatever you like with it.
When I attempted to integrate the iterators with my actual code, I hit a
problem that I don't know how to resolve with iterator_facade. To
illustrate it, I've modified the example code and attach it as baz3.cpp.
Now, Node is an abstract base class, and DerivedNode is instantiated.
Compiling it results in the following error:
\CVS\boost\boost\iterator\iterator_facade.hpp(389) : error C2259:
'Node' : cannot instantiate abstract class due to following members:
'int Node::getInfo(void) const' : pure virtual function was not defined
Can your technique be used in such contexts?
Thanks,
Keith MacDonald
begin 666 baz2.cpp
M+R\@8F%Z,BYC<' Z($)I9&ER96-T:6]N86P@:71E

"Keith MacDonald"
I've done that, and attach the new source. However, I hereby relinquish all rights over baz2.cpp, so feel free to do whatever you like with it.
When I attempted to integrate the iterators with my actual code, I hit a problem that I don't know how to resolve with iterator_facade. To illustrate it, I've modified the example code and attach it as baz3.cpp. Now, Node is an abstract base class, and DerivedNode is instantiated. Compiling it results in the following error:
\CVS\boost\boost\iterator\iterator_facade.hpp(389) : error C2259: 'Node' : cannot instantiate abstract class due to following members: 'int Node::getInfo(void) const' : pure virtual function was not defined
Can your technique be used in such contexts?
Very interesting case. The problem is that, when the iterator is not writable, operator[] returns an object of the iterator's value_type. In this case the value_type is abstract, so it can't be returned. This raises several problems that I can see. 1. Obviously, the library doesn't work for you. You can get around that by applying the enclosed patch to iterator_facade.hpp. We'll figure out the right long-term fix soon; this one might be it. 2. We have to re-think the readable iterator requirements if we want iterators over abstract types to be legal. My feeling is that the requirement should be that *a is convertible to value_type const&. 3. Your iterator isn't a legal random access iterator, because the random access iterator requirements say that a[n] must be convertible to value_type. You can't convert anything to value_type in this case, since it can't be constructed. I think this is a defect in the current standard, and will submit a DR. -- Dave Abrahams Boost Consulting www.boost-consulting.com

Your patch solves my immediate problem, thanks. Fortunately, both the
classes that I need iterators for only require bidirectional semantics, so
the random access issue does not arise, but thanks for pointing it out.
Keith MacDonald
"David Abrahams"
"Keith MacDonald"
writes: I've done that, and attach the new source. However, I hereby relinquish all rights over baz2.cpp, so feel free to do whatever you like with it.
When I attempted to integrate the iterators with my actual code, I hit a problem that I don't know how to resolve with iterator_facade. To illustrate it, I've modified the example code and attach it as baz3.cpp. Now, Node is an abstract base class, and DerivedNode is instantiated. Compiling it results in the following error:
\CVS\boost\boost\iterator\iterator_facade.hpp(389) : error C2259: 'Node' : cannot instantiate abstract class due to following members: 'int Node::getInfo(void) const' : pure virtual function was not defined
Can your technique be used in such contexts?
Very interesting case. The problem is that, when the iterator is not writable, operator[] returns an object of the iterator's value_type. In this case the value_type is abstract, so it can't be returned.
This raises several problems that I can see.
1. Obviously, the library doesn't work for you. You can get around that by applying the enclosed patch to iterator_facade.hpp. We'll figure out the right long-term fix soon; this one might be it.
2. We have to re-think the readable iterator requirements if we want iterators over abstract types to be legal. My feeling is that the requirement should be that *a is convertible to value_type const&.
3. Your iterator isn't a legal random access iterator, because the random access iterator requirements say that a[n] must be convertible to value_type. You can't convert anything to value_type in this case, since it can't be constructed. I think this is a defect in the current standard, and will submit a DR.
---------------------------------------------------------------------------- ----
-- Dave Abrahams Boost Consulting www.boost-consulting.com
---------------------------------------------------------------------------- ----
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

"Keith MacDonald"
I was quoting the same documentation you referred to.
OK, but my quote came from the front page (index.html), so I read that first. Perhaps that section should be rewritten.
I realize the measure of docs is in their effectiveness, but do you really think there's anything wrong with painting with a broad brush on the main page and then providing detailed revision in specific docs?
I'd love to. If I'm to use your code wholesale, I'll need you to add the standard boost copyright and license reference.
I've done that, and attach the new source. However, I hereby relinquish all rights over baz2.cpp, so feel free to do whatever you like with it.
Thanks.
When I attempted to integrate the iterators with my actual code, I hit a problem that I don't know how to resolve with iterator_facade. To illustrate it, I've modified the example code and attach it as baz3.cpp. Now, Node is an abstract base class, and DerivedNode is instantiated. Compiling it results in the following error:
\CVS\boost\boost\iterator\iterator_facade.hpp(389) : error C2259: 'Node' : cannot instantiate abstract class due to following members: 'int Node::getInfo(void) const' : pure virtual function was not defined
Can your technique be used in such contexts?
Thanks, Keith MacDonald
-- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams"
I realize the measure of docs is in their effectiveness, but do you really think there's anything wrong with painting with a broad brush on the main page and then providing detailed revision in specific docs? --
Only if the broad brush information paints a false picture: "In order to ease the implementation of new iterators, the Boost.Iterator library provides the iterator_facade class template, which implements many useful defaults and compile-time checks designed to help the author iterator ensure that his iterator is correct. It is common to define a new iterator which behaves like another iterator, but which modifies some aspect of its behavior. For that purpose, the library supplies the iterator_adaptor class template, which is specially designed to take advantage of as much of the underlying iterator's behavior as possible." By reading that, I was led to believe that I should use iterator_facade to create new iterators, and iterator_adaptor to modify existing iterators. Even the name "iterator_adaptor" provides no clue that it can also be used to create an iterator. If you approach the Introduction in iterator_adaptor.html with those preconceptions, it's easy to miss the implication that the base type need not be an iterator. Why not spell it out? In my opinion, for what it's worth, the documentation seems to be aimed at the developers of the library (so you're all singing from the same hymn sheet), rather than potential users. Clearly, both audiences need to be catered for - unless it was just an academic excercise. Of course, if you're already writing the text book for us users, then I completely understand the advantages of impenetrable free documentation ;-) Keith MacDonald

"Keith MacDonald"
"David Abrahams"
wrote in message news:u7k021gic.fsf@boost-consulting.com... I realize the measure of docs is in their effectiveness, but do you really think there's anything wrong with painting with a broad brush on the main page and then providing detailed revision in specific docs? --
Only if the broad brush information paints a false picture:
"In order to ease the implementation of new iterators, the Boost.Iterator library provides the iterator_facade class template, which implements many useful defaults and compile-time checks designed to help the author iterator ensure that his iterator is correct. It is common to define a new iterator which behaves like another iterator, but which modifies some aspect of its behavior. For that purpose, the library supplies the iterator_adaptor class template, which is specially designed to take advantage of as much of the underlying iterator's behavior as possible."
By reading that, I was led to believe that I should use iterator_facade to create new iterators, and iterator_adaptor to modify existing iterators.
That's correct. Your Node* _is_ an existing iterator, as are all pointers.
Even the name "iterator_adaptor" provides no clue that it can also be used to create an iterator.
It's actually very rare that there's a non-iterator which provides enough of the useful iterator operations to be used with iterator adaptor (e.g. int, used with counting_iterator). I don't think there's anything wrong with making those details less apparent.
If you approach the Introduction in iterator_adaptor.html with those preconceptions, it's easy to miss the implication that the base type need not be an iterator. Why not spell it out?
If you spell everything out in the introduction, you need to write a new introduction.
In my opinion, for what it's worth, the documentation seems to be aimed at the developers of the library (so you're all singing from the same hymn sheet), rather than potential users.
How many times do I have to repeat that We're working on the docs. That document is the standards proposal, but the Boost (user-level) docs aren't complete yet. ??
Clearly, both audiences need to be catered for - unless it was just an academic excercise. Of course, if you're already writing the text book for us users, then I completely understand the advantages of impenetrable free documentation ;-)
I'm providing free software *and* free documentation as time allows; I really don't need to have my motivations insulted that way. A smiley doesn't make it funny. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"Keith MacDonald"
writes: "David Abrahams"
wrote in message news:u7k021gic.fsf@boost-consulting.com... I realize the measure of docs is in their effectiveness, but do you really think there's anything wrong with painting with a broad brush on the main page and then providing detailed revision in specific docs? --
Only if the broad brush information paints a false picture:
"In order to ease the implementation of new iterators, the Boost.Iterator library provides the iterator_facade class template, which implements many useful defaults and compile-time checks designed to help the author iterator ensure that his iterator is correct. It is common to define a new iterator which behaves like another iterator, but which modifies some aspect of its behavior. For that purpose, the library supplies the iterator_adaptor class template, which is specially designed to take advantage of as much of
We're clearly on different wavelengths here. I've often found that if
someone asks an apparently dumb question about my software, or its
documentation, then it's better to improve the area in question, rather than
tell the person he's not using or reading it correctly. That way, I've
still got a happy customer and one less support issue to have to keep
responding to.
I was only trying to be helpful.
Keith MacDonald
"David Abrahams"
underlying iterator's behavior as possible."
By reading that, I was led to believe that I should use iterator_facade to create new iterators, and iterator_adaptor to modify existing iterators.
That's correct. Your Node* _is_ an existing iterator, as are all pointers.
Even the name "iterator_adaptor" provides no clue that it can also be used to create an iterator.
It's actually very rare that there's a non-iterator which provides enough of the useful iterator operations to be used with iterator adaptor (e.g. int, used with counting_iterator). I don't think there's anything wrong with making those details less apparent.
If you approach the Introduction in iterator_adaptor.html with those preconceptions, it's easy to miss the implication that the base type need not be an iterator. Why not spell it out?
If you spell everything out in the introduction, you need to write a new introduction.
In my opinion, for what it's worth, the documentation seems to be aimed at the developers of the library (so you're all singing from the same hymn sheet), rather than potential users.
How many times do I have to repeat that
We're working on the docs. That document is the standards proposal, but the Boost (user-level) docs aren't complete yet.
??
Clearly, both audiences need to be catered for - unless it was just an academic excercise. Of course, if you're already writing the text book for us users, then I completely understand the advantages of impenetrable free documentation ;-)
I'm providing free software *and* free documentation as time allows; I really don't need to have my motivations insulted that way. A smiley doesn't make it funny.
-- Dave Abrahams Boost Consulting www.boost-consulting.com

"Keith MacDonald"
We're clearly on different wavelengths here. I've often found that if someone asks an apparently dumb question about my software, or its documentation, then it's better to improve the area in question, rather than tell the person he's not using or reading it correctly.
I'm 100% in agreement with that. You *weren't* reading it correctly, but it's clearly the fault of the documentation. The problem I'm having is seeing how to keep users from feeling misled by the statement that apparently misled you. Even if iterator_adaptor can be used to adapt non-iterators, that *is* a corner case. We'll be telling people to use iterator_facade when they're not starting with something very much like the iterator they want to end up with. That's just good advice. Should we say, "think hard about it and remember that pointers are iterators too?" I don't think so. I think it'd be better to just show your linked list example implemented with both iterator_facade and iterator adaptor in the detailed user-level examples that we'll provide. And we can't do that on the front page.
I was only trying to be helpful.
I'm sorry, I realize that part of your post was trying to be helpful, but I have a hard time seeing how your veiled accusation that we're keeping the workings of the library secret so that we can sell books is anything other than a cheap shot.
In my opinion, for what it's worth, the documentation seems to be aimed at the developers of the library (so you're all singing from the same hymn sheet), rather than potential users.
How many times do I have to repeat that
We're working on the docs. That document is the standards proposal, but the Boost (user-level) docs aren't complete yet.
??
I'm sorry that I lost my patience with you saying that user-level docs are needed, but c'mon, the library isn't released yet, and I had already told you we were still working on the docs (twice!) in this very thread. I think it's fair to let me know that the docs could be improved, but before the library has even entered a Boost release this amounts to harping on it.
Clearly, both audiences need to be catered for - unless it was just an academic excercise. Of course, if you're already writing the text book for us users, then I completely understand the advantages of impenetrable free documentation ;-)
I'm providing free software *and* free documentation as time allows; I really don't need to have my motivations insulted that way. A smiley doesn't make it funny.
-- Dave Abrahams Boost Consulting www.boost-consulting.com
-- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams"
The problem I'm having is seeing how to keep users from feeling misled by the statement that apparently misled you. Even if iterator_adaptor can be used to adapt non-iterators, that *is* a corner case. We'll be telling people to use iterator_facade when they're not starting with something very much like the iterator they want to end up with.
Well, if we go back to my question that started this thread, I asked: "I'm stuck trying to use iterator_adaptor from the CVS head. I simply want to derive a non-const iterator from a const one derived from iterator_facade, as shown in the code below." And you replied: "Answer: don't do that. Making iterators by derivation from other iterators is almost always an error (and in your case also: for example the return type of operator++ is wrong on the derived iterator). Make a new constant iterator type with iterator_facade. If you do it right, it will interoperate properly with your mutable iterator. <snip> Looks like a job for iterator_adaptor." I had problems compiling your suggested solution, so, I replied: "My working solution is now to use iterator_facade to declare instances of const_iterator and iterator, which are independent of each other, except that a const_iterator can be constructed from an iterator." And you responded: "Is that what your posting was doing? And you think that's simpler than what I did above?" I'm afraid that I did not deduce from that that this was a corner case. If your introduction to iterators is from using them with standard library containers, it's natural to want to do the same things with your own containers, to lever the power of the standard algorithms. If the first time you try, an expert says "don't do that", there is plenty of scope for the misunderstanding that followed.
I think it's fair to let me know that the docs could be improved, but before the library has even entered a Boost release this amounts to harping on it
I was commenting on the documentation that I have before me, and assumed that that was what you were working on. Therefore, I assumed that you would be open to suggestions as to how to improve it, _before_ it is released. Given the above, I would now like to see a separate section on how to use the Boost.Iterator library to implement bidirectional and random access iterators (both const and non-const) for simple containers. That may well satisfy the requirements of more than half the potential users of this library - which should cut down on the number of people asking "dumb" questions, like me.
I'm sorry, I realize that part of your post was trying to be helpful, but I have a hard time seeing how your veiled accusation that we're keeping the workings of the library secret so that we can sell books is anything other than a cheap shot.
It was meant as a joke - hence the use of the smiley. Is there a better convention for indicating jokes in email? Keith MacDonald

"Keith MacDonald"
"David Abrahams"
wrote in message news:uu13545id.fsf@boost-consulting.com... The problem I'm having is seeing how to keep users from feeling misled by the statement that apparently misled you. Even if iterator_adaptor can be used to adapt non-iterators, that *is* a corner case. We'll be telling people to use iterator_facade when they're not starting with something very much like the iterator they want to end up with.
Well, if we go back to my question that started this thread, I asked:
"I'm stuck trying to use iterator_adaptor from the CVS head. I simply want to derive a non-const iterator from a const one derived from iterator_facade, as shown in the code below."
And you replied:
"Answer: don't do that. Making iterators by derivation from other iterators is almost always an error (and in your case also: for example the return type of operator++ is wrong on the derived iterator). Make a new constant iterator type with iterator_facade. If you do it right, it will interoperate properly with your mutable iterator. <snip> Looks like a job for iterator_adaptor."
I had problems compiling your suggested solution, so, I replied:
"My working solution is now to use iterator_facade to declare instances of const_iterator and iterator, which are independent of each other, except that a const_iterator can be constructed from an iterator."
You also wrote: "I may have misunderstood the purpose of boost::iterator: I was expecting it to make it easy to add standard conforming iterators to any container, but the complexity of the proposed solution, (using iterator_adaptor, which I can't get to compile), is making me doubt that." Which I took to mean that you thought my solution was too complex, and far more complex than what you started with.
And you responded:
"Is that what your posting was doing? And you think that's simpler than what I did above?"
I'm afraid that I did not deduce from that that this was a corner case.
It's not a corner case (you *are* adapting an iterator), and my response wasn't intended to suggest it was. All I was suggesting was that your approach of using derivation to produce an iterator from a const_iterator was much more complicated than what I posted. Admittedly, my code was untested (and so labelled), but with a little investment in reading the specification, I'm sure you could've made the minor fixes I supplied.
If your introduction to iterators is from using them with standard library containers, it's natural to want to do the same things with your own containers, to lever the power of the standard algorithms. If the first time you try, an expert says "don't do that", there is plenty of scope for the misunderstanding that followed.
I'm sorry, I was saying "don't do that" about defining new iterators by deriving them from other iterators. Was that unclear? I am very confused at this point, since I don't see why it has any relationship to the misunderstanding followed.
I think it's fair to let me know that the docs could be improved, but before the library has even entered a Boost release this amounts to harping on it
I was commenting on the documentation that I have before me, and assumed that that was what you were working on. Therefore, I assumed that you would be open to suggestions as to how to improve it, _before_ it is released.
Yes, thanks. We already understand what needs to be done, basically, but I appreciate you taking the time to let us know. We are under a lot of pressure with a boost release coming up and many issues surrounding these proposals in the standards committee. That, combined with fending off hostility from one particular committee member is probably making me touchier than neccessary.
Given the above, I would now like to see a separate section on how to use the Boost.Iterator library to implement bidirectional and random access iterators (both const and non-const) for simple containers. That may well satisfy the requirements of more than half the potential users of this library - which should cut down on the number of people asking "dumb" questions, like me.
Your questions weren't dumb.
I'm sorry, I realize that part of your post was trying to be helpful, but I have a hard time seeing how your veiled accusation that we're keeping the workings of the library secret so that we can sell books is anything other than a cheap shot.
It was meant as a joke - hence the use of the smiley. Is there a better convention for indicating jokes in email?
Not that I know of. Calling it a joke doesn't make it less offensive though. Suppose I suggested that you were just demanding better documentation so that you could understand the library well enough to write an article claiming you came up with all the ideas and then we stole them from you? ;-) See what I mean? -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams"
We are under a lot of pressure with a boost release coming up and many issues surrounding these proposals in the standards committee.
I'd better leave you in peace to get on with that then.
Calling it a joke doesn't make it less offensive
A joke that you have to explain rapidly becomes very tiresome. However, it was not irony-free. Please don't take offense. Thanks again for your assistance with my problem. Keith MacDonald

"Keith MacDonald"
"David Abrahams"
wrote in message news:ad4xqekh.fsf@boost-consulting.com... We are under a lot of pressure with a boost release coming up and many issues surrounding these proposals in the standards committee.
I'd better leave you in peace to get on with that then.
Calling it a joke doesn't make it less offensive
A joke that you have to explain rapidly becomes very tiresome.
Really? I always thought that jokes get funnier when explained. A *lot* funnier. irony-free-ly y'rs, Dave -- Dave Abrahams Boost Consulting www.boost-consulting.com

"Keith MacDonald"
"David Abrahams"
wrote in message news:ad4xqekh.fsf@boost-consulting.com... We are under a lot of pressure with a boost release coming up and many issues surrounding these proposals in the standards committee.
I'd better leave you in peace to get on with that then.
You might look at the CVS or http://www.boost-consulting.com/libs/iterator/doc/index.html if you're interested in the progress we've made so far. We'd really appreciate any feedback you have for us (really!). Thanks, -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams
"Keith MacDonald"
writes: "David Abrahams"
wrote in message news:ad4xqekh.fsf@boost-consulting.com... We are under a lot of pressure with a boost release coming up and many issues surrounding these proposals in the standards committee.
I'd better leave you in peace to get on with that then.
You might look at the CVS or http://www.boost-consulting.com/libs/iterator/doc/index.html if you're
Arf, sorry: http://www.boost-consulting.com/boost/libs/iterator/doc/index.html
interested in the progress we've made so far. We'd really appreciate any feedback you have for us (really!).
-- Dave Abrahams Boost Consulting www.boost-consulting.com

I know you're in a hurry, so I'll just comment on the documentation as I go,
rather than saving everything up until the end.
1. This is probably in the generator you're using for the HTML files: the
cursor behaves like it's over an active link, when it's over a heading.
This is due to lines like the following:
<h1><a class="toc-backref" href="#id6" name="new-style-iterators">New-Style
Iterators</a></h1>
It would be less confusing if the anchor tag was moved, like this:
<a class="toc-backref" href="#id6" name="new-style-iterators"></a>
<h1>New-Style Iterators</h1>
2. I like the changes to the paragraph "Iterator Facade and Adaptor" in
index.html. Using "type" instead of "iterator" was simple, but effective.
3. Have you considered adding a "road map" to index.html? Possibly like the
"Other Documents" links at the head of boost/libs/filesystem/doc/index.htm,
or like the "How to read this" section in the Boost.Signals documentation.
It would help the new reader judge how much time to allocate to reading the
documentation, and provide a handy starting point, if you get lost.
4. I got the updated documentation using CVS update, which broke my copy of
iterator_facade.hpp, because the CVS head copy contains this code:
template
> 1.15 , operator_brackets_proxy<Iterator> >::type type; };
Regards,
Keith MacDonald
"David Abrahams"
You might look at the CVS or http://www.boost-consulting.com/libs/iterator/doc/index.html if you're interested in the progress we've made so far. We'd really appreciate any feedback you have for us (really!).
Thanks,
-- Dave Abrahams Boost Consulting www.boost-consulting.com

Sorry, forget point 4, about iterator_facade.hpp. I reinstated the wrong
copy before running CVS update. It's my problem.
Keith MacDonald
"Keith MacDonald"
4. I got the updated documentation using CVS update, which broke my copy
of
iterator_facade.hpp, because the CVS head copy contains this code:
template
struct operator_brackets_result { typedef typename mpl::if_< <<<<<<< iterator_facade.hpp iterator_writability_disabled , Value ======= use_operator_brackets_proxy , Value >> 1.15 , operator_brackets_proxy<Iterator> >::type type; };
Regards, Keith MacDonald
"David Abrahams"
wrote in message news:uad4tmb0b.fsf@boost-consulting.com... You might look at the CVS or http://www.boost-consulting.com/libs/iterator/doc/index.html if you're interested in the progress we've made so far. We'd really appreciate any feedback you have for us (really!).
Thanks,
-- Dave Abrahams Boost Consulting www.boost-consulting.com

"Keith MacDonald"
I know you're in a hurry, so I'll just comment on the documentation as I go, rather than saving everything up until the end.
1. This is probably in the generator you're using for the HTML files: the cursor behaves like it's over an active link, when it's over a heading.
It's intentional. It *is* over an active link. You can bounce back and forth between the TOC and the various sections. I happen to like that behavior, but it could be turned off. I don't see a reason to, though.
This is due to lines like the following:
<h1><a class="toc-backref" href="#id6" name="new-style-iterators">New-Style Iterators</a></h1>
It would be less confusing if the anchor tag was moved, like this:
<a class="toc-backref" href="#id6" name="new-style-iterators"></a> <h1>New-Style Iterators</h1>
Why would that be less confusing?
2. I like the changes to the paragraph "Iterator Facade and Adaptor" in index.html. Using "type" instead of "iterator" was simple, but effective.
3. Have you considered adding a "road map" to index.html?
I hadn't.
Possibly like the "Other Documents" links at the head of boost/libs/filesystem/doc/index.htm, or like the "How to read this" section in the Boost.Signals documentation. It would help the new reader judge how much time to allocate to reading the documentation, and provide a handy starting point, if you get lost.
It's a great idea.
4. I got the updated documentation using CVS update, which broke my copy of iterator_facade.hpp, because the CVS head copy contains this code:
template
struct operator_brackets_result { typedef typename mpl::if_< <<<<<<< iterator_facade.hpp iterator_writability_disabled , Value ======= use_operator_brackets_proxy , Value >> 1.15 , operator_brackets_proxy<Iterator> >::type type; };
No it doesn't; that's just CVS respecting the local changes you made to your copy of iterator_facade.hpp. You can update with -C to throw those away. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams
"Keith MacDonald"
writes: Possibly like the "Other Documents" links at the head of boost/libs/filesystem/doc/index.htm, or like the "How to read this" section in the Boost.Signals documentation. It would help the new reader judge how much time to allocate to reading the documentation, and provide a handy starting point, if you get lost.
It's a great idea.
Would you care to propose something? We're running short of time and anything you could do to help improve the docs would really be appreciated. -- Dave Abrahams Boost Consulting www.boost-consulting.com

[Sorry that this is uselessly late]
On 1/12/04 5:57 PM, "David Abrahams"
"Keith MacDonald"
writes: [SNIP] This is due to lines like the following:
<h1><a class="toc-backref" href="#id6" name="new-style-iterators">New-Style Iterators</a></h1>
It would be less confusing if the anchor tag was moved, like this:
<a class="toc-backref" href="#id6" name="new-style-iterators"></a> <h1>New-Style Iterators</h1>
Why would that be less confusing? [TRUNCATE]
In fact, this would be worse. The anchor takes up zero area. This is sort-of acceptable for a link destination, but it's definitely bad for a link source, since it's now (practically) un-clickable! The HTML standard allows anchors to be sources and destinations simultaneously; take advantage of that if needed. -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com
participants (4)
-
Daniel Wallin
-
Daryle Walker
-
David Abrahams
-
Keith MacDonald