Topic: when is output_iterator_tag required?


Author: Ronald Garcia <garcia@osl.iu.edu>
Date: Sat, 11 Feb 2012 08:40:17 -0800 (PST)
Raw View
VC 2010 under debug mode fails to compile specializes std::copy() to
check iterator tags. If the source iterators have iterator_category
random_access_iterator_tag, then they use a special implementation and
so on.  The fall-back case
though requires that the iterator_category be output_iterator tag.  I
have an iterator that I would like to be the target of copy, but it is
neither bidirectional nor random_access, so its iterator_category is
input_iterator_tag.  As a result, VC 2010 fails to compile calls to
copy, though only when in debug mode.
The outstanding question I have is whether it is necessary or even
legal for an iterator to have an iterator_category that is somehow
both input_iterator_tag AND output_iterator tag simultaneously.

First I say *legal* because in my copy of a standard draft, (24.3.3)
says:
For every iterator of type Iterator,
iterator_traits<Iterator>::iterator_category shall be defined to be
the most specific category tag that describes the iterator   s behavior.

I'm unclear on whether that can be any tag other than the specific
ones listed. In particular, can I legally create a class that inherits
from both input_iterator_tag and output_iterator tag to merge them.

Second, I say *necessary* because while input_iterator_tag,
forward_iterator_tag, bidirectional_iterator_tag, and
random_access_iterator_tag  form an inheritance chain, none of them
inherit from output_iterator_tag.  Furthermore, const_iterators like
"const int *" are not OutputIterators but seem to still be
RandomAccessIterators:  at least they still have category
random_access_iterator_tag.  So in this case I'm not sure when (if
ever) it is necessary to have an iterator category that is convertible
to output_iterator_tag.
I can't find information in practice or theory.  For instance, the
Boost.Concept library doesn't ever even look at the iterator_category
when checking OutputIterator concept.   All uses of
output_iterator_tag I can find in the standard are things like
back_inserter and front_inserter, things that are not "really"
iterators, so to speak.

So my question is:  if I have an iterator that satisfies the
expression requirements of InputIterator and OutputIterator,is there
*any* wording in the C++ Standard that dictates what is legally the
proper thing to do with its iterator_category?  If so, where can I
find it?  If it should have input_iterator_tag, then there is a (quite
reasonable) bug in VC++ 2010's debug mode.  If it should have both,
then I have a fix for my particular situation.  If there is no clear
answer, then the standard is underspecified on this matter.

Thank you,
Ron Garcia


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]




Author: =?windows-1252?Q?Daniel_Kr=FCgler?=<daniel.kruegler@googlemail.com>
Date: Sun, 12 Feb 2012 08:08:46 -0800 (PST)
Raw View
Am 11.02.2012 17:40, schrieb Ronald Garcia:
>  VC 2010 under debug mode fails to compile specializes std::copy() to
>  check iterator tags. If the source iterators have iterator_category
>  random_access_iterator_tag, then they use a special implementation and
>  so on.  The fall-back case
>  though requires that the iterator_category be output_iterator tag.  I
>  have an iterator that I would like to be the target of copy, but it is
>  neither bidirectional nor random_access, so its iterator_category is
>  input_iterator_tag.  As a result, VC 2010 fails to compile calls to
>  copy, though only when in debug mode.
>  The outstanding question I have is whether it is necessary or even
>  legal for an iterator to have an iterator_category that is somehow
>  both input_iterator_tag AND output_iterator tag simultaneously.

Do you mean a user-defined class type somehow like

struct in_out_iterator_tag : std::input_iterator_tag,
std::output_iterator_tag {};

?

>  First I say *legal* because in my copy of a standard draft, (24.3.3)
>  says:
>  For every iterator of type Iterator,
>  iterator_traits<Iterator>::iterator_category shall be defined to be
>  the most specific category tag that describes the iterator   s behavior.
>
>  I'm unclear on whether that can be any tag other than the specific
>  ones listed. In particular, can I legally create a class that inherits
>  from both input_iterator_tag and output_iterator tag to merge them.

The standard is maybe a bit underspecified about the valid types
provided to the typedef iterator_category with iterator_traits, but
there seems to be the intent of allowing only exactly one of the
standardized tags. I agree that the wording does not *exactly* say that,
but I find it hard to read it otherwise.

>  Second, I say *necessary* because while input_iterator_tag,
>  forward_iterator_tag, bidirectional_iterator_tag, and
>  random_access_iterator_tag  form an inheritance chain, none of them
>  inherit from output_iterator_tag.  Furthermore, const_iterators like
>  "const int *" are not OutputIterators but seem to still be
>  RandomAccessIterators:  at least they still have category
>  random_access_iterator_tag.  So in this case I'm not sure when (if
>  ever) it is necessary to have an iterator category that is convertible
>  to output_iterator_tag.

It clearly is not necessary, there is no single evidence for that
interpretation in the standard.

>  I can't find information in practice or theory.  For instance, the
>  Boost.Concept library doesn't ever even look at the iterator_category
>  when checking OutputIterator concept.   All uses of
>  output_iterator_tag I can find in the standard are things like
>  back_inserter and front_inserter, things that are not "really"
>  iterators, so to speak.

Why are they not iterators?

What about ostream_iterator, ostreambuf_iterator, or raw_storage_iterator?

>  So my question is:  if I have an iterator that satisfies the
>  expression requirements of InputIterator and OutputIterator,is there
>  *any* wording in the C++ Standard that dictates what is legally the
>  proper thing to do with its iterator_category?

I don't think that the standard has a clear answer to this question, but
there is evidence for the sign that you cannot combine both, see e.g.
Table 105. On the other hand this is some kind of contradiction, because
output iterators are somewhat orthogonal to all other iterators
categories, see also [iterator.requirements.general] p4 (emphasis mine):

"Iterators that **further** satisfy the requirements of output iterators
are called mutable iterators. Nonmutable iterators are referred to as
constant iterators."

>  If so, where can I
>  find it?  If it should have input_iterator_tag, then there is a (quite
>  reasonable) bug in VC++ 2010's debug mode.  If it should have both,
>  then I have a fix for my particular situation.  If there is no clear
>  answer, then the standard is underspecified on this matter.

A clarification of the standard might help. On the other hand the
iterator categories are the somehow broken, because they they don't
cleanly separate between traversal and access functionality. Nonetheless
your example should be used to open a library issue for this. This
increases the pressure to solve these problems ;-)

I recommend to send a corresponding issue to the address mentioned here:

http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html

For details of the submission please read here:

http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#submit_issue

Thanks&  Greetings from Bremen,

Daniel Kr   gler


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]