daac0f2ab1
[SVN r80902]
442 lines
14 KiB
ReStructuredText
442 lines
14 KiB
ReStructuredText
.. 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)
|
|
|
|
.. Version 1.3 of this ReStructuredText document corresponds to
|
|
n1530_, the paper accepted by the LWG for TR1.
|
|
|
|
.. Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003.
|
|
|
|
|
|
.. parsed-literal::
|
|
|
|
template <
|
|
class Derived
|
|
, class Value
|
|
, class CategoryOrTraversal
|
|
, class Reference = Value&
|
|
, class Difference = ptrdiff_t
|
|
>
|
|
class iterator_facade {
|
|
public:
|
|
typedef remove_const<Value>::type value_type;
|
|
typedef Reference reference;
|
|
typedef Value\* pointer;
|
|
typedef Difference difference_type;
|
|
typedef /* see below__ \*/ iterator_category;
|
|
|
|
reference operator\*() const;
|
|
/* see below__ \*/ operator->() const;
|
|
/* see below__ \*/ operator[](difference_type n) const;
|
|
Derived& operator++();
|
|
Derived operator++(int);
|
|
Derived& operator--();
|
|
Derived operator--(int);
|
|
Derived& operator+=(difference_type n);
|
|
Derived& operator-=(difference_type n);
|
|
Derived operator-(difference_type n) const;
|
|
protected:
|
|
typedef iterator_facade iterator_facade\_;
|
|
};
|
|
|
|
// 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&);
|
|
|
|
__ `iterator category`_
|
|
|
|
__ `operator arrow`_
|
|
|
|
__ brackets_
|
|
|
|
__ minus_
|
|
|
|
.. _`iterator category`:
|
|
|
|
The ``iterator_category`` member of ``iterator_facade`` is
|
|
|
|
.. parsed-literal::
|
|
|
|
*iterator-category*\ (CategoryOrTraversal, reference, value_type)
|
|
|
|
where *iterator-category* is defined as follows:
|
|
|
|
.. include:: facade_iterator_category.rst
|
|
|
|
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
|
|
>
|
|
{};
|
|
|
|
|
|
``iterator_facade`` Requirements
|
|
--------------------------------
|
|
|
|
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 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``.
|
|
|
|
.. _`core operations`:
|
|
|
|
.. topic:: ``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`` |Single Pass Iterator |
|
|
| | |refer to the same | |
|
|
| | |position. | |
|
|
+--------------------+----------------------+-------------------------+---------------------------+
|
|
|``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 |equivalent to |Random Access Traversal |
|
|
| |``F::difference_type``|``distance(c, X(z))``. |Iterator |
|
|
+--------------------+----------------------+-------------------------+---------------------------+
|
|
|
|
|
|
|
|
``iterator_facade`` operations
|
|
------------------------------
|
|
|
|
The operations in this section are described in terms of operations on
|
|
the core interface of ``Derived`` which may be inaccessible
|
|
(i.e. private). The implementation should access these operations
|
|
through member functions of class ``iterator_core_access``.
|
|
|
|
``reference operator*() const;``
|
|
|
|
:Returns: ``static_cast<Derived const*>(this)->dereference()``
|
|
|
|
``operator->() const;`` (see below__)
|
|
|
|
__ `operator arrow`_
|
|
|
|
:Returns: If ``reference`` is a reference type, an object
|
|
of type ``pointer`` equal to::
|
|
|
|
&static_cast<Derived const*>(this)->dereference()
|
|
|
|
Otherwise returns an object of unspecified type such that,
|
|
``(*static_cast<Derived const*>(this))->m`` is equivalent to ``(w = **static_cast<Derived const*>(this),
|
|
w.m)`` for some temporary object ``w`` of type ``value_type``.
|
|
|
|
.. _brackets:
|
|
|
|
*unspecified* ``operator[](difference_type n) const;``
|
|
|
|
:Returns: an object convertible to ``value_type``. For constant
|
|
objects ``v`` of type ``value_type``, and ``n`` of type
|
|
``difference_type``, ``(*this)[n] = v`` is equivalent to
|
|
``*(*this + n) = v``, and ``static_cast<value_type
|
|
const&>((*this)[n])`` is equivalent to
|
|
``static_cast<value_type const&>(*(*this + n))``
|
|
|
|
|
|
|
|
``Derived& operator++();``
|
|
|
|
:Effects:
|
|
|
|
::
|
|
|
|
static_cast<Derived*>(this)->increment();
|
|
return *static_cast<Derived*>(this);
|
|
|
|
``Derived operator++(int);``
|
|
|
|
:Effects:
|
|
|
|
::
|
|
|
|
Derived tmp(static_cast<Derived const*>(this));
|
|
++*this;
|
|
return tmp;
|
|
|
|
|
|
``Derived& operator--();``
|
|
|
|
:Effects:
|
|
|
|
::
|
|
|
|
static_cast<Derived*>(this)->decrement();
|
|
return *static_cast<Derived*>(this);
|
|
|
|
|
|
``Derived operator--(int);``
|
|
|
|
:Effects:
|
|
|
|
::
|
|
|
|
Derived tmp(static_cast<Derived const*>(this));
|
|
--*this;
|
|
return tmp;
|
|
|
|
|
|
``Derived& operator+=(difference_type n);``
|
|
|
|
:Effects:
|
|
|
|
::
|
|
|
|
static_cast<Derived*>(this)->advance(n);
|
|
return *static_cast<Derived*>(this);
|
|
|
|
|
|
``Derived& operator-=(difference_type n);``
|
|
|
|
:Effects:
|
|
|
|
::
|
|
|
|
static_cast<Derived*>(this)->advance(-n);
|
|
return *static_cast<Derived*>(this);
|
|
|
|
|
|
``Derived operator-(difference_type n) const;``
|
|
|
|
:Effects:
|
|
|
|
::
|
|
|
|
Derived tmp(static_cast<Derived const*>(this));
|
|
return tmp -= n;
|
|
|
|
::
|
|
|
|
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&);
|
|
|
|
:Effects:
|
|
|
|
::
|
|
|
|
Derived tmp(static_cast<Derived const*>(this));
|
|
return tmp += n;
|
|
|
|
|
|
::
|
|
|
|
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);
|
|
|
|
:Returns:
|
|
if ``is_convertible<Dr2,Dr1>::value``
|
|
|
|
then
|
|
``((Dr1 const&)lhs).equal((Dr2 const&)rhs)``.
|
|
|
|
Otherwise,
|
|
``((Dr2 const&)rhs).equal((Dr1 const&)lhs)``.
|
|
|
|
::
|
|
|
|
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);
|
|
|
|
:Returns:
|
|
if ``is_convertible<Dr2,Dr1>::value``
|
|
|
|
then
|
|
``!((Dr1 const&)lhs).equal((Dr2 const&)rhs)``.
|
|
|
|
Otherwise,
|
|
``!((Dr2 const&)rhs).equal((Dr1 const&)lhs)``.
|
|
|
|
::
|
|
|
|
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);
|
|
|
|
:Returns:
|
|
if ``is_convertible<Dr2,Dr1>::value``
|
|
|
|
then
|
|
``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) < 0``.
|
|
|
|
Otherwise,
|
|
``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) > 0``.
|
|
|
|
::
|
|
|
|
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);
|
|
|
|
:Returns:
|
|
if ``is_convertible<Dr2,Dr1>::value``
|
|
|
|
then
|
|
``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) <= 0``.
|
|
|
|
Otherwise,
|
|
``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) >= 0``.
|
|
|
|
::
|
|
|
|
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);
|
|
|
|
:Returns:
|
|
if ``is_convertible<Dr2,Dr1>::value``
|
|
|
|
then
|
|
``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) > 0``.
|
|
|
|
Otherwise,
|
|
``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) < 0``.
|
|
|
|
|
|
::
|
|
|
|
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);
|
|
|
|
:Returns:
|
|
if ``is_convertible<Dr2,Dr1>::value``
|
|
|
|
then
|
|
``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) >= 0``.
|
|
|
|
Otherwise,
|
|
``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) <= 0``.
|
|
|
|
.. _minus:
|
|
|
|
::
|
|
|
|
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);
|
|
|
|
:Return Type:
|
|
if ``is_convertible<Dr2,Dr1>::value``
|
|
|
|
then
|
|
``difference`` shall be
|
|
``iterator_traits<Dr1>::difference_type``.
|
|
|
|
Otherwise
|
|
``difference`` shall be ``iterator_traits<Dr2>::difference_type``
|
|
|
|
:Returns:
|
|
if ``is_convertible<Dr2,Dr1>::value``
|
|
|
|
then
|
|
``-((Dr1 const&)lhs).distance_to((Dr2 const&)rhs)``.
|
|
|
|
Otherwise,
|
|
``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs)``.
|