[iterator] Help needed understanding output_iterator requirements

Dear iterator experts, Jesse Perla recently reported that boost::multi_array fails compilation for many basic tasks on MSVC 2010. I investigated the failures, because I had already investigated other failures on MSVC 2010 reported by Jesse Perla for boost::ublas. While I'm quite familiar with boost::ublas, I'm a complete novice with respect to boost::multi_array and boost::iterator. I could track the failures to a specific (intentional?) behavior of iterator_facade from Boost.Iterator (more specifically of facade_iterator_category.hpp): http://lists.boost.org/Archives/boost/2010/03/163039.php Thomas Klimpel wrote:
What effectively happens it that the iterator gets the category "input_iterator", but std::copy wants to have an "output_iterator". I think I understand why the iterator doesn't satisfies the requirement of a "forward_iterator", but it's unclear to me why it didn't qualify as an "output_iterator". There is an "input_output_iterator_tag" in "boost/iterator/detail/facade_iterator_category.hpp", so it would have been possible for the iterator to be both "input_iterator" and "output_iterator". However, it seems to me that "input_output_iterator_tag" is never used in the Boost.Iterator library. I would have to read more about "output_iterator" to understand whether Boost.Iterator is correct here. With my current understanding of "output_iterator", I would say it's a bug in "boost/iterator/detail/facade_iterator_category.hpp".
Perhaps somebody with more knowledge about "output_iterator" and Boost.Iterator can explain to me why an iterator using the "boost::random_access_traversal_tag" for the "CategoryOrTraversal" template parameter of "iterator_facade" will never get the category "output_iterator" (or "input_output_iterator_tag").
Of course I could go on and read more about "output_iterator", or find out whether the Boost.Iterator documentation has to say something about this issue, but since I only came to this problem because I wanted to help Jesse Perla on a problem with boost::multi_array, I would much prefer if an "iterator expert" could "take over". Regards, Thomas

Thomas Klimpel wrote:
Dear iterator experts,
Jesse Perla recently reported that boost::multi_array fails compilation for many basic tasks on MSVC 2010. I investigated the failures, because I had already investigated other failures on MSVC 2010 reported by Jesse Perla for boost::ublas. While I'm quite familiar with boost::ublas, I'm a complete novice with respect to boost::multi_array and boost::iterator.
I could track the failures to a specific (intentional?) behavior of iterator_facade from Boost.Iterator (more specifically of facade_iterator_category.hpp):
http://lists.boost.org/Archives/boost/2010/03/163039.php
Thomas Klimpel wrote:
What effectively happens it that the iterator gets the category "input_iterator", but std::copy wants to have an "output_iterator". I think I understand why the iterator doesn't satisfies the requirement of a "forward_iterator", but it's unclear to me why it didn't qualify as an "output_iterator". There is an "input_output_iterator_tag" in "boost/iterator/detail/facade_iterator_category.hpp", so it would have been possible for the iterator to be both "input_iterator" and "output_iterator". However, it seems to me that "input_output_iterator_tag" is never used in the Boost.Iterator library. I would have to read more about "output_iterator" to understand whether Boost.Iterator is correct here. With my current understanding of "output_iterator", I would say it's a bug in "boost/iterator/detail/facade_iterator_category.hpp".
Perhaps somebody with more knowledge about "output_iterator" and Boost.Iterator can explain to me why an iterator using the "boost::random_access_traversal_tag" for the "CategoryOrTraversal" template parameter of "iterator_facade" will never get the category "output_iterator" (or "input_output_iterator_tag").
Of course I could go on and read more about "output_iterator", or find out whether the Boost.Iterator documentation has to say something about this issue, but since I only came to this problem because I wanted to help Jesse Perla on a problem with boost::multi_array, I would much prefer if an "iterator expert" could "take over".
Regards, Thomas
Without being an expert, a quick review of http://www.boost.org/doc/libs/1_42_0/libs/iterator/doc/iterator_facade.html#... shows that std::output_iterator_tag is never chosen as the iterator category by boost::iterator_facade. It also shows that the behavior of choosing std::input_iterator_tag for your particular case is the documented behavior. Of course, this doesn't shed any light on the motivation behind this decision. It may have been the intention that output iterators should be explicitly declared as such by specifying the category as std::output_iterator_tag. This aspect of the standard that treats iterators with proxy references as automatically have the very lowest of traversal categories is annoying at best. I've resorted to overriding the traversal category normally deduced by boost::iterator_facade; I haven't had any ill effects yet, but I'm not sure *technically* what parts of the standard (and *practically*, in terms of the various implementations on the various compilers) depends on, e.g., dereferenced random-access iterators returning lvalue references. - Jeff

Jeffrey Hellrung wrote:
Without being an expert, a quick review of
http://www.boost.org/doc/libs/1_42_0/libs/iterator/doc/iterator_facade. html#iterator-category
shows that std::output_iterator_tag is never chosen as the iterator category by boost::iterator_facade. It also shows that the behavior of choosing std::input_iterator_tag for your particular case is the documented behavior.
Thanks, so at least I know now that I didn't misinterpreted the code in "facade_iterator_category.hpp". I fact, the documentation in "facade_iterator_category.hpp" itself was less clear with respect to this questions, so that I already wondered whether I had missed something in boost::multi_array causing the iterator not to be an output_iterator. excerp from "facade_iterator_category.hpp": // // Convert an iterator_facade's traversal category, Value parameter, // and ::reference type to an appropriate old-style category. // // If writability has been disabled per the above metafunction, the // result will not be convertible to output_iterator_tag. // // Otherwise, if Traversal == single_pass_traversal_tag, the following // conditions will result in a tag that is convertible both to // input_iterator_tag and output_iterator_tag: // // 1. Reference is a reference to non-const // 2. Reference is not a reference and is convertible to Value // template <class Traversal, class ValueParam, class Reference> struct iterator_facade_default_category Regards, Thomas
participants (2)
-
Jeffrey Hellrung
-
Thomas Klimpel