Topic: Should value_type, reference_type, etc. be in standard iterator types?
Author: kuyper@wizard.net
Date: Wed, 28 Mar 2007 09:39:43 CST Raw View
Chris Jefferson wrote:
> On Mar 27, 10:01 pm, "Daniel Kr gler" <daniel.krueg...@googlemail.com>
> wrote:
..
> > I don't understand what you mean with "messing around"
> > here. The C++ standard has provided std::iterator_traits as an
> > customization point for exactly this reason and you are allowed
> > to specialize it for your types, see section 24.3.3. You can
> > also use std::iterator as a helper class or any other approach
> > that fulfills the constraints.
>
> I wasn't sure if it was allowed for implementaitons to specialize for
> the types in the library. Clearly I can specialise it for my types,
> but is an implementer allowed to specialise it for std::list iterators
> for example? I suspect so, but I wasn't sure if it was allowed or not.
> I know that some kinds of changes aren't allowed, as they are
> observable by users.
It is not only allowed, but mandatory. Section 24.3.1p1 says:
> To implement algorithms only in terms of iterators, it is often necessary to determine the value and difference
> types that correspond to a particular iterator type. Accordingly, it is required that if Iterator is the type of an
> iterator, the types
>
> iterator_traits<Iterator>::difference_type
> iterator_traits<Iterator>::value_type
> iterator_traits<Iterator>::iterator_category
>
> be defined as the iterator's difference type, value type, and iterator category, respectively.
It is the responsibility of the implementation to ensure that
iterator_traits<> is appropriately specialized for every iterator type
defined by the standard library. In particular, it should be
appropriately specialized for std::iterator<>. It is the
responsibility of the user to ensure that iterator_traits<> is
appropriately specialized for any iterator type that a standard
library template is instantiated with. Implementations of the standard
library templates are entitled to assume that iterator_traits<> has
been appropriately specialized for any iterator type they are
instantiated with.
Since iterator_traits<> is already specialized for pointer types, this
is only an issue for iterators that are class types; but it's not a
difficult issue: deriving from std::iterator<> is sufficient to meet
that requirement.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Chris Jefferson" <4zumanga@gmail.com>
Date: Tue, 27 Mar 2007 12:28:02 CST Raw View
Here is an interesting question that came up recently. Is the
following standards conforming?
list<int>::iterator::value_type t;
It works on every compiler I have access to and I've seen a lot of
people using it, but I'm now not sure the standard requires it work.
The most obvious manner of making sure iterator_traits works for non-
pointer iterator types is to insert value_type, difference_type, etc.
into the iterator. However, is this required? I can think of two ways
around this:
1) Specialise iterator_traits for the iterators of each of the
standard containers
2) Make iterator_traits a friend of the iterators and make the
typedefs private.
The reason this came up originally is:
vector<int>::iterator::value_type t;
In compilers where vector::iterator is a raw pointer, this code
clearly won't work. In the case where iterator is not a pointer, I can
think of 3 readings of the standard.
1) This has to work, as the standard doesn't allow messing around with
the definition of iterator_traits.
2) This may or may not work depending on how vector<int>::iterator is
implemented.
3) Implementations should try to stop this working as a QOI issue.
Any comments / suggestions? Would it possibly be worth saying this
typedefs have to be defined, simply because they are so frequently
defined? Perhaps even require that vector::iterator is a class in C+
+09 just to standardise behaviour?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "=?iso-8859-1?q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Tue, 27 Mar 2007 15:01:02 CST Raw View
Chris Jefferson schrieb:
> Here is an interesting question that came up recently. Is the
> following standards conforming?
>
> list<int>::iterator::value_type t;
It might compile, or not - no guarantee. The iterator types
of all containers of the container library are implementation
defined and no such guarantees are given. An exception
to this rule is, that all reverse iterator's do provide this
guarantee, because they are specified to be std::reverse_iterator's
(which derives from std::iterator and thus is supposed to
provide these typedef's). Personally I never used this
knowledge as advantage to access reverse_iterator typedef's
by directly asking the iterator type itslef, I always use
Container-typedef's or std::iterator_traits.
In this special situation I see no reason, why you should not
use list<int>::value_type (which is int, of course).
In general std::iterator_traits is the way to go - why don't you
use it?
> The most obvious manner of making sure iterator_traits works for non-
> pointer iterator types is to insert value_type, difference_type, etc.
> into the iterator. However, is this required? I can think of two ways
> around this:
It is not required. The iterator types *specified* in the standard
do follow this convention (specified), but no user/implementation-
defined iterator is required to do so. This is a good thing, IMO.
> 1) Specialise iterator_traits for the iterators of each of the
> standard containers
> 2) Make iterator_traits a friend of the iterators and make the
> typedefs private.
These are the obvious solutions, but not the only choices.
> The reason this came up originally is:
>
> vector<int>::iterator::value_type t;
>
> In compilers where vector::iterator is a raw pointer, this code
> clearly won't work. In the case where iterator is not a pointer, I can
> think of 3 readings of the standard.
First, I don't see any reason, why you shouldn't use either
ContainerType::value_type of
std::iterator_traits<ItratorType>::value_type.
std::iterator_traits is the perfect example of an interface
adaption. IMO it is a bad programming style, if I have to think
about the actual implementation of an implementation-defined
entity. If you differentiate between iterator types at this level,
where do you stop? Consequently all types, which need
any form of an adaptor, are wrongly written, then?
> 1) This has to work, as the standard doesn't allow messing around with
> the definition of iterator_traits.
I don't understand what you mean with "messing around"
here. The C++ standard has provided std::iterator_traits as an
customization point for exactly this reason and you are allowed
to specialize it for your types, see section 24.3.3. You can
also use std::iterator as a helper class or any other approach
that fulfills the constraints.
> 2) This may or may not work depending on how vector<int>::iterator is
> implemented.
The standard guarantees no more and no less than this.
> 3) Implementations should try to stop this working as a QOI issue.
IMO, this is a very illogical reasoning. I cannot see why
preventing it would increase QOI, because such typedefs don't
represent a danger by itself.
> Any comments / suggestions? Would it possibly be worth saying this
> typedefs have to be defined, simply because they are so frequently
> defined? Perhaps even require that vector::iterator is a class in C+
> +09 just to standardise behaviour?
It would be *possible* to require that, but I see no convincing
reasons for that. IMO, you should accept this pattern of interface
adaption and use std::iterator_traits - it was invented for this
reason.
Interface adaptions foster code robustness and remove
unnecessary dependencies.
Greetings from Bremen,
Daniel Kr gler
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Tue, 27 Mar 2007 20:08:06 GMT Raw View
on Tue Mar 27 2007, "Chris Jefferson" <4zumanga-AT-gmail.com> wrote:
> Here is an interesting question that came up recently. Is the
> following standards conforming?
>
> list<int>::iterator::value_type t;
>
> It works on every compiler I have access to and I've seen a lot of
> people using it, but I'm now not sure the standard requires it work.
It does not. The correct way to access the iterator's value_type is
through iterator_traits.
> The most obvious manner of making sure iterator_traits works for non-
> pointer iterator types is to insert value_type, difference_type, etc.
> into the iterator. However, is this required?
No
> I can think of two ways
> around this:
>
> 1) Specialise iterator_traits for the iterators of each of the
> standard containers
> 2) Make iterator_traits a friend of the iterators and make the
> typedefs private.
Right
> The reason this came up originally is:
>
> vector<int>::iterator::value_type t;
>
> In compilers where vector::iterator is a raw pointer, this code
> clearly won't work. In the case where iterator is not a pointer, I can
> think of 3 readings of the standard.
>
> 1) This has to work, as the standard doesn't allow messing around with
> the definition of iterator_traits.
That is not the intention of the standard. The standard allows
specialization of standard library types so long as they retain the
right semantics.
> 2) This may or may not work depending on how vector<int>::iterator is
> implemented.
> 3) Implementations should try to stop this working as a QOI issue.
>
> Any comments / suggestions? Would it possibly be worth saying this
> typedefs have to be defined, simply because they are so frequently
> defined? Perhaps even require that vector::iterator is a class in C+
> +09 just to standardise behaviour?
There are many things about iterators that should be fixed, but I
don't think this is on the list.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Chris Jefferson" <4zumanga@gmail.com>
Date: Tue, 27 Mar 2007 17:59:52 CST Raw View
On Mar 27, 10:01 pm, "Daniel Kr gler" <daniel.krueg...@googlemail.com>
wrote:
> Chris Jefferson schrieb:
>
> > Here is an interesting question that came up recently. Is the
> > following standards conforming?
>
> > list<int>::iterator::value_type t;
>
>
> In this special situation I see no reason, why you should not
> use list<int>::value_type (which is int, of course).
> In general std::iterator_traits is the way to go - why don't you
> use it?
As a general comment, I point out that I personally don't use this, I
always use iterator_traits. However I've read a reasonable amount code
that did do this, and pondered on if it was legal or not.
> > 1) This has to work, as the standard doesn't allow messing around with
> > the definition of iterator_traits.
>
> I don't understand what you mean with "messing around"
> here. The C++ standard has provided std::iterator_traits as an
> customization point for exactly this reason and you are allowed
> to specialize it for your types, see section 24.3.3. You can
> also use std::iterator as a helper class or any other approach
> that fulfills the constraints.
I wasn't sure if it was allowed for implementaitons to specialize for
the types in the library. Clearly I can specialise it for my types,
but is an implementer allowed to specialise it for std::list iterators
for example? I suspect so, but I wasn't sure if it was allowed or not.
I know that some kinds of changes aren't allowed, as they are
observable by users.
> IMO, this is a very illogical reasoning. I cannot see why
> preventing it would increase QOI, because such typedefs don't
> represent a danger by itself.
Well, it't annoying when you move your code from one compiler where
this works, to another one where it doesn't (how I discovered the
dodgy code in the first place).
Chris
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]