[concept_check] Should OutputIterator check for output_iterator_tag?

Hello, In tracking down a problem with Boost.MultiArray, I'd like to write a test case that exhibits the failure. Specifically, certain iterators should be models of OutputIterator, and it's my impression that an output iterator needs to have an iterator_category that's convertible to output_iterator_tag(). However, it looks like the OutputIterator Concept checker in the concept checker library does not check that the output iterator has such an iterator_category. Is that an oversight, or is it not the case that an output iterator have a category that's convertible to output_iterator_tag? It looks like InputIterator, RandomAccessIterator concept checkers perform such a check. Thanks, Ron

on Mon Jan 09 2012, Ronald Garcia <rxg-AT-cs.cmu.edu> wrote:
Hello,
In tracking down a problem with Boost.MultiArray, I'd like to write a test case that exhibits the failure. Specifically, certain iterators should be models of OutputIterator, and it's my impression that an output iterator needs to have an iterator_category that's convertible to output_iterator_tag(). However, it looks like the OutputIterator Concept checker in the concept checker library does not check that the output iterator has such an iterator_category. Is that an oversight, or is it not the case that an output iterator have a category that's convertible to output_iterator_tag? It looks like InputIterator, RandomAccessIterator concept checkers perform such a check.
All I can tell you is that I tried not to change the meaning of the existing checker for OutputIterator... so technically you'll have to ask Jeremy ;-) Come to think of it, since random_access_iterator_tag is not convertible to output_iterator_tag, and char* is definitely an OutputIterator, I don't think you can make that requirement. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Hi Dave (and Jeremy), Thanks for the note. I didn't realize that random_access_iterator_tag is not convertible to output_iterator! At least looking at page 607 of n1905 (Draft Standard), that seems to clearly be the case. To top that off, reading page 605 of n1905, it sounds like every iterator must have an iterator_category defined, but input_iterator_tag is a perfectly fine iterator category. It sounds like any iterator that at least models input_iterator does not need to have an iterator_category that is convertible to output_iterator_tag. Does that sound right? If so, then there is a bug in MSVC 2010's implementation of copy, which is the trac issue that I have been diagnosing: https://svn.boost.org/trac/boost/ticket/4874
(IDL refers to _ITERATOR_DEBUG_LEVEL, which is 0 in release mode and 2 in debug mode.)
-- The problem is that multi_array iterators report themselves as input iterators, which can't be written to (e.g. as the destination of a copy()). Under IDL=0, copy() doesn't actually care how its destination iterator is marked with an iterator category tag, it just tries to write to the destination iterator, and that works. Under IDL > 0, copy() wants to know whether its source and destination iterators are both random-access, in which case it can perform a range check and unwrap the destination iterator for increased performance. It does this by overloading foo(input_iterator_tag, output_iterator_tag) and foo(random_access_iterator_tag, random_access_iterator_tag) and calling foo(category(source), category(destination)). If both source and destination are random-access, both overloads are viable (i.e. callable) and the second overload is preferred, so it's actually called. Otherwise, source is required to be at least an input iterator (maybe stronger) and destination is required to be at least an output iterator (maybe stronger) so the first overload must be viable and the second overload will be non-viable, so the first overload wins by default.
However, if the destination is not marked as an output iterator or stronger, then the first overload is non-viable as well as the second, so overload resolution fails and boom.
Best, Ron On Jan 10, 2012, at 4:09 AM, Dave Abrahams wrote:
on Mon Jan 09 2012, Ronald Garcia <rxg-AT-cs.cmu.edu> wrote:
Hello,
In tracking down a problem with Boost.MultiArray, I'd like to write a test case that exhibits the failure. Specifically, certain iterators should be models of OutputIterator, and it's my impression that an output iterator needs to have an iterator_category that's convertible to output_iterator_tag(). However, it looks like the OutputIterator Concept checker in the concept checker library does not check that the output iterator has such an iterator_category. Is that an oversight, or is it not the case that an output iterator have a category that's convertible to output_iterator_tag? It looks like InputIterator, RandomAccessIterator concept checkers perform such a check.
All I can tell you is that I tried not to change the meaning of the existing checker for OutputIterator... so technically you'll have to ask Jeremy ;-)
Come to think of it, since random_access_iterator_tag is not convertible to output_iterator_tag, and char* is definitely an OutputIterator, I don't think you can make that requirement.
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Good, it sounds like I got it right :) (I hope it was on purpose but I honestly don't recall!) Cheers, Jeremy On Tue, Jan 10, 2012 at 1:40 PM, Ronald Garcia <rxg@cs.cmu.edu> wrote:
Hi Dave (and Jeremy),
Thanks for the note. I didn't realize that random_access_iterator_tag is not convertible to output_iterator! At least looking at page 607 of n1905 (Draft Standard), that seems to clearly be the case. To top that off, reading page 605 of n1905, it sounds like every iterator must have an iterator_category defined, but input_iterator_tag is a perfectly fine iterator category.
It sounds like any iterator that at least models input_iterator does not need to have an iterator_category that is convertible to output_iterator_tag. Does that sound right? If so, then there is a bug in MSVC 2010's implementation of copy, which is the trac issue that I have been diagnosing:
https://svn.boost.org/trac/boost/ticket/4874
(IDL refers to _ITERATOR_DEBUG_LEVEL, which is 0 in release mode and 2 in debug mode.)
-- The problem is that multi_array iterators report themselves as input iterators, which can't be written to (e.g. as the destination of a copy()). Under IDL=0, copy() doesn't actually care how its destination iterator is marked with an iterator category tag, it just tries to write to the destination iterator, and that works. Under IDL > 0, copy() wants to know whether its source and destination iterators are both random-access, in which case it can perform a range check and unwrap the destination iterator for increased performance. It does this by overloading foo(input_iterator_tag, output_iterator_tag) and foo(random_access_iterator_tag, random_access_iterator_tag) and calling foo(category(source), category(destination)). If both source and destination are random-access, both overloads are viable (i.e. callable) and the second overload is preferred, so it's actually called. Otherwise, source is required to be at least an input iterator (maybe stronger) and destination is required to be at least an output iterator (maybe stronger) so the first overload must be viable and the second overload will be non-viable, so the first overload wins by default.
However, if the destination is not marked as an output iterator or stronger, then the first overload is non-viable as well as the second, so overload resolution fails and boom.
Best, Ron
On Jan 10, 2012, at 4:09 AM, Dave Abrahams wrote:
on Mon Jan 09 2012, Ronald Garcia <rxg-AT-cs.cmu.edu> wrote:
Hello,
In tracking down a problem with Boost.MultiArray, I'd like to write a
test case that exhibits the failure. Specifically, certain iterators
should be models of OutputIterator, and it's my impression that an
output iterator needs to have an iterator_category that's convertible
to output_iterator_tag(). However, it looks like the OutputIterator
Concept checker in the concept checker library does not check that the
output iterator has such an iterator_category. Is that an oversight,
or is it not the case that an output iterator have a category that's
convertible to output_iterator_tag? It looks like InputIterator,
RandomAccessIterator concept checkers perform such a check.
All I can tell you is that I tried not to change the meaning of the existing checker for OutputIterator... so technically you'll have to ask Jeremy ;-)
Come to think of it, since random_access_iterator_tag is not convertible to output_iterator_tag, and char* is definitely an OutputIterator, I don't think you can make that requirement.
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- ____________________________________ Jeremy Siek <jeremy.siek@colorado.edu> http://ecee.colorado.edu/~siek/ Assistant Professor Dept. of Electrical, Computer, and Energy Engineering University of Colorado at Boulder

I think you'd have found out almost immediately had you gotten this one wrong! on Tue Jan 10 2012, Jeremy Siek <jeremy.siek-AT-colorado.edu> wrote:
Good, it sounds like I got it right :) (I hope it was on purpose but I honestly don't recall!)
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
participants (3)
-
Dave Abrahams
-
Jeremy Siek
-
Ronald Garcia