📄 iter-issue-list.rst
字号:
+++++++++++++++++++++++++++++++++++++
Iterator concept and adapter issues
+++++++++++++++++++++++++++++++++++++
:date: $Date: 2004/01/27 03:17:30 $
.. contents:: Index
===================================
Issues from Matt's TR issues list
===================================
9.1 iterator_access overspecified?
==================================
: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.
9.2 operators of iterator_facade overspecified
==============================================
: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.
9.3 enable_if_interoperable needs standardese
=============================================
: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:
The ``enable_if_interoperable`` template used above is for
exposition purposes. The member operators should only be in an
overload set provided the derived types ``Dr1`` and ``Dr2`` are
interoperable, meaning that at least one of the types is
convertible to the other. The ``enable_if_interoperable``
approach uses SFINAE to take the operators out of the overload
set when the types are not interoperable. The operators should
behave *as-if* ``enable_if_interoperable`` were defined to be::
template <bool, typename> enable_if_interoperable_impl
{};
template <typename T> enable_if_interoperable_impl<true,T>
{ typedef T type; };
template<typename Dr1, typename Dr2, typename T>
struct enable_if_interoperable
: enable_if_interoperable_impl<
is_convertible<Dr1,Dr2>::value || is_convertible<Dr2,Dr1>::value
, T
>
{};
9.4 enable_if_convertible unspecified, conflicts with requires
==============================================================
: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:
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
signatures involving ``enable_if_convertible`` should behave
*as-if* ``enable_if_convertible`` were defined to be::
template <bool> enable_if_convertible_impl
{};
template <> enable_if_convertible_impl<true>
{ struct type; };
template<typename From, typename To>
struct enable_if_convertible
: enable_if_convertible_impl<is_convertible<From,To>::value>
{};
If an expression other than the default argument is used to
supply the value of a function parameter whose type is written
in terms of ``enable_if_convertible``, the program is
ill-formed, no diagnostic required.
[*Note:* The ``enable_if_convertible`` approach uses SFINAE to
take the constructor out of the overload set when the types are
not implicitly convertible. ]
9.5 iterator_adaptor has an extraneous 'bool' at the start of the template definition
=====================================================================================
:Submitter: Pete Becker
:Status: New
The title says it all; this is probably just a typo.
:Proposed resolution: Remove the 'bool'.
9.6 Name of private member shouldn't be normative
=================================================
: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: Mark the member ``m_iterator`` 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.
In [lib.iterator.adaptor]
Change::
Base m_iterator;
to::
Base m_iterator; // exposition only
9.7 iterator_adaptor operations specifications are a bit inconsistent
=====================================================================
: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.
9.8 Specialized adaptors text should be normative
=================================================
: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
9.9 Reverse_iterator text is too informal
=========================================
: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.
9.10 'prior' is undefined
=========================
: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:
``reference operator*() const;``
:Effects:
::
Iterator tmp = m_iterator;
return *--tmp;
:Rationale:
The style of specification has changed because of issue 9.37x.
9.11 "In other words" is bad wording
====================================
: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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -