diff --git a/doc/default.css b/doc/default.css index 0e4226a..8c1e342 100644 --- a/doc/default.css +++ b/doc/default.css @@ -5,6 +5,8 @@ :version: $Revision$ :copyright: This stylesheet has been placed in the public domain. +boostinspect:nolicense + Default cascading style sheet for the HTML output of Docutils. */ diff --git a/doc/interoperability-revisited.rst b/doc/interoperability-revisited.rst index e75a2c6..add3546 100755 --- a/doc/interoperability-revisited.rst +++ b/doc/interoperability-revisited.rst @@ -5,6 +5,9 @@ :date: $Date$ :copyright: Copyright Thomas Witt 2004. +.. Distributed under the Boost +.. Software License, Version 1.0. (See accompanying +.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Problem ======= diff --git a/doc/iter-issue-list.html b/doc/iter-issue-list.html deleted file mode 100755 index abe7c7a..0000000 --- a/doc/iter-issue-list.html +++ /dev/null @@ -1,5268 +0,0 @@ - - - -
- - -Date: | -2004-01-27 |
---|
Submitter: | Pete Becker | -
---|---|
Status: | New | -
The proposal includes:
--enum iterator_access { - readable_iterator = 1, writable_iterator = 2, - swappable_iterator = 4, lvalue_iterator = 8 -}; --
In general, the standard specifies thing like this as a bitmask -type with a list of defined names, and specifies neither the exact -type nor the specific values. Is there a reason for iterator_access -to be more specific?
-Proposed resolution: | |
---|---|
The iterator_access enum will be removed, -so this is no longer an issue. See the resolution to 9.15. | -
Submitter: | Pete Becker | -
---|---|
Status: | New | -
In general, we've provided operational semantics for things like -operator++. That is, we've said that ++iter must work, without -requiring either a member function or a non-member function. -iterator_facade specifies most operators as member -functions. There's no inherent reason for these to be members, so -we should remove this requirement. Similarly, some operations are -specified as non-member functions but could be implemented as -members. Again, the standard doesn't make either of these choices, -and TR1 shouldn't, either. So: operator*(), operator++(), -operator++(int), operator--(), operator--(int), -operator+=, operator-=, operator-(difference_type), -operator-(iterator_facade instance), and operator+ should -be specified with operational semantics and not explicitly required -to be members or non-members.
-Proposed resolution: | |
---|---|
Not a defect. | -|
Rationale: | The standard uses valid expressions such as ++iter -in requirements tables, such as for input iterator. However, for -classes, such as reverse_iterator, the standard uses function -prototypes, as we have done here for -iterator_facade. Further, the prototype specification does -not prevent the implementor from using members or non-members, -since nothing the user can do in a conforming program can detect -how the function is implemented. | -
Submitter: | Pete Becker | -
---|---|
Status: | New | -
The only discussion of what this means is in a note, so is -non-normative. Further, the note seems to be incorrect. It says -that enable_if_interoperable only works for types that "are -interoperable, by which we mean they are convertible to each -other." This requirement is too strong: it should be that one of -the types is convertible to the other. N1541 48
-Proposed resolution: | |
---|---|
Add normative text. Relax requirements in the -proposed way. -Change: --[Note: The enable_if_interoperable template used above is -for exposition purposes. The member operators should be only be -in an overload set provided the derived types Dr1 and -Dr2 are interoperable, by which we mean they are -convertible to each other. The enable_if_interoperable -approach uses SFINAE to take the operators out of the overload -set when the types are not interoperable.]- To: --- |
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
In every place where enable_if_convertible is used it's used like -this (simplified):
--template<class T> -struct C -{ - template<class T1> - C(T1, enable_if_convertible<T1, T>::type* = 0); -}; --
The idea being that this constructor won't compile if T1 isn't -convertible to T. As a result, the constructor won't be considered -as a possible overload when constructing from an object x where the -type of x isn't convertible to T. In addition, however, each of -these constructors has a requires clause that requires -convertibility, so the behavior of a program that attempts such a -construction is undefined. Seems like the enable_if_convertible -part is irrelevant, and should be removed. There are two -problems. First, enable_if_convertible is never specified, so we -don't know what this is supposed to do. Second: we could reasonably -say that this overload should be disabled in certain cases or we -could reasonably say that behavior is undefined, but we can't say -both.
-Thomas Witt writes that the goal of putting in -enable_if_convertible here is to make sure that a specific overload -doesn't interfere with the generic case except when that overload -makes sense. He agrees that what we currently have is deficient. -Dave Abrahams writes that there is no conflict with the requires -cause because the requires clause only takes effect when the -function is actually called. The presence of the constructor -signature can/will be detected by is_convertible without violating -the requires clause, and thus it makes a difference to disable -those constructor instantiations that would be disabled by -enable_if_convertible even if calling them invokes undefined -behavior. There was more discussion on the reflector: -c++std-lib-12312, c++std-lib-12325, c++std-lib- 12330, -c++std-lib-12334, c++std-lib-12335, c++std-lib-12336, -c++std-lib-12338, c++std-lib- 12362.
-Proposed resolution: | |
---|---|
Change: --[Note: The enable_if_convertible<X,Y>::type expression -used in this section is for exposition purposes. The converting -constructors for specialized adaptors should be only be in an -overload set provided that an object of type X is -implicitly convertible to an object of type Y. The -enable_if_convertible approach uses SFINAE to take the -constructor out of the overload set when the types are not -implicitly convertible.]- To: --- |
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
The title says it all; this is probably just a typo.
-Proposed resolution: | |
---|---|
Remove the 'bool'. | -
Submitter: | Pete Becker | -
---|---|
Status: | New | -
iterator_adaptor has a private member named m_iterator. Presumably -this is for exposition only, since it's an implementation -detail. It needs to be marked as such.
-Proposed resolution: | |
---|---|
In [lib.iterator.adaptor] -Change: --Base m_iterator; -- to: --Base m_iterator; // exposition only -- |
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
iterator_adpator() has a Requires clause, that Base must be default -constructible. iterator_adaptor(Base) has no Requires clause, -although the Returns clause says that the Base member is copy -construced from the argument (this may actually be an oversight in -N1550, which doesn't require iterators to be copy constructible or -assignable).
-Proposed resolution: | |
---|---|
Add a requirements section for the template -parameters of iterator_adaptor, and state that Base must be Copy -Constructible and Assignable. -N1550 does in fact include requirements for copy constructible -and assignable in the requirements tables. To clarify, we've also -added the requirements to the text. - |
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
similar to 9.3, "Specialized Adaptors" has a note describing -enable_if_convertible. This should be normative text.
-Proposed resolution: | |
---|---|
Changed it to normative -text. See the resolution of 9.4 | -
Submitter: | Pete Becker | -
---|---|
Status: | New | -
reverse iterator "flips the direction of the base iterator's -motion". This needs to be more formal, as in the current -standard. Something like: "iterates through the controlled sequence -in the opposite direction"
-Proposed resolution: | |
---|---|
Change: --The reverse iterator adaptor flips the direction of a base -iterator's motion. Invoking operator++() moves the base -iterator backward and invoking operator--() moves the base -iterator forward.- to: --The reverse iterator adaptor iterates through the adapted iterator -range in the opposite direction.- |
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
reverse_iterator::dereference is specified as calling a function -named 'prior' which has no specification.
-Proposed resolution: | |||
---|---|---|---|
Change the specification to avoid using prior as follows. -Remove: --typename reverse_iterator::reference dereference() const { return *prior(this->base()); } -- And at the end of the operations section add: --- |
-|||
Rationale: | The style of specification has changed because of issue 9.37x. | -
Submitter: | Pete Becker | -
---|---|
Status: | New | -
Transform iterator has a two-part specification: it does this, in -other words, it does that. "In other words" always means "I didn't -say it right, so I'll try again." We need to say it once.
-Proposed resolution: | |
---|---|
Change: --The transform iterator adapts an iterator by applying some function -object to the result of dereferencing the iterator. In other words, -the operator* of the transform iterator first dereferences the -base iterator, passes the result of this to the function object, and -then returns the result.- to: --The transform iterator adapts an iterator by modifying the -operator* to apply a function object to the result of -dereferencing the iterator and returning the result.- |
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
transform_iterator has a private member named 'm_f' which should be -marked "exposition only."
-Proposed resolution: | |
---|---|
Mark the member m_f as exposition -only. Note/DWA: I think this is NAD because the user can't -detect it, though I'm happy to mark it exposition only. -Change: --UnaryFunction m_f; -- to: --UnaryFunction m_f; // exposition only -- |
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
The description of Counting iterator is unclear. "The counting -iterator adaptor implements dereference by returning a reference to -the base object. The other operations are implemented by the base -m_iterator, as per the inheritance from iterator_adaptor."
-Proposed resolution: | |
---|---|
Change: --The counting iterator adaptor implements dereference by -returning a reference to the base object. The other operations -are implemented by the base m_iterator, as per the -inheritance from iterator_adaptor.- to: --counting_iterator adapts an object by adding an -operator* that returns the current value of the object. All -other iterator operations are forwarded to the adapted object.- |
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
Counting iterator has the following note:
--[Note: implementers are encouraged to provide an implementation -of distance_to and a difference_type that avoids overflows in the -cases when the Incrementable type is a numeric type.]-
I'm not sure what this means. The user provides a template argument -named Difference, but there's no difference_type. I assume this is -just a glitch in the wording. But if implementors are encouraged to -ignore this argument if it won't work right, why is it there?
-Proposed resolution: | |
---|---|
The difference_type was inherited from -iterator_adaptor. However, we've removed the explicit -inheritance, so explicit typedefs have been added. See the -resolution of 9.37x. | -
Submitter: | Dave Abrahams | -
---|---|
Status: | New | -
Shortly after N1550 was accepted, we discovered that an iterator's -lvalueness can be determined knowing only its value_type. This -predicate can be calculated even for old-style iterators (on whose -reference type the standard places few requirements). A trait in -the Boost iterator library does it by relying on the compiler's -unwillingness to bind an rvalue to a T& function template -parameter. Similarly, it is possible to detect an iterator's -readability knowing only its value_type. Thus, any interface which -asks the user to explicitly describe an iterator's lvalue-ness or -readability seems to introduce needless complexity.
-Proposed resolution: | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
In N1550: -Remove: --- After: --Like the old iterator requirements, we provide tags for -purposes of dispatching based on the traversal concepts. The -tags are related via inheritance so that a tag is convertible -to another tag if the concept associated with the first tag is -a refinement of the second tag.- Add: --- From the Readable Iterator Requirements table, remove: --- From the Writable Iterator Requirements table, remove: --- From the Swappable Iterator Requirements table, remove: --- From [lib.iterator.synopsis] replace: --template <class Iterator> struct is_readable; -template <class Iterator> struct is_writable; -template <class Iterator> struct is_swappable; -template <class Iterator> struct traversal_category; - -enum iterator_access { readable_iterator = 1, writable_iterator = 2, - swappable_iterator = 4, lvalue_iterator = 8 }; - -template <unsigned int access_bits, class TraversalTag> -struct iterator_tag : /* appropriate old category or categories */ { - static const iterator_access access = - (iterator_access)access_bits & - (readable_iterator | writable_iterator | swappable_iterator); - typedef TraversalTag traversal; -}; -- with: --template <class Iterator> struct is_readable_iterator; -template <class Iterator> struct iterator_traversal; -- In [lib.iterator.traits], remove: --- Change: --- to: --- In N1530: -In [lib.iterator.helper.synopsis]: -Change: --const unsigned use_default_access = -1; - -struct iterator_core_access { /* implementation detail */ }; - -template < - class Derived - , class Value - , unsigned AccessCategory - , class TraversalCategory - , class Reference = Value& - , class Difference = ptrdiff_t -> -class iterator_facade; - -template < - class Derived - , class Base - , class Value = use_default - , unsigned Access = use_default_access - , class Traversal = use_default - , class Reference = use_default - , class Difference = use_default -> -class iterator_adaptor; - -template < - class Iterator - , class Value = use_default - , unsigned Access = use_default_access - , class Traversal = use_default - , class Reference = use_default - , class Difference = use_default -> -class indirect_iterator; -- To: --struct iterator_core_access { /* implementation detail */ }; - -template < - class Derived - , class Value - , class CategoryOrTraversal - , class Reference = Value& - , class Difference = ptrdiff_t -> -class iterator_facade; - -template < - class Derived - , class Base - , class Value = use_default - , class CategoryOrTraversal = use_default - , class Reference = use_default - , class Difference = use_default -> -class iterator_adaptor; - -template < - class Iterator - , class Value = use_default - , class CategoryOrTraversal = use_default - , class Reference = use_default - , class Difference = use_default -> -class indirect_iterator; -- Change: --template < - class Incrementable - , unsigned Access = use_default_access - , class Traversal = use_default - , class Difference = use_default -> -class counting_iterator -- To: --template < - class Incrementable - , class CategoryOrTraversal = use_default - , class Difference = use_default -> -class counting_iterator; -- In [lib.iterator.facade]: -Change: --template < - class Derived - , class Value - , unsigned AccessCategory - , class TraversalCategory - , class Reference = /* see below */ - , class Difference = ptrdiff_t -> -class iterator_facade { -- to: --template < - class Derived - , class Value - , class CategoryOrTraversal - , class Reference = Value& - , class Difference = ptrdiff_t -> -class iterator_facade { -- Change: --typedef iterator_tag<AccessCategory, TraversalCategory> iterator_category; -- to: --typedef /* see below */ iterator_category; -- Change: --// Comparison operators -template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, - class Dr2, class V2, class AC2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1, Dr2, bool>::type // exposition -operator ==(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, - iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); - -template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, - class Dr2, class V2, class AC2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1, Dr2, bool>::type -operator !=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, - iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); - -template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, - class Dr2, class V2, class AC2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1, Dr2, bool>::type -operator <(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, - iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); - -template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, - class Dr2, class V2, class AC2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1, Dr2, bool>::type -operator <=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, - iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); - -template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, - class Dr2, class V2, class AC2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1, Dr2, bool>::type -operator >(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, - iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); - -template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, - class Dr2, class V2, class AC2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1, Dr2, bool>::type -operator >=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, - iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); - -template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, - class Dr2, class V2, class AC2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1, Dr2, bool>::type -operator >=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, - iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); - -// Iterator difference -template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, - class Dr2, class V2, class AC2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1, Dr2, bool>::type -operator -(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, - iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); - -// Iterator addition -template <class Derived, class V, class AC, class TC, class R, class D> -Derived operator+ (iterator_facade<Derived, V, AC, TC, R, D> const&, - typename Derived::difference_type n) -- to: --// Comparison operators -template <class Dr1, class V1, class TC1, class R1, class D1, - class Dr2, class V2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1,Dr2,bool>::type // exposition -operator ==(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, - iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); - -template <class Dr1, class V1, class TC1, class R1, class D1, - class Dr2, class V2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1,Dr2,bool>::type -operator !=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, - iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); - -template <class Dr1, class V1, class TC1, class R1, class D1, - class Dr2, class V2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1,Dr2,bool>::type -operator <(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, - iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); - -template <class Dr1, class V1, class TC1, class R1, class D1, - class Dr2, class V2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1,Dr2,bool>::type -operator <=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, - iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); - -template <class Dr1, class V1, class TC1, class R1, class D1, - class Dr2, class V2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1,Dr2,bool>::type -operator >(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, - iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); - -template <class Dr1, class V1, class TC1, class R1, class D1, - class Dr2, class V2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1,Dr2,bool>::type -operator >=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, - iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); - -// Iterator difference -template <class Dr1, class V1, class TC1, class R1, class D1, - class Dr2, class V2, class TC2, class R2, class D2> -/* see below */ -operator-(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, - iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); - -// Iterator addition -template <class Dr, class V, class TC, class R, class D> -Derived operator+ (iterator_facade<Dr,V,TC,R,D> const&, - typename Derived::difference_type n); - -template <class Dr, class V, class TC, class R, class D> -Derived operator+ (typename Derived::difference_type n, - iterator_facade<Dr,V,TC,R,D> const&); -- After the iterator_facade synopsis, add: -The iterator_category member of iterator_facade is --iterator-category(CategoryOrTraversal, value_type, reference) -- where iterator-category is defined as follows: --iterator-category(C,R,V) := - if (C is convertible to std::input_iterator_tag - || C is convertible to std::output_iterator_tag - ) - return C - - else if (C is not convertible to incrementable_traversal_tag) - the program is ill-formed - - else return a type X satisfying the following two constraints: - - 1. X is convertible to X1, and not to any more-derived - type, where X1 is defined by: - - if (R is a reference type - && C is convertible to forward_traversal_tag) - { - if (C is convertible to random_access_traversal_tag) - X1 = random_access_iterator_tag - else if (C is convertible to bidirectional_traversal_tag) - X1 = bidirectional_iterator_tag - else - X1 = forward_iterator_tag - } - else - { - if (C is convertible to single_pass_traversal_tag - && R is convertible to V) - X1 = input_iterator_tag - else - X1 = C - } - - 2. category-to-traversal(X) is convertible to the most - derived traversal tag type to which X is also - convertible, and not to any more-derived traversal tag - type. -- |
-
--In [lib.iterator.facade] iterator_facade requirements:
-Remove:
--AccessCategory must be an unsigned value which uses no more -bits than the greatest value of iterator_access.-In the Iterator Adaptor section, change:
--Several of the template parameters of iterator_adaptor default -to use_default (or use_default_access).-to:
--Several of the template parameters of iterator_adaptor default -to use_default.-In [lib.iterator.special.adaptors]:
-Change:
--template < - class Iterator - , class Value = use_default - , unsigned Access = use_default_access - , class Traversal = use_default - , class Reference = use_default - , class Difference = use_default -> -class indirect_iterator --to:
--template < - class Iterator - , class Value = use_default - , class CategoryOrTraversal = use_default - , class Reference = use_default - , class Difference = use_default -> -class indirect_iterator --Change:
--template < - class Iterator2, class Value2, unsigned Access2, class Traversal2 - , class Reference2, class Difference2 -> -indirect_iterator( --to:
--template < - class Iterator2, class Value2, class Category2 - , class Reference2, class Difference2 -> -indirect_iterator( --Change:
--template < - class Incrementable - , unsigned Access = use_default_access - , class Traversal = use_default - , class Difference = use_default -> -class counting_iterator --to:
--template < - class Incrementable - , class CategoryOrTraversal = use_default - , class Difference = use_default -> -class counting_iterator --Change:
--typedef iterator_tag< - writable_iterator - , incrementable_traversal_tag -> iterator_category; --to:
--typedef std::output_iterator_tag iterator_category;-In [lib.iterator.adaptor]
-Change:
--template < - class Derived - , class Base - , class Value = use_default - , unsigned Access = use_default_access - , class Traversal = use_default - , class Reference = use_default - , class Difference = use_default -> -class iterator_adaptor --To:
--template < - class Derived - , class Base - , class Value = use_default - , class CategoryOrTraversal = use_default - , class Reference = use_default - , class Difference = use_default -> -class iterator_adaptor --
Rationale: | - |
---|
Submitter: | Dave Abrahams | -
---|---|
Status: | New | -
is_writable_iterator returns false positives for forward iterators -whose value_type has a private assignment operator, or whose -reference type is not a reference (currently legal).
-Proposed Resolution: | |
---|---|
See the resolution to 9.15. | -
Submitter: | Dave Abrahams | -
---|---|
Status: | New | -
is_swappable_iterator has the same problems as -is_writable_iterator. In addition, if we allow users to write their -own iter_swap functions it's easy to imagine old-style iterators -for which is_swappable returns false negatives.
-Proposed Resolution: | |
---|---|
See the resolution to 9.15. | -
Submitter: | Dave Abrahams | -
---|---|
Status: | New | -
I am concerned that there is little use for any of is_readable, -is_writable, or is_swappable, and that not only do they unduly -constrain iterator implementors but they add overhead to -iterator_facade and iterator_adaptor in the form of a template -parameter which would otherwise be unneeded. Since we can't -implement two of them accurately for old-style iterators, I am -having a hard time justifying their impact on the rest of the -proposal(s).
-Proposed Resolution: | |
---|---|
See the resolution to 9.15. | -
Submitter: | Dave Abrahams | -
---|---|
Status: | New | -
The proposed iterator_tag class template accepts an "access bits" -parameter which includes a bit to indicate the iterator's -lvalueness (whether its dereference operator returns a reference to -its value_type. The relevant part of N1550 says:
--The purpose of the lvalue_iterator part of the iterator_access -enum is to communicate to iterator_tagwhether the reference type -is an lvalue so that the appropriate old category can be chosen -for the base class. The lvalue_iterator bit is not recorded in -the iterator_tag::access data member.-
The lvalue_iterator bit is not recorded because N1550 aims to -improve orthogonality of the iterator concepts, and a new-style -iterator's lvalueness is detectable by examining its reference -type. This inside/outside difference is awkward and confusing.
-Proposed Resolution: | |
---|---|
The iterator_tag class will be removed, so this is no longer an issue. -See the resolution to 9.15. | -
Submitter: | Dave Abrahams | -
---|---|
Status: | New | -
Howard Hinnant pointed out some inconsistencies with the naming of -these tag types:
--incrementable_iterator_tag // ++r, r++ -single_pass_iterator_tag // adds a == b, a != b -forward_traversal_iterator_tag // adds multi-pass -bidirectional_traversal_iterator_tag // adds --r, r-- -random_access_traversal_iterator_tag // adds r+n,n+r,etc. --
Howard thought that it might be better if all tag names contained -the word "traversal". It's not clear that would result in the best -possible names, though. For example, incrementable iterators can -only make a single pass over their input. What really distinguishes -single pass iterators from incrementable iterators is not that they -can make a single pass, but that they are equality -comparable. Forward traversal iterators really distinguish -themselves by introducing multi-pass capability. Without entering -a "Parkinson's Bicycle Shed" type of discussion, it might be worth -giving the names of these tags (and the associated concepts) some -extra attention.
-Proposed resolution: | |||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Change the names of the traversal tags to the -following names: --incrementable_traversal_tag -single_pass_traversal_tag -forward_traversal_tag -bidirectional_traversal_tag -random_access_traversal_tag -- In [lib.iterator.traversal]: -Change: --- to: --- Change: --- to: --- Change: --- to: --- Change: --- to: --- Change: --- to: --- In [lib.iterator.synopsis], change: --struct incrementable_iterator_tag { }; -struct single_pass_iterator_tag : incrementable_iterator_tag { }; -struct forward_traversal_tag : single_pass_iterator_tag { }; -- to: --struct incrementable_traversal_tag { }; -struct single_pass_traversal_tag : incrementable_traversal_tag { }; -struct forward_traversal_tag : single_pass_traversal_tag { }; -- Remove: --struct null_category_tag { }; -struct input_output_iterator_tag : input_iterator_tag, output_iterator_tag {}; -- |
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
The first template argument to iterator_facade is named Derived, -and the proposal says:
--The Derived template parameter must be a class derived from -iterator_facade.-
First, iterator_facade is a template, so cannot be derived -from. Rather, the class must be derived from a specialization of -iterator_facade. More important, isn't Derived required to be the -class that is being defined? That is, if I understand it right, the -definition of D here this is not valid:
--class C : public iterator_facade<C, ... > { ... }; -class D : public iterator_facade<C, ...> { ... }; --
In the definition of D, the Derived argument to iterator_facade is -a class derived from a specialization of iterator_facade, so the -requirement is met. Shouldn't the requirement be more like "when -using iterator_facade to define an iterator class Iter, the class -Iter must be derived from a specialization of iterator_facade whose -first template argument is Iter." That's a bit awkward, but at the -moment I don't see a better way of phrasing it.
-Proposed resolution: | |
---|---|
In [lib.iterator.facade] -Remove: --The Derived template parameter must be a class derived from -iterator_facade.- Change: --The following table describes the other requirements on the -Derived parameter. Depending on the resulting iterator's -iterator_category, a subset of the expressions listed in the table -are required to be valid. The operations in the first column must be -accessible to member functions of class iterator_core_access.- to: --The following table describes the typical valid expressions on -iterator_facade's Derived parameter, depending on the -iterator concept(s) it will model. The operations in the first -column must be made accessible to member functions of class -iterator_core_access. In addition, -static_cast<Derived*>(iterator_facade*) shall be well-formed.- In [lib.iterator.adaptor] -Change: --The iterator_adaptor is a base class template derived from -an instantiation of iterator_facade.- to: --Each specialization of the iterator_adaptor class template -is derived from a specialization of iterator_facade.- Change: --The Derived template parameter must be a derived class of -iterator_adaptor.- To: --static_cast<Derived*>(iterator_adaptor*) shall be well-formed.- |
-
[Note: The proposed resolution to Issue 9.37 contains related -changes]
-Submitter: | Pete Becker | -
---|---|
Status: | New | -
The proposal says:
--template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, -class Dr2, class V2, class AC2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1, Dr2, bool>::type -operator -(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, -iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); --
Shouldn't the return type be one of the two iterator types? Which -one? The idea is that if one of the iterator types can be converted -to the other type, then the subtraction is okay. Seems like the -return type should then be the type that was converted to. Is that -right?
-Proposed resolution: | |
---|---|
See resolution to 9.34. | -
Submitter: | Pete Becker | -
---|---|
Status: | New | -
In the table that lists the required (sort of) member functions of -iterator types that are based on iterator_facade, the entry for -c.equal(y) says:
--true iff c and y refer to the same position. Implements c == y -and c != y. The second sentence is inside out. c.equal(y) does -not implement either of these operations. It is used to implement -them. Same thing in the description of c.distance_to(z).-
Proposed resolution: | |
---|---|
remove "implements" descriptions from -table. See resolution to 9.34 | -
Submitter: | Pete Becker | -
---|---|
Status: | New | -
Several of the descriptions use the name X without defining -it. This seems to be a carryover from the table immediately above -this section, but the text preceding that table says "In the table -below, X is the derived iterator type." Looks like the X:: -qualifiers aren't really needed; X::reference can simply be -reference, since that's defined by the iterator_facade -specialization itself.
-Proposed resolution: | |||||
---|---|---|---|---|---|
Remove references to X. -In [lib.iterator.facade] operations operator->() const;: --- |
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
Several of the member functions return a Derived object or a -Derived&. Their Effects clauses end with:
--return *this; --
This should be
--return *static_cast<Derived*>(this); --
Proposed resolution: | |
---|---|
In [lib.iterator.facade], in the effects clause -of the following operations: --Derived& operator++() -Derived& operator--() -Derived& operator+=(difference_type n) -Derived& operator-=(difference_type n) --
|
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
The returns clause for operator[](difference_type n) const -says:
--Returns: an object convertible to X::reference and holding a copy -p of a+n such that, for a constant object v of type -X::value_type, X::reference(a[n] = v) is equivalent to p = v. -This needs to define 'a', but assuming it's supposed to be -*this (or maybe *(Derived*)this), it still isn't clear -what this says. Presumably, the idea is that you can index off of -an iterator and assign to the result. But why the requirement -that it hold a copy of a+n? Granted, that's probably how it's -implemented, but it seems over-constrained. And the last phrase -seems wrong. p is an iterator; there's no requirement that you -can assign a value_type object to it. Should that be *p = v? -But why the cast in reference(a[n] = v)?-
Proposed resolution: | |||||
---|---|---|---|---|---|
In section operator[]: --- In [lib.iterator.facade] operations: --- |
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
operator- has both an effects clause and a returns -clause. Looks like the returns clause should be removed.
-Proposed resolution: | |||
---|---|---|---|
Remove the returns clause. -In [lib.iterator.facade] operations: -
|
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
The default constructor returns "An instance of indirect_iterator -with a default constructed base object", but the constructor that -takes an Iterator object returns "An instance of indirect_iterator -with the iterator_adaptor subobject copy constructed from x." The -latter is the correct form, since it does not reach inside the base -class for its semantics. So the default constructor shoudl return -"An instance of indirect_iterator with a default-constructed -iterator_adaptor subobject."
-Proposed resolution: | |||||
---|---|---|---|---|---|
|
-|||||
Rationale: | Inheritance from iterator_adaptor has been removed, so we instead -give the semantics in terms of the (exposition only) member -m_iterator. | -
Submitter: | Pete Becker | -
---|---|
Status: | New | -
The templated constructor that takes an indirect_iterator with a -different set of template arguments says that it returns "An -instance of indirect_iterator that is a copy of [the argument]". -But the type of the argument is different from the type of the -object being constructed, and there is no description of what -a "copy" means. The Iterator template parameter for the argument -must be convertible to the Iterator template parameter for the type -being constructed, which suggests that the argument's contained -Iterator object should be converted to the target type's Iterator -type. Is that what's meant here? -(Pete later writes: In fact, this problem is present in all of the -specialized adaptors that have a constructor like this: the -constructor returns "a copy" of the argument without saying what a -copy is.)
-Proposed resolution: | |||||
---|---|---|---|---|---|
|
-|||||
Rationale: | Inheritance from iterator_adaptor has been removed, so we -instead give the semantics in terms of the member m_iterator. | -
Submitter: | Pete Becker | -
---|---|
Status: | New | -
The specialized adaptors that take both a Value and a Reference -template argument all take them in that order, i.e. Value precedes -Reference in the template argument list, with the exception of -transform_iterator, where Reference precedes Value. This seems like -a possible source of confusion. Is there a reason why this order is -preferable?
-Proposed resolution: | |
---|---|
NAD | -|
Rationale: | defaults for Value depend on Reference. A sensible -Value can almost always be computed from Reference. The first -parameter is UnaryFunction, so the argument order is already -different from the other adapters. | -
Submitter: | Pete Becker | -
---|---|
Status: | New | -
function_output_iterator requirements says: "The UnaryFunction must -be Assignable, Copy Constructible, and the expression f(x) must be -valid, where f is an object of type UnaryFunction and x is an -object of a type accepted by f."
-Everything starting with "and," somewhat reworded, is actually a -constraint on output_proxy::operator=. All that's needed to create -a function_output_iterator object is that the UnaryFunction type be -Assignable and CopyConstructible. That's also sufficient to -dereference and to increment such an object. It's only when you try -to assign through a dereferenced iterator that f(x) has to work, -and then only for the particular function object that the iterator -holds and for the particular value that is being assigned.
-Proposed resolution: | |
---|---|
After function_output_iterator& operator++(int); add: --private: - UnaryFunction m_f; // exposition only --
After the requirements section, add: - |
-
function_output_iterator models
--function_output_iterator is a model of the Writable and -Incrementable Iterator concepts.-
Returns: | An instance of function_output_iterator with -f stored as a data member. | -
---|
Effects: | Constructs an instance of function_output_iterator -with m_f constructed from f. | -
---|
output_proxy operator*();
-Returns: | An instance of output_proxy constructed with -a copy of the unary function f. | -
---|
operator*();
-Returns: | An object r of unspecified type such that r = t -is equivalent to m_f(t) for all t. | -
---|
function_output_iterator::output_proxy operations
-output_proxy(UnaryFunction& f);
-Returns: | An instance of output_proxy with f stored as -a data member. | -
---|
template <class T> output_proxy& operator=(const T& value);
-Effects: | -m_f(value); -return *this; -- |
-
---|
Change:
--explicit function_output_iterator(const UnaryFunction& f = UnaryFunction()); --
to:
--explicit function_output_iterator(); - -explicit function_output_iterator(const UnaryFunction& f); --
Submitter: | Pete Becker | -
---|---|
Status: | New | -
This means someone can store an output_proxy object for later use, -whatever that means. It also constrains output_proxy to hold a copy -of the function object, rather than a pointer to the iterator -object. Is all this mechanism really necessary?
-Proposed resolution: | |
---|---|
See issue 9.31. | -
Submitter: | Pete Becker | -
---|---|
Status: | New | -
c++std-lib-12333:
--N1550 requires that for a Readable Iterator a of type X, *a -returns an object of type -iterator_traits<X>::reference. istreambuf_iterator::operator* -returns charT, but istreambuf_iterator::reference is -charT&. So am I overlooking something, or is -istreambuf_iterator not Readable.-
Proposed resolution: | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Remove all constraints on -iterator_traits<X>::reference in Readable Iterator and Lvalue -Iterator. Change Lvalue Iterator to refer to T& instead of -iterator_traits<X>::reference. -
From the Input Iterator Requirements table, remove: --- Change: --- to: ---
Change: --- to: --- At the end of the section reverse_iterator models, add: -The type iterator_traits<Iterator>::reference must be the type of -*i, where i is an object of type Iterator. - |
-||||||||||||||||||||||||||||
Rationale: | Ideally there should be requirements on the reference -type, however, since Readable Iterator is suppose to correspond -to the current standard iterator requirements (which do not place -requirements on the reference type) we will leave them off for -now. There is a DR in process with respect to the reference type -in the stadard iterator requirements. Once that is resolved we -will revisit this issue for Readable Iterator and Lvalue -Iterator. -We added Assignable to the requirements for Readable -Iterator. This is needed to have Readable Iterator coincide with -the capabilities of Input Iterator. - |
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
c++std-lib-12562:
--The template functions operator==, operator!=, -operator<, operator<=, operator>, operator>=, and -operator- that take two arguments that are specializations of -iterator_facade have no specification. The template function -operator+ that takes an argument that is a specialization of -iterator_facade and an argument of type difference_type has no -specification.-
Proposed resolution: | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Add the missing specifications. --template <class Dr, class V, class TC, class R, class D> -Derived operator+ (iterator_facade<Dr,V,TC,R,D> const&, - typename Derived::difference_type n); - -template <class Dr, class V, class TC, class R, class D> -Derived operator+ (typename Derived::difference_type n, - iterator_facade<Dr,V,TC,R,D> const&); --
-template <class Dr1, class V1, class TC1, class R1, class D1, - class Dr2, class V2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1,Dr2,bool>::type -operator ==(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, - iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); --
-template <class Dr1, class V1, class TC1, class R1, class D1, - class Dr2, class V2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1,Dr2,bool>::type -operator !=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, - iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); --
-template <class Dr1, class V1, class TC1, class R1, class D1, - class Dr2, class V2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1,Dr2,bool>::type -operator <(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, - iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); --
-template <class Dr1, class V1, class TC1, class R1, class D1, - class Dr2, class V2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1,Dr2,bool>::type -operator <=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, - iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); --
-template <class Dr1, class V1, class TC1, class R1, class D1, - class Dr2, class V2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1,Dr2,bool>::type -operator >(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, - iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); --
-template <class Dr1, class V1, class TC1, class R1, class D1, - class Dr2, class V2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1,Dr2,bool>::type -operator >=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, - iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); --
-template <class Dr1, class V1, class TC1, class R1, class D1, - class Dr2, class V2, class TC2, class R2, class D2> -typename enable_if_interoperable<Dr1,Dr2,difference>::type -operator -(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, - iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); --
|
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
c++std-lib-12563:
---The table listing the functions required for types derived from -iterator_facade has two functions named equal and two named -distance_to:
--c.equal(b) -c.equal(y) -c.distance_to(b) -c.distance_to(z) --where b and c are const objects of the derived type, y and z are -constant objects of certain iterator types that are interoperable -with the derived type. Seems like the 'b' versions are -redundant: in both cases, the other version will take a 'b'. In -fact, iterator_adaptor is specified to use iterator_facade, but -does not provide the 'b' versions of these functions.
-Are the 'b' versions needed?
-
Proposed resolution: | |||||||||
---|---|---|---|---|---|---|---|---|---|
Remove the 'b' versions. -In iterator_facade requirements, remove: --- and remove: --- |
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
c++std-lib-12636:
---The table that lists required functions for the derived type X -passed to iterator_facade lists, among others:
-for a single pass iterator:
--c.equal(b) -c.equal(y) --where b and c are const X objects, and y is a const object of a -single pass iterator that is interoperable with X. Since X is -interoperable with itself, c.equal(b) is redundant. There is a -difference in their descriptions, but its meaning isn't -clear. The first is "true iff b and c are equivalent", and the -second is "true iff c and y refer to the same position." Is there -a difference between the undefined term "equivalent" and "refer -to the same position"?
-Similarly, for a random access traversal iterator:
--c.distance_to(b) -c.distance_to(z) --where z is a constant object of a random access traversal -iterator that is interoperable with X. Again, X is interoperable -with itself, so c.distance_to(b) is redundant. Also, the -specification for c.distance_to(z) isn't valid. It's written -as "equivalent to distance(c, z)". The template function distance -takes two arguments of the same type, so distance(c, z) isn't -valid if c and z are different types. Should it be -distance(c, (X)z)?
-
Proposed resolution: | |||||||||
---|---|---|---|---|---|---|---|---|---|
Removed the 'b' versions (see 9.35) and added the cast. -Change: --- to: --- |
-
Submitter: | Pete Becker | -
---|---|
Status: | New | -
c++std-lib-12696: -The paper requires that iterator_adaptor be derived from an -appropriate instance of iterator_facade, and that most of the specific -forms of adaptors be derived from appropriate instances of -iterator_adaptor. That seems like overspecification, and we ought to -look at specifying these things in terms of what the various templates -provide rather than how they're implemented.
-Proposed resolution: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Remove the specfication of inheritance, and add explicit -specification of all the functionality that was inherited from the -specialized iterators. -In iterator_adaptor, inheritance is retained, sorry NAD. Also, -the Interoperable Iterators concept is added to the new iterator -concepts, and this concept is used in the specification of the -iterator adaptors. -In n1550, after [lib.random.access.traversal.iterators], add: --- In N1530: --- |
-
iterator_adaptor base class parameters
---The V', C', R', and D' parameters of the iterator_facade -used as a base class in the summary of iterator_adaptor -above are defined as follows:
--V' = if (Value is use_default) - return iterator_traits<Base>::value_type - else - return Value - -C' = if (CategoryOrTraversal is use_default) - return iterator_traversal<Base>::type - else - return CategoryOrTraversal - -R' = if (Reference is use_default) - if (Value is use_default) - return iterator_traits<Base>::reference - else - return Value& - else - return Reference - -D' = if (Difference is use_default) - return iterator_traits<Base>::difference_type - else - return Difference --
In [lib.iterator.special.adaptors]
-Change:
--class indirect_iterator - : public iterator_adaptor</* see discussion */> -{ - friend class iterator_core_access; --
to:
--class indirect_iterator -{ - public: - typedef /* see below */ value_type; - typedef /* see below */ reference; - typedef /* see below */ pointer; - typedef /* see below */ difference_type; - typedef /* see below */ iterator_category; --
Change:
--private: // as-if specification - typename indirect_iterator::reference dereference() const - { - return **this->base(); - } --
to:
-- Iterator const& base() const; - reference operator*() const; - indirect_iterator& operator++(); - indirect_iterator& operator--(); -private: - Iterator m_iterator; // exposition --
After the synopsis add:
---The member types of indirect_iterator are defined -according to the following pseudo-code, where V is -iterator_traits<Iterator>::value_type
--if (Value is use_default) then - typedef remove_const<pointee<V>::type>::type value_type; -else - typedef remove_const<Value>::type value_type; - -if (Reference is use_default) then - if (Value is use_default) then - typedef indirect_reference<V>::type reference; - else - typedef Value& reference; -else - typedef Reference reference; - -if (Value is use_default) then - typedef pointee<V>::type* pointer; -else - typedef Value* pointer; - -if (Difference is use_default) - typedef iterator_traits<Iterator>::difference_type difference_type; -else - typedef Difference difference_type; - -if (CategoryOrTraversal is use_default) - typedef iterator-category( - iterator_traversal<Iterator>::type,``reference``,``value_type`` - ) iterator_category; -else - typedef iterator-category( - CategoryOrTraversal,``reference``,``value_type`` - ) iterator_category; --
[Note: See resolution to 9.44y for a description of pointee and -indirect_reference]
-After the requirements section, add:
-indirect_iterator models
---In addition to the concepts indicated by iterator_category -and by iterator_traversal<indirect_iterator>::type, a -specialization of indirect_iterator models the following -concepts, Where v is an object of -iterator_traits<Iterator>::value_type:
----
-- Readable Iterator if reference(*v) is convertible to -value_type.
-- Writable Iterator if reference(*v) = t is a valid -expression (where t is an object of type -indirect_iterator::value_type)
-- Lvalue Iterator if reference is a reference type.
-indirect_iterator<X,V1,C1,R1,D1> is interoperable with -indirect_iterator<Y,V2,C2,R2,D2> if and only if X is -interoperable with Y.
-
Before indirect_iterator(); add:
--In addition to the operations required by the concepts described -above, specializations of indirect_iterator provide the -following operations.-
Returns: | An instance of indirect_iterator with -the iterator_adaptor subobject copy constructed from x. | -
---|
Returns: | An instance of indirect_iterator with -m_iterator copy constructed from x. | -
---|
At the end of the indirect_iterator operations add:
---Iterator const& base() const;
--
-- - - - - Returns: m_iterator -reference operator*() const;
--
-- - - - - Returns: **m_iterator -indirect_iterator& operator++();
--
-- - - - Effects: ++m_iterator -- - Returns: *this -indirect_iterator& operator--();
--
-- - - - Effects: --m_iterator -- - Returns: *this -
Change:
--template <class Iterator> -class reverse_iterator : - public iterator_adaptor< reverse_iterator<Iterator>, Iterator > -{ - friend class iterator_core_access; --
to:
--template <class Iterator> -class reverse_iterator -{ -public: - typedef iterator_traits<Iterator>::value_type value_type; - typedef iterator_traits<Iterator>::reference reference; - typedef iterator_traits<Iterator>::pointer pointer; - typedef iterator_traits<Iterator>::difference_type difference_type; - typedef /* see below */ iterator_category; --
Change:
--private: // as-if specification - typename reverse_iterator::reference dereference() const { return *prior(this->base()); } - - void increment() { --this->base_reference(); } - void decrement() { ++this->base_reference(); } - - void advance(typename reverse_iterator::difference_type n) - { - this->base_reference() += -n; - } - - template <class OtherIterator> - typename reverse_iterator::difference_type - distance_to(reverse_iterator<OtherIterator> const& y) const - { - return this->base_reference() - y.base(); - } --
to:
-- Iterator const& base() const; - reference operator*() const; - reverse_iterator& operator++(); - reverse_iterator& operator--(); -private: - Iterator m_iterator; // exposition --
reverse_iterator requirements
-The base Iterator must be a model of Bidirectional Traversal -Iterator. The resulting reverse_iterator will be a model of the -most refined standard traversal and access concepts that are modeled -by Iterator.
-reverse_iterator requirements
-Iterator must be a model of Bidirectional Traversal Iterator.
-reverse_iterator models
---A specialization of reverse_iterator models the same iterator -traversal and iterator access concepts modeled by its Iterator -argument. In addition, it may model old iterator concepts -specified in the following table:
--
-- - -- - - - - If I models -then reverse_iterator<I> models -- Readable Lvalue Iterator, -Bidirectional Traversal Iterator -Bidirectional Iterator -- Writable Lvalue Iterator, -Bidirectional Traversal Iterator -Mutable Bidirectional Iterator -- Readable Lvalue Iterator, -Random Access Traversal Iterator -Random Access Iterator -- - Writable Lvalue Iterator, -Random Access Traversal Iterator -Mutable Random Access Iterator -reverse_iterator<X> is interoperable with -reverse_iterator<Y> if and only if X is interoperable with -Y.
-
Returns: | An instance of reverse_iterator with a -default constructed base object. | -
---|
Effects: | Constructs an instance of reverse_iterator with m_iterator -default constructed. | -
---|
Effects: | Constructs an instance of reverse_iterator with a -base object copy constructed from x. | -
---|
Effects: | Constructs an instance of reverse_iterator with a -m_iterator constructed from x. | -
---|
Returns: | An instance of reverse_iterator that is a copy of r. | -
---|
Effects: | Constructs instance of reverse_iterator whose -m_iterator subobject is constructed from y.base(). | -
---|
Iterator const& base() const;
-Returns: | m_iterator | -
---|
reference operator*() const;
-Effects: | - |
---|
-Iterator tmp = m_iterator; -return *--tmp; --
reverse_iterator& operator++();
-Effects: | --m_iterator | -
---|---|
Returns: | *this | -
reverse_iterator& operator--();
-Effects: | ++m_iterator | -
---|---|
Returns: | *this | -
Change:
--class transform_iterator - : public iterator_adaptor</* see discussion */> -{ - friend class iterator_core_access; --
to:
--class transform_iterator -{ -public: - typedef /* see below */ value_type; - typedef /* see below */ reference; - typedef /* see below */ pointer; - typedef iterator_traits<Iterator>::difference_type difference_type; - typedef /* see below */ iterator_category; --
After UnaryFunction functor() const; add:
--Iterator const& base() const; -reference operator*() const; -transform_iterator& operator++(); -transform_iterator& operator--(); --
Change:
--private: - typename transform_iterator::value_type dereference() const; - UnaryFunction m_f; -}; --
to:
--private: - Iterator m_iterator; // exposition only - UnaryFunction m_f; // exposition only -}; --
The type Iterator must at least model Readable Iterator. The -resulting transform_iterator models the most refined of the -following that is also modeled by Iterator.
----
-- Writable Lvalue Iterator if -result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type -is a non-const reference.
-- Readable Lvalue Iterator if -result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type -is a const reference.
-- Readable Iterator otherwise.
-
The transform_iterator models the most refined standard traversal -concept that is modeled by Iterator.
-The reference type of transform_iterator is -result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type. -The value_type is remove_cv<remove_reference<reference> >::type.
-After the requirements section, add:
-transform_iterator models
---The resulting transform_iterator models the most refined of the -following options that is also modeled by Iterator.
----
-- Writable Lvalue Iterator if -transform_iterator::reference is a non-const -reference.
-- Readable Lvalue Iterator if -transform_iterator::reference is a const reference.
-- Readable Iterator otherwise.
-The transform_iterator models the most refined standard traversal -concept that is modeled by the Iterator argument.
-If transform_iterator is a model of Readable Lvalue Iterator then -it models the following original iterator concepts depending on what -the Iterator argument models.
--
-- - -- - - - - If Iterator models -then transform_iterator models -- Single Pass Iterator -Input Iterator -- Forward Traversal Iterator -Forward Iterator -- Bidirectional Traversal Iterator -Bidirectional Iterator -- - Random Access Traversal Iterator -Random Access Iterator -If transform_iterator models Writable Lvalue Iterator then it is a -mutable iterator (as defined in the old iterator requirements).
-transform_iterator<F1, X, R1, V1> is interoperable with -transform_iterator<F2, Y, R2, V2> if and only if X is -interoperable with Y.
-
Remove the private operations section heading and remove:
--``typename transform_iterator::value_type dereference() const;`` - -:Returns: ``m_f(transform_iterator::dereference());`` --
After the entry for functor(), add:
--``Iterator const& base() const;`` - -:Returns: ``m_iterator`` - - -``reference operator*() const;`` - -:Returns: ``m_f(*m_iterator)`` - - -``transform_iterator& operator++();`` - -:Effects: ``++m_iterator`` -:Returns: ``*this`` - - -``transform_iterator& operator--();`` - -:Effects: ``--m_iterator`` -:Returns: ``*this`` --
Change:
--template <class Predicate, class Iterator> -class filter_iterator - : public iterator_adaptor< - filter_iterator<Predicate, Iterator>, Iterator - , use_default - , /* see details */ - > -{ - public: --
to:
--template <class Predicate, class Iterator> -class filter_iterator -{ - public: - typedef iterator_traits<Iterator>::value_type value_type; - typedef iterator_traits<Iterator>::reference reference; - typedef iterator_traits<Iterator>::pointer pointer; - typedef iterator_traits<Iterator>::difference_type difference_type; - typedef /* see below */ iterator_category; --
Change:
--private: // as-if specification - void increment() - { - ++(this->base_reference()); - satisfy_predicate(); - } - - void satisfy_predicate() - { - while (this->base() != this->m_end && !this->m_predicate(*this->base())) - ++(this->base_reference()); - } - - Predicate m_predicate; - Iterator m_end; --
to:
-- Iterator const& base() const; - reference operator*() const; - filter_iterator& operator++(); -private: - Predicate m_pred; // exposition only - Iterator m_iter; // exposition only - Iterator m_end; // exposition only --
After the requirements section, add:
-filter_iterator models
---The concepts that filter_iterator models are dependent on which -concepts the Iterator argument models, as specified in the -following tables.
--
-- - -- - - - - If Iterator models -then filter_iterator models -- Single Pass Iterator -Single Pass Iterator -- - Forward Traversal Iterator -Forward Traversal Iterator --
-- - -- - - - - If Iterator models -then filter_iterator models -- Readable Iterator -Readable Iterator -- Writable Iterator -Writable Iterator -- - Lvalue Iterator -Lvalue Iterator --
-- - -- - - - - If Iterator models -then filter_iterator models -- Readable Iterator, Single Pass Iterator -Input Iterator -- Readable Lvalue Iterator, Forward Traversal Iterator -Forward Iterator -- - Writable Lvalue Iterator, Forward Traversal Iterator -Mutable Forward Iterator -filter_iterator<P1, X> is interoperable with filter_iterator<P2, Y> -if and only if X is interoperable with Y.
-
Returns: | a filter_iterator whose -predicate is a default constructed Predicate and -whose end is a default constructed Iterator. | -
---|
Effects: | Constructs a filter_iterator whose``m_pred``, m_iter, and m_end -members are a default constructed. | -
---|
Returns: | A filter_iterator at position x that filters according -to predicate f and that will not increment past end. | -
---|
Effects: | Constructs a filter_iterator where m_iter is either -the first position in the range [x,end) such that f(*m_iter) == true -or else``m_iter == end``. The member m_pred is constructed from -f and m_end from end. | -
---|
Returns: | A filter_iterator at position x that filters -according to a default constructed Predicate -and that will not increment past end. | -
---|
Effects: | Constructs a filter_iterator where m_iter is either -the first position in the range [x,end) such that m_pred(*m_iter) == true -or else``m_iter == end``. The member m_pred is default constructed. | -
---|
Returns: | A copy of iterator t. | -
---|
Effects: | Constructs a filter iterator whose members are copied from t. | -
---|
Returns: | A copy of the predicate object used to construct *this. | -
---|
Returns: | m_pred | -
---|
Returns: | The object end used to construct *this. | -
---|
Returns: | m_end | -
---|
At the end of the operations section, add:
---reference operator*() const;
--
-- - - - - Returns: *m_iter -filter_iterator& operator++();
--
-- - - - Effects: Increments m_iter and then continues to -increment m_iter until either m_iter == m_end -or m_pred(*m_iter) == true. -- - Returns: *this -
Change:
--class counting_iterator - : public iterator_adaptor< - counting_iterator<Incrementable, Access, Traversal, Difference> - , Incrementable - , Incrementable - , Access - , /* see details for traversal category */ - , Incrementable const& - , Incrementable const* - , /* distance = Difference or a signed integral type */> -{ - friend class iterator_core_access; - public: --
to:
--class counting_iterator -{ - public: - typedef Incrementable value_type; - typedef const Incrementable& reference; - typedef const Incrementable* pointer; - typedef /* see below */ difference_type; - typedef /* see below */ iterator_category; --
Change:
--private: - typename counting_iterator::reference dereference() const - { - return this->base_reference(); - } --
to:
-- Incrementable const& base() const; - reference operator*() const; - counting_iterator& operator++(); - counting_iterator& operator--(); -private: - Incrementable m_inc; // exposition --
After the synopsis, add:
---If the Difference argument is use_default then -difference_type is an unspecified signed integral -type. Otherwise difference_type is Difference.
-iterator_category is determined according to the following -algorithm:
--if (CategoryOrTraversal is not use_default) - return CategoryOrTraversal -else if (numeric_limits<Incrementable>::is_specialized) - return iterator-category( - random_access_traversal_tag, Incrementable, const Incrementable&) -else - return iterator-category( - iterator_traversal<Incrementable>::type, - Incrementable, const Incrementable&) --
The Incrementable type must be Default Constructible, Copy -Constructible, and Assignable. The default distance is -an implementation defined signed integegral type.
-The resulting counting_iterator models Readable Lvalue Iterator.
-After the requirements section, add:
-counting_iterator models
---Specializations of counting_iterator model Readable Lvalue -Iterator. In addition, they model the concepts corresponding to the -iterator tags to which their iterator_category is convertible. -Also, if CategoryOrTraversal is not use_default then -counting_iterator models the concept corresponding to the iterator -tag CategoryOrTraversal. Otherwise, if -numeric_limits<Incrementable>::is_specialized, then -counting_iterator models Random Access Traversal Iterator. -Otherwise, counting_iterator models the same iterator traversal -concepts modeled by Incrementable.
-counting_iterator<X,C1,D1> is interoperable with -counting_iterator<Y,C2,D2> if and only if X is -interoperable with Y.
-
At the begining of the operations section, add:
--In addition to the operations required by the concepts modeled by -counting_iterator, counting_iterator provides the following -operations.-
Returns: | A default constructed instance of counting_iterator. | -
---|
Requires: | Incrementable is Default Constructible. | -
---|---|
Effects: | Default construct the member m_inc. | -
Returns: | An instance of counting_iterator that is a copy of rhs. | -
---|
Effects: | Construct member m_inc from rhs.m_inc. | -
---|
Returns: | An instance of counting_iterator with its base -object copy constructed from x. | -
---|
Effects: | Construct member m_inc from x. | -
---|
At the end of the operations section, add:
---reference operator*() const;
--
-- - - - - Returns: m_inc -counting_iterator& operator++();
--
-- - - - Effects: ++m_inc -- - Returns: *this -counting_iterator& operator--();
--
-- - - - Effects: --m_inc -- - Returns: *this -Incrementable const& base() const;
--
-- - - - - Returns: m_inc -
Submitter: | Howard Hinnant | -
---|---|
Status: | New | -
c++std-lib-12585:
-Readable Iterator Requirements says:
----
-- - -- - - - - a->m -U& -pre: (*a).m is well-defined. Equivalent to (*a).m -
Do we mean to outlaw iterators with proxy references from meeting -the readable requirements?
-Would it be better for the requirements to read static_cast<T>(*a).m -instead of (*a).m ?
-Proposed resolution: | |
---|---|
NAD. | -|
Rationale: | We think you're misreading "pre:". -If (*a).m is not well defined, then the iterator is not -required to provide a->m. So a proxy iterator is not -required to provide a->m. -As an aside, it is possible for proxy iterators to -support ->, so changing the requirements to -read static_cast<T>(*a).m is interesting. -However, such a change to Readable Iterator would -mean that it no longer corresponds to the -input iterator requirements. So old iterators would not -necessarily conform to new iterator requirements. - |
-
Submitter: | Pete Becker | -
---|
c++std-lib-12635:
-counting_iterator takes an argument for its Traversal type, with a -default value of use_default. It is derived from an instance of -iterator_adaptor, where the argument passed for the Traversal type -is described as "/* see details for traversal category -*/". The details for counting_iterator describe constraints on -the Incrementable type imposed by various traversal -categories. There is no description of what the argument to -iterator_adaptor should be.
-Proposed resolution: | |
---|---|
We no longer inherit from iterator_adaptor. So instead, -we specify the iterator_category in terms of the Traversal type -(which is now called CategoryOrTraversal). Also the -requirements and models section was reorganized to -match these changes and to make more sense. | -
Submitter: | Pete Becker | -
---|
c++std-lib-12640:
----The value_type of the Iterator template parameter should itself -be dereferenceable. The return type of the operator* for -the value_type must be the same type as the Reference template -parameter.-I'd say this a bit differently, to emphasize what's required: -iterator_traits<Iterator>::value_type must be dereferenceable. -The Reference template parameter must be the same type as -*iterator_traits<Iterator>::value_type().
--The Value template parameter will be the value_type for the -indirect_iterator, unless Value is const. If Value is const X, then -value_type will be non- const X.-Also non-volatile, right? In other words, if Value isn't use_default, it -just gets passed as the Value argument for iterator_adaptor.
---The default for Value is:
--iterator_traits< iterator_traits<Iterator>::value_type >::value_type --If the default is used for Value, then there must be a valid -specialization of iterator_traits for the value type of the -base iterator.
-The earlier requirement is that -iterator_traits<Iterator>::value_type must be -dereferenceable. Now it's being treated as an iterator. Is this -just a pun, or is iterator_traits<Iterator>::value_type -required to be some form of iterator? If it's the former we need -to find a different way to say it. If it's the latter we need to -say so.
-
Proposed resolution: | |
---|---|
Change: --- to: ----The expression *v, where v is an object of -iterator_traits<Iterator>::value_type, shall be valid -expression and convertible to reference. Iterator -shall model the traversal concept indicated by -iterator_category. Value, Reference, and -Difference shall be chosen so that value_type, -reference, and difference_type meet the requirements -indicated by iterator_category.- |
-|
Rationale: | Not included above is the specification of the -value_type, reference, etc., members, which is handled by -the changes in 9.37x. | -
Submitter: | Pete Becker | -
---|
c++std-lib-12641:
--The reference type of transform_iterator is result_of< -UnaryFunction(iterator_traits<Iterator>::reference) ->::type. The value_type is -remove_cv<remove_reference<reference> >::type.-
These are the defaults, right? If the user supplies their own types -that's what gets passed to iterator_adaptor. And again, the -specification should be in terms of the specialization of -iterator_adaptor, and not in terms of the result:
-Reference argument to iterator_adaptor:
--if (Reference != use_default) - Reference -else - result_of< - UnaryFunction(iterator_traits<Iterator>::reference) - >::type --
Value argument to iterator_adaptor:
--if (Value != use_default) - Value -else if (Reference != use_default) - remove_reference<reference>::type -else - remove_reference< - result_of< - UnaryFunction(iterator_traits<Iterator>::reference) - >::type - >::type --
There's probably a better way to specify that last alternative, but -I've been at this too long, and it's all turning into a maze of -twisty passages, all alike.
-Proposed resolution: | |
---|---|
Replace: --The reference type of transform_iterator is result_of< -UnaryFunction(iterator_traits<Iterator>::reference) ->::type. The value_type is -remove_cv<remove_reference<reference> >::type.- with: --- |
-
Submitter: | Pete Becker | -
---|
c++std-lib-12642:
-The paper says:
--template<class Predicate, class Iterator> -class filter_iterator - : public iterator_adaptor< - filter_iterator<Predicate, Iterator>, - Iterator, - use_default, - /* see details */ > --
That comment covers the Access, Traversal, Reference, and Difference -arguments. The only specification for any of these in the details is:
--The access category of the filter_iterator will be the same as -the access category of Iterator.-
Needs more.
-Proposed resolution: | |
---|---|
Add to the synopsis: --typedef iterator_traits<Iterator>::value_type value_type; -typedef iterator_traits<Iterator>::reference reference; -typedef iterator_traits<Iterator>::pointer pointer; -typedef iterator_traits<Iterator>::difference_type difference_type; -typedef /* see below */ iterator_category; -- and add just after the synopsis: --If Iterator models Readable Lvalue Iterator and Forward -Traversal Iterator then iterator_category is convertible -to std::forward_iterator_tag. Otherwise -iterator_category is convertible to -std::input_iterator_tag.- |
-
Submitter: | Jeremy Siek | -
---|
We do not need to require that the function objects have the same -type, just that they be convertible.
-Proposed resolution: | |
---|---|
Change: --template<class OtherIterator, class R2, class V2> -transform_iterator( - transform_iterator<UnaryFunction, OtherIterator, R2, V2> const& t - , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition -); -- to: --template<class F2, class I2, class R2, class V2> -transform_iterator( - transform_iterator<F2, I2, R2, V2> const& t - , typename enable_if_convertible<I2, Iterator>::type* = 0 // exposition only - , typename enable_if_convertible<F2, UnaryFunction>::type* = 0 // exposition only -); -- |
-
Submitter: | Dave Abrahams | -
---|
indirect_iterator should be able to iterate over containers of -smart pointers, but the mechanism that allows it was left out of -the specification, even though it's present in the Boost -specification
-Proposed resolution: | |
---|---|
Add pointee and indirect_reference -to deal with this capability. -In [lib.iterator.helper.synopsis], add: --template <class Dereferenceable> -struct pointee; - -template <class Dereferenceable> -struct indirect_reference; -- After indirect_iterator's abstract, add: - |
-
Class template pointee
- - - --template <class Dereferenceable> -struct pointee -{ - typedef /* see below */ type; -}; --
Requires: | For an object x of type Dereferenceable, *x -is well-formed. If ++x is ill-formed it shall neither be -ambiguous nor shall it violate access control, and -Dereferenceable::element_type shall be an accessible type. -Otherwise iterator_traits<Dereferenceable>::value_type shall -be well formed. [Note: These requirements need not apply to -explicit or partial specializations of pointee] | -
---|
type is determined according to the following algorithm, where -x is an object of type Dereferenceable:
--if ( ++x is ill-formed ) -{ - return ``Dereferenceable::element_type`` -} -else if (``*x`` is a mutable reference to - std::iterator_traits<Dereferenceable>::value_type) -{ - return iterator_traits<Dereferenceable>::value_type -} -else -{ - return iterator_traits<Dereferenceable>::value_type const -} --
Class template indirect_reference
- - - --template <class Dereferenceable> -struct indirect_reference -{ - typedef /* see below */ type; -}; --
Requires: | For an object x of type Dereferenceable, *x -is well-formed. If ++x is ill-formed it shall neither be -ambiguous nor shall it violate access control, and -pointee<Dereferenceable>::type& shall be well-formed. -Otherwise iterator_traits<Dereferenceable>::reference shall -be well formed. [Note: These requirements need not apply to -explicit or partial specializations of indirect_reference] | -
---|
type is determined according to the following algorithm, where -x is an object of type Dereferenceable:
--if ( ++x is ill-formed ) - return ``pointee<Dereferenceable>::type&`` -else - std::iterator_traits<Dereferenceable>::reference --
See proposed resolution to Issue 9.37x for more changes related to -this issue.
-Submitter: | Dave Abrahams | -
---|
"because specification helps to highlight that the Reference -template parameter may not always be identical to the iterator's -reference type, and will keep users making mistakes based on -that assumption."
-Proposed resolution: | |
---|---|
add "from" before "making" - |
-
mention of obsolete projection_iterator
----
-- - - - Proposed Resolution: - - From n1530, in the Specialized Adaptors section, remove:
--projection_iterator, which is similar to transform_iterator -except that when dereferenced it returns a reference instead of -a value.-- - Rationale: This iterator was in the original boost library, but the new -iterator concepts allowed this iterator to be -folded into transform_iterator. -
Submitter: | Dave Abrahams | -
---|
We've had some real-life reports that iterators that use -iterator_adaptor's base() function can be inefficient -when the Base iterator is expensive to copy. Iterators, of -all things, should be efficient.
-Proposed resolution: | |
---|---|
In [lib.iterator.adaptor] -Change: --Base base() const; -- to: --Base const& base() const; -- twice (once in the synopsis and once in the public -operations section). - |
-
Submitter: | Jeremy Siek | -
---|
We want Forward Traversal Iterator plus Readable Lvalue Iterator to -match the old Foward Iterator requirements, so we need Forward -Traversal Iterator to include Default Constructible.
-Proposed resolution: | |||||||
---|---|---|---|---|---|---|---|
Change: --- to: --- |
-
A general cleanup and simplification of the requirements and -description of type members for iterator_facade.
-The user is only allowed to add const as a qualifier.
-We use to have an unspecified type for pointer, to match the -return type of operator->, but there's no real reason to make them -match, so we just use the simpler Value* for pointer.
-Change:
--typedef /* see description of operator-> */ pointer;-
The nested ::value_type type will be the same as -remove_cv<Value>::type, so the Value parameter must be -an (optionally const-qualified) non-reference type.
-The nested ::reference will be the same as the Reference -parameter; it must be a suitable reference type for the resulting -iterator. The default for the Reference parameter is -Value&.
-Change:
---In the table below, X is the derived iterator type, a is an -object of type X, b and c are objects of type const X, -n is an object of X::difference_type, y is a constant -object of a single pass iterator type interoperable with X, and z -is a constant object of a random access traversal iterator type -interoperable with X.
--
-- - -- - - - - - - Expression -Return Type -Assertion/Note -Required to implement -Iterator Concept(s) -- c.dereference() -X::reference -- Readable Iterator, Writable -Iterator -- c.equal(b) -convertible to bool -true iff b and c are -equivalent. -Single Pass Iterator -- c.equal(y) -convertible to bool -true iff c and y refer to the -same position. Implements c == y -and c != y. -Single Pass Iterator -- a.advance(n) -unused -- Random Access Traversal -Iterator -- a.increment() -unused -- Incrementable Iterator -- a.decrement() -unused -- Bidirectional Traversal -Iterator -- c.distance_to(b) -convertible to -X::difference_type -equivalent to distance(c, b) -Random Access Traversal -Iterator -- - c.distance_to(z) -convertible to -X::difference_type -equivalent to distance(c, z). -Implements c - z, c < z, c -<= z, c > z, and c >= c. -Random Access Traversal -Iterator -
to:
---In the table below, F is iterator_facade<X,V,C,R,D>, a is an -object of type X, b and c are objects of type const X, -n is an object of F::difference_type, y is a constant -object of a single pass iterator type interoperable with X, and z -is a constant object of a random access traversal iterator type -interoperable with X.
-iterator_facade Core Operations
--
-- - -- - - - - - - Expression -Return Type -Assertion/Note -Used to implement Iterator -Concept(s) -- c.dereference() -F::reference -- Readable Iterator, Writable -Iterator -- c.equal(y) -convertible to bool -true iff c and y -refer to the same -position. -Single Pass Iterator -- a.increment() -unused -- Incrementable Iterator -- a.decrement() -unused -- Bidirectional Traversal -Iterator -- a.advance(n) -unused -- Random Access Traversal -Iterator -- - c.distance_to(z) -convertible to -F::difference_type -equivalent to -distance(c, X(z)). -Random Access Traversal -Iterator -