forked from boostorg/iterator
merged from trunk
[SVN r21580]
This commit is contained in:
@ -46,14 +46,15 @@ objects for several reasons:
|
||||
Usage
|
||||
-----
|
||||
|
||||
The user of ``iterator_facade`` derives his iterator class from an
|
||||
specialization of ``iterator_facade`` which takes the derived iterator
|
||||
class as the first template parameter. The order of the other
|
||||
template parameters to ``iterator_facade`` have been carefully chosen
|
||||
to take advantage of useful defaults. For example, when defining a
|
||||
constant lvalue iterator, the user can pass a const-qualified version
|
||||
of the iterator's ``value_type`` as ``iterator_facade``\ 's ``Value``
|
||||
parameter and omit the ``Reference`` parameter which follows.
|
||||
The user of ``iterator_facade`` derives his iterator class from a
|
||||
specialization of ``iterator_facade`` and passes the derived
|
||||
iterator class as ``iterator_facade``\ 's first template parameter.
|
||||
The order of the other template parameters have been carefully
|
||||
chosen to take advantage of useful defaults. For example, when
|
||||
defining a constant lvalue iterator, the user can pass a
|
||||
const-qualified version of the iterator's ``value_type`` as
|
||||
``iterator_facade``\ 's ``Value`` parameter and omit the
|
||||
``Reference`` parameter which follows.
|
||||
|
||||
The derived iterator class must define member functions implementing
|
||||
the iterator's core behaviors. The following table describes
|
||||
@ -150,14 +151,16 @@ into the temporary iterator ``p+n``, which is destroyed when
|
||||
|
||||
Writable iterators built with ``iterator_facade`` implement the
|
||||
semantics required by the preferred resolution to `issue 299`_ and
|
||||
adopted by proposal n1550_: the result of ``p[n]`` is a proxy object
|
||||
containing a copy of ``p+n``, and ``p[n] = x`` is equivalent to ``*(p
|
||||
+ n) = x``. This approach will work properly for any random-access
|
||||
iterator regardless of the other details of its implementation. A
|
||||
user who knows more about the implementation of her iterator is free
|
||||
to implement an ``operator[]`` which returns an lvalue in the derived
|
||||
iterator class; it will hide the one supplied by ``iterator_facade``
|
||||
from clients of her iterator.
|
||||
adopted by proposal n1550_: the result of ``p[n]`` is an object
|
||||
convertible to the iterator's ``value_type``, and ``p[n] = x`` is
|
||||
equivalent to ``*(p + n) = x`` (Note: This result object may be
|
||||
implemented as a proxy containing a copy of ``p+n``). This approach
|
||||
will work properly for any random-access iterator regardless of the
|
||||
other details of its implementation. A user who knows more about
|
||||
the implementation of her iterator is free to implement an
|
||||
``operator[]`` that returns an lvalue in the derived iterator
|
||||
class; it will hide the one supplied by ``iterator_facade`` from
|
||||
clients of her iterator.
|
||||
|
||||
.. _n1550: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/papers/2003/n1550.html
|
||||
|
||||
|
@ -245,10 +245,13 @@ __ `operator arrow`_
|
||||
|
||||
*unspecified* ``operator[](difference_type n) const;``
|
||||
|
||||
:Returns: an object convertible to ``reference`` and holding a copy
|
||||
*p* of ``*static_cast<Derived const*>(this) + n`` such that, for a constant object ``v`` of type
|
||||
``value_type``, ``(*static_cast<Derived const*>(this))[n] = v`` is equivalent
|
||||
to ``p = v``.
|
||||
:Returns: an object convertible to ``value_type``. For constant
|
||||
objects ``v`` of type ``value_type``, and ``n`` of type
|
||||
``difference_type``, and reference ``p`` equal to
|
||||
``*static_cast<Derived const*>(this)``, ``(*this)[n] = v`` is
|
||||
equivalent to ``*(p+ n) = v``, and ``static_cast<value_type
|
||||
const&>((*this)[n])`` is equivalent to
|
||||
``static_cast<value_type const&>(*(p+n))``
|
||||
|
||||
|
||||
|
||||
|
@ -22,9 +22,11 @@
|
||||
#include <boost/type_traits/add_pointer.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/is_POD.hpp>
|
||||
|
||||
#include <boost/mpl/apply_if.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
|
||||
#include <boost/iterator/detail/config_def.hpp> // this goes last
|
||||
|
||||
@ -182,11 +184,21 @@ namespace boost
|
||||
Iterator m_iter;
|
||||
};
|
||||
|
||||
template <class Value, class Reference>
|
||||
struct use_operator_brackets_proxy
|
||||
: mpl::and_<
|
||||
// Really we want an is_copy_constructible trait here,
|
||||
// but is_POD will have to suffice in the meantime.
|
||||
boost::is_POD<Value>
|
||||
, iterator_writability_disabled<Value,Reference>
|
||||
>
|
||||
{};
|
||||
|
||||
template <class Iterator, class Value, class Reference>
|
||||
struct operator_brackets_result
|
||||
{
|
||||
typedef typename mpl::if_<
|
||||
iterator_writability_disabled<Value,Reference>
|
||||
use_operator_brackets_proxy<Value,Reference>
|
||||
, Value
|
||||
, operator_brackets_proxy<Iterator>
|
||||
>::type type;
|
||||
@ -387,12 +399,11 @@ namespace boost
|
||||
typename detail::operator_brackets_result<Derived,Value,Reference>::type
|
||||
operator[](difference_type n) const
|
||||
{
|
||||
typedef detail::iterator_writability_disabled<Value,Reference>
|
||||
not_writable;
|
||||
typedef detail::use_operator_brackets_proxy<Value,Reference> use_proxy;
|
||||
|
||||
return detail::make_operator_brackets_result<Derived>(
|
||||
this->derived() + n
|
||||
, not_writable()
|
||||
, use_proxy()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,9 @@
|
||||
|
||||
# include <boost/detail/is_incrementable.hpp>
|
||||
# include <boost/iterator/iterator_traits.hpp>
|
||||
# include <boost/type_traits/add_const.hpp>
|
||||
# include <boost/type_traits/remove_cv.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/apply_if.hpp>
|
||||
|
||||
namespace boost {
|
||||
@ -17,9 +19,37 @@ namespace boost {
|
||||
namespace detail
|
||||
{
|
||||
template <class P>
|
||||
struct smart_ptr_value
|
||||
struct smart_ptr_pointee
|
||||
{
|
||||
typedef typename remove_cv<typename P::element_type>::type type;
|
||||
typedef typename P::element_type type;
|
||||
};
|
||||
|
||||
template <class Iterator>
|
||||
struct iterator_pointee
|
||||
{
|
||||
typedef typename iterator_traits<Iterator>::value_type value_type;
|
||||
|
||||
struct impl
|
||||
{
|
||||
template <class T>
|
||||
static char test(T const&);
|
||||
|
||||
static char (& test(value_type&) )[2];
|
||||
|
||||
static Iterator& x;
|
||||
};
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, is_constant = sizeof(impl::test(*impl::x)) == 1);
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
::boost::detail::iterator_pointee<Iterator>::is_constant
|
||||
# else
|
||||
is_constant
|
||||
# endif
|
||||
, typename add_const<value_type>::type
|
||||
, value_type
|
||||
>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
@ -27,11 +57,11 @@ template <class P>
|
||||
struct pointee
|
||||
{
|
||||
typedef typename remove_cv<P>::type stripped;
|
||||
|
||||
|
||||
typedef typename mpl::apply_if<
|
||||
detail::is_incrementable<stripped>
|
||||
, iterator_value<stripped>
|
||||
, detail::smart_ptr_value<stripped>
|
||||
, detail::iterator_pointee<stripped>
|
||||
, detail::smart_ptr_pointee<stripped>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
subproject libs/iterator/test ;
|
||||
|
||||
subinclude libs/iterator/example ;
|
||||
|
||||
import testing ;
|
||||
|
||||
test-suite iterator
|
||||
@ -29,6 +31,7 @@ test-suite iterator
|
||||
# These tests should work for just about everything.
|
||||
[ compile is_lvalue_iterator.cpp ]
|
||||
[ compile is_readable_iterator.cpp ]
|
||||
[ compile pointee.cpp ]
|
||||
|
||||
[ run unit_tests.cpp ]
|
||||
[ run concept_tests.cpp ]
|
||||
|
@ -30,19 +30,8 @@ struct my_ptr {
|
||||
BOOST_TT_BROKEN_COMPILER_SPEC(my_ptr)
|
||||
BOOST_TT_BROKEN_COMPILER_SPEC(zow)
|
||||
|
||||
#ifndef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
|
||||
|
||||
# define STATIC_ASSERT_SAME_POINTER(P1, P2) \
|
||||
STATIC_ASSERT_SAME( \
|
||||
boost::remove_const<boost::remove_pointer<P1>::type>::type \
|
||||
, boost::remove_const<boost::remove_pointer<P2>::type>::type \
|
||||
)
|
||||
|
||||
#else
|
||||
|
||||
# define STATIC_ASSERT_SAME_POINTER(P1, P2) STATIC_ASSERT_SAME(P1,P2)
|
||||
|
||||
#endif
|
||||
// Borland 5.6.4 and earlier drop const all over the place, so this
|
||||
// test will fail in the lines marked with (**)
|
||||
|
||||
int main()
|
||||
{
|
||||
@ -50,7 +39,7 @@ int main()
|
||||
typedef boost::indirect_iterator<int**> Iter;
|
||||
STATIC_ASSERT_SAME(Iter::value_type, int);
|
||||
STATIC_ASSERT_SAME(Iter::reference, int&);
|
||||
STATIC_ASSERT_SAME_POINTER(Iter::pointer, int*);
|
||||
STATIC_ASSERT_SAME(Iter::pointer, int*);
|
||||
STATIC_ASSERT_SAME(Iter::difference_type, std::ptrdiff_t);
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_convertible<Iter::iterator_category,
|
||||
@ -62,31 +51,26 @@ int main()
|
||||
typedef boost::indirect_iterator<int const**> Iter;
|
||||
STATIC_ASSERT_SAME(Iter::value_type, int);
|
||||
STATIC_ASSERT_SAME(Iter::reference, const int&);
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // Borland drops const all over the place
|
||||
STATIC_ASSERT_SAME_POINTER(Iter::pointer, const int*);
|
||||
#endif
|
||||
STATIC_ASSERT_SAME(Iter::pointer, const int*); // (**)
|
||||
}
|
||||
{
|
||||
typedef boost::indirect_iterator<int**, int> Iter;
|
||||
STATIC_ASSERT_SAME(Iter::value_type, int);
|
||||
STATIC_ASSERT_SAME(Iter::reference, int&);
|
||||
STATIC_ASSERT_SAME_POINTER(Iter::pointer, int*);
|
||||
STATIC_ASSERT_SAME(Iter::pointer, int*);
|
||||
}
|
||||
{
|
||||
typedef boost::indirect_iterator<int**, const int> Iter;
|
||||
STATIC_ASSERT_SAME(Iter::value_type, int);
|
||||
STATIC_ASSERT_SAME(Iter::reference, const int&);
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // Borland drops const all over the place
|
||||
STATIC_ASSERT_SAME_POINTER(Iter::pointer, const int*);
|
||||
#endif
|
||||
STATIC_ASSERT_SAME(Iter::pointer, const int*); // (**)
|
||||
}
|
||||
{
|
||||
typedef boost::indirect_iterator<my_ptr*> Iter;
|
||||
STATIC_ASSERT_SAME(Iter::value_type, zow);
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // Borland drops const all over the place
|
||||
STATIC_ASSERT_SAME(Iter::reference, const zow&);
|
||||
STATIC_ASSERT_SAME_POINTER(Iter::pointer, const zow*);
|
||||
#endif
|
||||
STATIC_ASSERT_SAME(Iter::reference, const zow&); // (**)
|
||||
STATIC_ASSERT_SAME(Iter::pointer, const zow*); // (**)
|
||||
|
||||
STATIC_ASSERT_SAME(Iter::difference_type, std::ptrdiff_t);
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_convertible<Iter::iterator_category,
|
||||
@ -98,7 +82,7 @@ int main()
|
||||
typedef boost::indirect_iterator<char**, int, std::random_access_iterator_tag, long&, short> Iter;
|
||||
STATIC_ASSERT_SAME(Iter::value_type, int);
|
||||
STATIC_ASSERT_SAME(Iter::reference, long&);
|
||||
STATIC_ASSERT_SAME_POINTER(Iter::pointer, int*);
|
||||
STATIC_ASSERT_SAME(Iter::pointer, int*);
|
||||
STATIC_ASSERT_SAME(Iter::difference_type, short);
|
||||
}
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user