[SVN r20853]
This commit is contained in:
Dave Abrahams
2003-11-19 04:25:17 +00:00
parent cd37eb3bfb
commit 62b70f57a9
11 changed files with 369 additions and 232 deletions

View File

@ -15,7 +15,7 @@
namespace boost { namespace boost {
template <class Incrementable, class Category, class Difference> class counting_iterator; template <class Incrementable, class Traversal, class Difference> class counting_iterator;
namespace detail namespace detail
{ {
@ -67,35 +67,37 @@ namespace detail
}; };
BOOST_STATIC_ASSERT(is_numeric<int>::value); BOOST_STATIC_ASSERT(is_numeric<int>::value);
template <class Incrementable, class Category, class Difference> template <class Incrementable, class Traversal, class Difference>
struct counting_iterator_base struct counting_iterator_base
{ {
typedef typename mpl::apply_if< typedef typename detail::ia_dflt_help<
is_same<Category, use_default> Traversal
, mpl::apply_if< , mpl::apply_if<
is_numeric<Incrementable> is_numeric<Incrementable>
, mpl::identity<std::random_access_iterator_tag> , mpl::identity<random_access_traversal_tag>
, BOOST_ITERATOR_CATEGORY<Incrementable> , iterator_traversal<Incrementable>
> >
, mpl::identity<Category> >::type traversal;
>::type category;
typedef typename mpl::apply_if< typedef typename detail::ia_dflt_help<
is_same<Difference, use_default> Difference
, mpl::apply_if< , mpl::apply_if<
is_numeric<Incrementable> is_numeric<Incrementable>
, numeric_difference<Incrementable> , numeric_difference<Incrementable>
, iterator_difference<Incrementable> , iterator_difference<Incrementable>
> >
, mpl::identity<Difference>
>::type difference; >::type difference;
typedef iterator_adaptor< typedef iterator_adaptor<
counting_iterator<Incrementable, Category, Difference> // self counting_iterator<Incrementable, Traversal, Difference> // self
, Incrementable // Base , Incrementable // Base
, Incrementable // value_type , Incrementable // Value
, category # ifndef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
, Incrementable const& // reference const // MSVC won't strip this. Instead we enable Thomas'
// criterion (see boost/iterator/detail/facade_iterator_category.hpp)
# endif
, traversal
, Incrementable const& // reference
, difference , difference
> type; > type;
}; };
@ -128,11 +130,11 @@ namespace detail
}; };
} }
template <class Incrementable, class Category = use_default, class Difference = use_default> template <class Incrementable, class Traversal = use_default, class Difference = use_default>
class counting_iterator class counting_iterator
: public detail::counting_iterator_base<Incrementable, Category, Difference>::type : public detail::counting_iterator_base<Incrementable, Traversal, Difference>::type
{ {
typedef typename detail::counting_iterator_base<Incrementable, Category, Difference>::type super_t; typedef typename detail::counting_iterator_base<Incrementable, Traversal, Difference>::type super_t;
friend class iterator_core_access; friend class iterator_core_access;
public: public:

View File

@ -24,6 +24,11 @@
# define BOOST_ITERATOR_CONFIG_DEF # define BOOST_ITERATOR_CONFIG_DEF
#endif #endif
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531))
# define BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY 1
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531)) \ || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531)) \
|| (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER)) || (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER))

View File

@ -0,0 +1,220 @@
// Copyright David Abrahams 2003. Use, modification and distribution is
// subject to 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)
#ifndef FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
# define FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
# include <boost/iterator/iterator_categories.hpp>
# include <boost/static_assert.hpp>
# include <boost/mpl/or.hpp> // used in iterator_tag inheritance logic
# include <boost/mpl/and.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/apply_if.hpp>
# include <boost/mpl/identity.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/type_traits/is_const.hpp>
# include <boost/type_traits/is_reference.hpp>
# include <boost/type_traits/is_convertible.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/iterator/detail/config_def.hpp> // try to keep this last
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
# include <boost/python/detail/indirect_traits.hpp>
# endif
//
// iterator_category deduction for iterator_facade
//
// forward declaration
namespace boost { struct use_default; }
namespace boost { namespace detail {
struct input_output_iterator_tag
: std::input_iterator_tag, std::output_iterator_tag {};
//
// True iff the user has explicitly disabled writability of this
// iterator. Pass the iterator_facade's Value parameter and its
// nested ::reference type.
//
template <class ValueParam, class Reference>
struct iterator_writability_disabled
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic?
: mpl::or_<
is_const<Reference>
, python::detail::is_reference_to_const<Reference>
, is_const<ValueParam>
>
# else
: is_const<ValueParam>
# endif
{};
//
// Convert an iterator_facade's traversal category, Value parameter,
// and ::reference type to an appropriate old-style category.
//
// If writability has been disabled per the above metafunction, the
// result will not be convertible to output_iterator_tag.
//
// Otherwise, if Traversal == single_pass_traversal_tag, the following
// conditions will result in a tag that is convertible both to
// input_iterator_tag and output_iterator_tag:
//
// 1. Reference is a reference to non-const
// 2. Reference is not a reference and is convertible to Value
//
template <class Traversal, class ValueParam, class Reference>
struct iterator_facade_default_category
: mpl::apply_if<
mpl::and_<
is_reference<Reference>
, is_convertible<Traversal,forward_traversal_tag>
>
, mpl::apply_if<
is_convertible<Traversal,random_access_traversal_tag>
, mpl::identity<std::random_access_iterator_tag>
, mpl::if_<
is_convertible<Traversal,bidirectional_traversal_tag>
, std::bidirectional_iterator_tag
, std::forward_iterator_tag
>
>
, typename mpl::apply_if<
mpl::and_<
is_convertible<Traversal, single_pass_traversal_tag>
, mpl::or_< // check for readability
is_same<ValueParam,use_default>
, is_convertible<Reference, ValueParam>
>
>
, mpl::if_<
iterator_writability_disabled<ValueParam,Reference>
, std::input_iterator_tag
, input_output_iterator_tag
>
, mpl::identity<std::output_iterator_tag>
>
>
{
};
// True iff T is convertible to an old-style iterator category.
template <class T>
struct is_iterator_category
: mpl::or_<
is_convertible<T,std::input_iterator_tag>
, is_convertible<T,std::output_iterator_tag>
>
{
};
template <>
struct is_iterator_category<int>
: mpl::false_
{};
template <class T>
struct is_iterator_traversal
: is_convertible<T,incrementable_traversal_tag>
{};
//
// A composite iterator_category tag convertible to Category (a pure
// old-style category) and Traversal (a pure traversal tag).
// Traversal must be a strict increase of the traversal power given by
// Category.
//
template <class Category, class Traversal>
struct iterator_category_with_traversal
: Category, Traversal
{
# if 0
// Because of limitations on multiple user-defined conversions,
// this should be a good test of whether convertibility is enough
// in the spec, or whether we need to specify inheritance.
operator Category() const { return Category(); }
operator Traversal() const { return Traversal(); }
# endif
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
// Make sure this isn't used to build any categories where
// convertibility to Traversal is redundant. Should just use the
// Category element in that case.
BOOST_STATIC_ASSERT(
!(is_convertible<
typename iterator_category_to_traversal<Category>::type
, Traversal
>::value));
BOOST_STATIC_ASSERT(is_iterator_category<Category>::value);
BOOST_STATIC_ASSERT(!is_iterator_category<Traversal>::value);
BOOST_STATIC_ASSERT(!is_iterator_traversal<Category>::value);
BOOST_STATIC_ASSERT(is_iterator_traversal<Traversal>::value);
# endif
};
template <>
struct iterator_category_with_traversal<int,int>
{};
// Computes an iterator_category tag whose traversal is Traversal and
// which is appropriate for an iterator
template <class Traversal, class ValueParam, class Reference>
struct facade_iterator_category_impl
{
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
BOOST_STATIC_ASSERT(!is_iterator_category<Traversal>::value);
# endif
typedef typename iterator_facade_default_category<
Traversal,ValueParam,Reference
>::type category;
typedef typename mpl::if_<
is_same<
Traversal
, typename iterator_category_to_traversal<category>::type
>
, category
, iterator_category_with_traversal<category,Traversal>
>::type type;
};
template <>
struct facade_iterator_category_impl<int,int,int> {};
//
// Compute an iterator_category for iterator_facade
//
template <class CategoryOrTraversal, class ValueParam, class Reference>
struct facade_iterator_category
: mpl::apply_if<
is_iterator_category<CategoryOrTraversal>
, mpl::identity<CategoryOrTraversal> // old-style categories are fine as-is
, facade_iterator_category_impl<CategoryOrTraversal,ValueParam,Reference>
>
{
};
template <>
struct facade_iterator_category<int,int,int>
{
typedef int type;
};
}} // namespace boost::detail
# include <boost/iterator/detail/config_undef.hpp>
#endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP

View File

@ -14,6 +14,8 @@
// should be the last #include // should be the last #include
#include <boost/iterator/detail/config_def.hpp> #include <boost/iterator/detail/config_def.hpp>
#ifndef BOOST_NO_IS_CONVERTIBLE
namespace boost { namespace boost {
namespace detail namespace detail
@ -122,7 +124,7 @@ namespace detail
{}; {};
template <class It> template <class It>
struct is_mutable_lvalue_iterator_impl struct is_non_const_lvalue_iterator_impl
: is_lvalue_iterator_impl< : is_lvalue_iterator_impl<
BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<It>::value_type BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<It>::value_type
>::template rebind<It> >::template rebind<It>
@ -135,10 +137,12 @@ BOOST_TT_AUX_BOOL_TRAIT_DEF1(
is_lvalue_iterator,T,::boost::detail::is_readable_lvalue_iterator_impl<T>::value) is_lvalue_iterator,T,::boost::detail::is_readable_lvalue_iterator_impl<T>::value)
BOOST_TT_AUX_BOOL_TRAIT_DEF1( BOOST_TT_AUX_BOOL_TRAIT_DEF1(
is_mutable_lvalue_iterator,T,::boost::detail::is_mutable_lvalue_iterator_impl<T>::value) is_non_const_lvalue_iterator,T,::boost::detail::is_non_const_lvalue_iterator_impl<T>::value)
} // namespace boost } // namespace boost
#endif
#include <boost/iterator/detail/config_undef.hpp> #include <boost/iterator/detail/config_undef.hpp>
#endif // IS_LVALUE_ITERATOR_DWA2003112_HPP #endif // IS_LVALUE_ITERATOR_DWA2003112_HPP

View File

@ -13,6 +13,8 @@
// should be the last #include // should be the last #include
#include <boost/iterator/detail/config_def.hpp> #include <boost/iterator/detail/config_def.hpp>
#ifndef BOOST_NO_IS_CONVERTIBLE
namespace boost { namespace boost {
namespace detail namespace detail
@ -99,6 +101,8 @@ BOOST_TT_AUX_BOOL_TRAIT_DEF1(
} // namespace boost } // namespace boost
#endif
#include <boost/iterator/detail/config_undef.hpp> #include <boost/iterator/detail/config_undef.hpp>
#endif // IS_READABLE_ITERATOR_DWA2003112_HPP #endif // IS_READABLE_ITERATOR_DWA2003112_HPP

View File

@ -26,7 +26,7 @@
#include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/is_convertible.hpp>
#ifdef BOOST_ITERATOR_REFERENCE_PRIMACY #ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
# include <boost/type_traits/remove_reference.hpp> # include <boost/type_traits/remove_reference.hpp>
#else #else
# include <boost/type_traits/add_reference.hpp> # include <boost/type_traits/add_reference.hpp>
@ -38,6 +38,20 @@
namespace boost namespace boost
{ {
// Used as a default template argument internally, merely to
// indicate "use the default", this can also be passed by users
// explicitly in order to specify that the default should be used.
struct use_default;
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// the incompleteness of use_default causes massive problems for
// is_convertible (naturally). This workaround is fortunately not
// needed for vc6/vc7.
template<class To>
struct is_convertible<use_default,To>
: mpl::false_ {};
# endif
namespace detail namespace detail
{ {
@ -157,7 +171,7 @@ namespace boost
typedef iterator_facade< typedef iterator_facade<
Derived Derived
# ifdef BOOST_ITERATOR_REFERENCE_PRIMACY # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
, typename detail::ia_dflt_help< , typename detail::ia_dflt_help<
Value Value
, mpl::apply_if< , mpl::apply_if<
@ -177,7 +191,7 @@ namespace boost
, iterator_traversal<Base> , iterator_traversal<Base>
>::type >::type
# ifdef BOOST_ITERATOR_REFERENCE_PRIMACY # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
, typename detail::ia_dflt_help< , typename detail::ia_dflt_help<
Reference Reference
, iterator_reference<Base> , iterator_reference<Base>
@ -199,6 +213,7 @@ namespace boost
> >
type; type;
}; };
template <class T> int static_assert_convertible_to(T);
} }
// //
@ -287,17 +302,18 @@ namespace boost
// ); // );
return m_iterator == x.base(); return m_iterator == x.base();
} }
typedef typename iterator_category_to_traversal<
typename super_t::iterator_category
>::type my_traversal;
# define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \
typedef int assertion[sizeof(detail::static_assert_convertible_to<cat>(my_traversal()))];
// BOOST_STATIC_ASSERT((is_convertible<my_traversal,cat>::value));
void advance(typename super_t::difference_type n) void advance(typename super_t::difference_type n)
{ {
# if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) // seems to get instantiated incorrectly BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
BOOST_STATIC_ASSERT(
(is_convertible<
BOOST_DEDUCED_TYPENAME super_t::iterator_category
, random_access_traversal_tag
>::value)
);
# endif
m_iterator += n; m_iterator += n;
} }
@ -305,14 +321,7 @@ namespace boost
void decrement() void decrement()
{ {
# if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) // seems to get instantiated incorrectly BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag)
BOOST_STATIC_ASSERT(
(is_convertible<
BOOST_DEDUCED_TYPENAME super_t::iterator_category
, bidirectional_traversal_tag
>::value)
);
# endif
--m_iterator; --m_iterator;
} }
@ -322,12 +331,7 @@ namespace boost
typename super_t::difference_type distance_to( typename super_t::difference_type distance_to(
iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const
{ {
BOOST_STATIC_ASSERT( BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
(is_convertible<
BOOST_DEDUCED_TYPENAME super_t::iterator_category
, random_access_traversal_tag
>::value)
);
// Maybe readd with same_distance // Maybe readd with same_distance
// BOOST_STATIC_ASSERT( // BOOST_STATIC_ASSERT(
// (detail::same_category_and_difference<Derived,OtherDerived>::value) // (detail::same_category_and_difference<Derived,OtherDerived>::value)
@ -335,6 +339,8 @@ namespace boost
return y.base() - m_iterator; return y.base() - m_iterator;
} }
# undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL
private: // data members private: // data members
Base m_iterator; Base m_iterator;
}; };

View File

@ -13,16 +13,12 @@
# include <boost/detail/workaround.hpp> # include <boost/detail/workaround.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/and.hpp>
# include <boost/mpl/apply_if.hpp> # include <boost/mpl/apply_if.hpp>
# include <boost/mpl/identity.hpp> # include <boost/mpl/identity.hpp>
# include <boost/mpl/placeholders.hpp> # include <boost/mpl/placeholders.hpp>
# include <boost/mpl/aux_/lambda_support.hpp> # include <boost/mpl/aux_/lambda_support.hpp>
# include <boost/type_traits/is_reference.hpp>
# include <boost/type_traits/is_convertible.hpp> # include <boost/type_traits/is_convertible.hpp>
# include <boost/type_traits/is_const.hpp>
# ifdef BOOST_ITERATOR_REFERENCE_PRIMACY # ifdef BOOST_ITERATOR_REFERENCE_PRIMACY
# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION # ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
@ -54,70 +50,7 @@ struct random_access_traversal_tag
namespace detail namespace detail
{ {
struct input_output_iterator_tag
: std::input_iterator_tag, std::output_iterator_tag {};
//
// Helper for iterator_tag and iterator_facade. True iff the user
// has explicitly disabled writability of this iterator.
//
template <class Value, class Reference>
struct iterator_writability_disabled
# ifdef BOOST_ITERATOR_REFERENCE_PRIMACY
# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
: mpl::or_<is_const<Reference>,python::detail::is_reference_to_const<Reference> >
# else
: is_const<typename remove_reference<Reference>::type>
# endif
# else
: is_const<Value>
# endif
{};
template <class Value, class Reference, class Traversal>
struct old_iterator_category
{
typedef typename mpl::
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
if_
# else
apply_if
# endif
<
mpl::and_<
is_reference<Reference>
, is_convertible<Traversal,forward_traversal_tag>
>
, mpl::apply_if<
is_convertible<Traversal,random_access_traversal_tag>
, mpl::identity<std::random_access_iterator_tag>
, mpl::if_<
is_convertible<Traversal,bidirectional_traversal_tag>
, std::bidirectional_iterator_tag
, std::forward_iterator_tag
>
>
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
::type
# endif
, typename mpl::apply_if<
mpl::and_<
is_convertible<Traversal, single_pass_traversal_tag>
, is_convertible<Reference, Value>
>
, mpl::if_<
iterator_writability_disabled<Value,Reference>
, std::input_iterator_tag
, input_output_iterator_tag
>
, mpl::identity<std::output_iterator_tag>
>
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
::type
# endif
>::type type;
};
// //
// Convert a "strictly old-style" iterator category to a traversal // Convert a "strictly old-style" iterator category to a traversal
// tag. This is broken out into a separate metafunction to reduce // tag. This is broken out into a separate metafunction to reduce
@ -125,7 +58,7 @@ namespace detail
// for new-style types. // for new-style types.
// //
template <class Cat> template <class Cat>
struct old_style_category_to_traversal struct category_to_traversal
: mpl::apply_if< : mpl::apply_if<
is_convertible<Cat,std::random_access_iterator_tag> is_convertible<Cat,std::random_access_iterator_tag>
, mpl::identity<random_access_traversal_tag> , mpl::identity<random_access_traversal_tag>
@ -151,7 +84,7 @@ namespace detail
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) # if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
template <> template <>
struct old_style_category_to_traversal<int> struct category_to_traversal<int>
{ {
typedef int type; typedef int type;
}; };
@ -167,38 +100,10 @@ struct iterator_category_to_traversal
: mpl::apply_if< // if already convertible to a traversal tag, we're done. : mpl::apply_if< // if already convertible to a traversal tag, we're done.
is_convertible<Cat,incrementable_traversal_tag> is_convertible<Cat,incrementable_traversal_tag>
, mpl::identity<Cat> , mpl::identity<Cat>
, detail::old_style_category_to_traversal<Cat> , detail::category_to_traversal<Cat>
> >
{}; {};
//
// To be used for a new-style iterator's iterator_category; provides
// implicit conversion to the appropriate old-style iterator category.
//
// If Value is const the result will not be convertible to
// output_iterator_tag.
//
// Otherwise, if Traversal == single_pass_traversal_tag, the following
// conditions will result in a tag that is convertible both to
// input_iterator_tag and output_iterator_tag:
//
// 1. Reference is a reference to non-const
// 2. Reference is not a reference and is convertible to Value
//
template <class Value, class Reference, class Traversal>
struct iterator_tag
: detail::old_iterator_category<Value, Reference, Traversal>::type
{
operator Traversal() { return Traversal(); }
# if 0
typedef typename detail::old_iterator_category<
Value, Reference, Traversal
>::type old_category;
operator old_category() const { return old_category(); }
# endif
};
// Trait to get an iterator's traversal category // Trait to get an iterator's traversal category
template <class Iterator = mpl::_1> template <class Iterator = mpl::_1>
struct iterator_traversal struct iterator_traversal
@ -226,7 +131,6 @@ struct iterator_traversal<mpl::_>
{}; {};
# endif # endif
} // namespace boost } // namespace boost
#include <boost/iterator/detail/config_undef.hpp> #include <boost/iterator/detail/config_undef.hpp>

View File

@ -12,21 +12,17 @@
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
#include <boost/iterator.hpp> #include <boost/iterator.hpp>
#include <boost/iterator/iterator_categories.hpp> #include <boost/iterator/detail/facade_iterator_category.hpp>
#include <boost/iterator/interoperable.hpp> #include <boost/iterator/interoperable.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/iterator/detail/enable_if.hpp> #include <boost/iterator/detail/enable_if.hpp>
#include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/type_traits/remove_const.hpp> #include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/is_convertible.hpp>
#ifdef BOOST_ITERATOR_REFERENCE_PRIMACY
# include <boost/type_traits/add_pointer.hpp>
# include <boost/type_traits/add_const.hpp>
#endif
#include <boost/mpl/apply_if.hpp> #include <boost/mpl/apply_if.hpp>
#include <boost/mpl/or.hpp> #include <boost/mpl/or.hpp>
@ -36,22 +32,8 @@ namespace boost
{ {
// This forward declaration is required for the friend declaration // This forward declaration is required for the friend declaration
// in iterator_core_access // in iterator_core_access
template <class I, class V, class TC, class R, class D> class iterator_facade; template <class I, class V, class C, class R, class D> class iterator_facade;
// Used as a default template argument internally, merely to
// indicate "use the default", this can also be passed by users
// explicitly in order to specify that the default should be used.
struct use_default;
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// the incompleteness of use_default causes massive problems for
// is_convertible (naturally). This workaround is fortunately not
// needed for vc6/vc7.
template<class To>
struct is_convertible<use_default,To>
: mpl::false_ {};
# endif
namespace detail namespace detail
{ {
// //
@ -82,37 +64,41 @@ namespace boost
}; };
// //
// Generates the associated types for an iterator_facade with the // Generates associated types for an iterator_facade with the
// given parameters. Additionally generates a 'base' type for // given parameters.
// compiler/library combinations which require user-defined
// iterators to inherit from std::iterator.
// //
template < template <
class Value class ValueParam
, class TraversalCategory , class CategoryOrTraversal
, class Reference , class Reference
, class Difference , class Difference
> >
struct iterator_facade_types struct iterator_facade_types
{ {
typedef iterator_tag<Value, Reference, TraversalCategory> iterator_category; typedef typename facade_iterator_category<
CategoryOrTraversal, ValueParam, Reference
typedef typename remove_const<Value>::type value_type; >::type iterator_category;
typedef typename remove_const<ValueParam>::type value_type;
typedef typename mpl::apply_if<
detail::iterator_writability_disabled<ValueParam,Reference>
, add_pointer<typename add_const<value_type>::type>
, add_pointer<value_type>
>::type pointer;
# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ # if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
&& (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \ && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \
|| BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \ || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \
|| BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101)) \ || BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101)) \
|| BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 310) || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 310)
# define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1
// To interoperate with some broken library/compiler // To interoperate with some broken library/compiler
// combinations, user-defined iterators must be derived from // combinations, user-defined iterators must be derived from
// std::iterator. It is possible to implement a standard // std::iterator. It is possible to implement a standard
// library for broken compilers without this limitation. // library for broken compilers without this limitation.
# define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1
typedef typedef
iterator<iterator_category, value_type, Difference, Value*, Reference> iterator<iterator_category, value_type, Difference, pointer, Reference>
base; base;
# endif # endif
}; };
@ -176,10 +162,10 @@ namespace boost
public: public:
operator_brackets_proxy(Iterator const& iter) operator_brackets_proxy(Iterator const& iter)
: m_iter(iter) : m_iter(iter)
{} {}
operator reference() operator reference() const
{ {
return *m_iter; return *m_iter;
} }
@ -222,18 +208,18 @@ namespace boost
// Macros which describe the declarations of binary operators // Macros which describe the declarations of binary operators
# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ # define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
template < \ template < \
class Derived1, class V1, class TC1, class R1, class D1 \ class Derived1, class V1, class C1, class R1, class D1 \
, class Derived2, class V2, class TC2, class R2, class D2 \ , class Derived2, class V2, class C2, class R2, class D2 \
> \ > \
prefix typename detail::enable_if_interoperable< \ prefix typename detail::enable_if_interoperable< \
Derived1, Derived2, result_type \ Derived1, Derived2, result_type \
>::type \ >::type \
operator op( \ operator op( \
iterator_facade<Derived1, V1, TC1, R1, D1> const& lhs \ iterator_facade<Derived1, V1, C1, R1, D1> const& lhs \
, iterator_facade<Derived2, V2, TC2, R2, D2> const& rhs) , iterator_facade<Derived2, V2, C2, R2, D2> const& rhs)
# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \ # define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \
template <class Derived, class V, class TC, class R, class D> \ template <class Derived, class V, class C, class R, class D> \
prefix Derived operator+ args prefix Derived operator+ args
// //
@ -254,7 +240,7 @@ namespace boost
public: public:
# else # else
template <class I, class V, class TC, class R, class D> friend class iterator_facade; template <class I, class V, class C, class R, class D> friend class iterator_facade;
# define BOOST_ITERATOR_FACADE_RELATION(op) \ # define BOOST_ITERATOR_FACADE_RELATION(op) \
BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, bool); BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, bool);
@ -274,7 +260,7 @@ namespace boost
BOOST_ITERATOR_FACADE_PLUS_HEAD( BOOST_ITERATOR_FACADE_PLUS_HEAD(
friend friend
, (iterator_facade<Derived, V, TC, R, D> const& , (iterator_facade<Derived, V, C, R, D> const&
, typename Derived::difference_type) , typename Derived::difference_type)
) )
; ;
@ -282,7 +268,7 @@ namespace boost
BOOST_ITERATOR_FACADE_PLUS_HEAD( BOOST_ITERATOR_FACADE_PLUS_HEAD(
friend friend
, (typename Derived::difference_type , (typename Derived::difference_type
, iterator_facade<Derived, V, TC, R, D> const&) , iterator_facade<Derived, V, C, R, D> const&)
) )
; ;
@ -337,14 +323,14 @@ namespace boost
template < template <
class Derived // The derived iterator type being constructed class Derived // The derived iterator type being constructed
, class Value , class Value
, class TraversalCategory , class CategoryOrTraversal
, class Reference = Value& , class Reference = Value&
, class Difference = std::ptrdiff_t , class Difference = std::ptrdiff_t
> >
class iterator_facade class iterator_facade
# ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE # ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
: public detail::iterator_facade_types< : public detail::iterator_facade_types<
Value, TraversalCategory, Reference, Difference Value, CategoryOrTraversal, Reference, Difference
>::base >::base
# undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE # undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
# endif # endif
@ -365,21 +351,17 @@ namespace boost
return static_cast<Derived const&>(*this); return static_cast<Derived const&>(*this);
} }
typedef detail::iterator_facade_types<
Value, CategoryOrTraversal, Reference, Difference
> associated_types;
public: public:
typedef typename remove_const<Value>::type value_type; typedef typename associated_types::value_type value_type;
typedef Reference reference; typedef Reference reference;
typedef Difference difference_type; typedef Difference difference_type;
# if BOOST_ITERATOR_REFERENCE_PRIMACY typedef typename associated_types::pointer pointer;
typedef typename mpl::apply_if< typedef typename associated_types::iterator_category iterator_category;
detail::iterator_writability_disabled<Value,Reference>
, add_pointer<typename add_const<value_type>::type>
, add_pointer<value_type>
>::type pointer;
# else
typedef Value* pointer;
# endif
typedef iterator_tag<Value,Reference,TraversalCategory> iterator_category;
reference operator*() const reference operator*() const
{ {
@ -403,9 +385,9 @@ namespace boost
typename detail::operator_brackets_result<Derived,Value,Reference>::type typename detail::operator_brackets_result<Derived,Value,Reference>::type
operator[](difference_type n) const operator[](difference_type n) const
{ {
typedef detail::iterator_writability_disabled<Value,Reference> use_proxy; typedef detail::iterator_writability_disabled<Value,Reference> not_writable;
return detail::make_operator_brackets_result<Derived>(this->derived() + n, use_proxy()); return detail::make_operator_brackets_result<Derived>(this->derived() + n, not_writable());
} }
Derived& operator++() Derived& operator++()
@ -583,13 +565,13 @@ namespace boost
} }
BOOST_ITERATOR_FACADE_PLUS(( BOOST_ITERATOR_FACADE_PLUS((
iterator_facade<Derived, V, TC, R, D> const& i iterator_facade<Derived, V, C, R, D> const& i
, typename Derived::difference_type n , typename Derived::difference_type n
)) ))
BOOST_ITERATOR_FACADE_PLUS(( BOOST_ITERATOR_FACADE_PLUS((
typename Derived::difference_type n typename Derived::difference_type n
, iterator_facade<Derived, V, TC, R, D> const& i , iterator_facade<Derived, V, C, R, D> const& i
)) ))
# undef BOOST_ITERATOR_FACADE_PLUS # undef BOOST_ITERATOR_FACADE_PLUS
# undef BOOST_ITERATOR_FACADE_PLUS_HEAD # undef BOOST_ITERATOR_FACADE_PLUS_HEAD

View File

@ -24,15 +24,11 @@
# include <boost/concept_archetype.hpp> // for detail::dummy_constructor # include <boost/concept_archetype.hpp> // for detail::dummy_constructor
# include <boost/detail/iterator.hpp> # include <boost/detail/iterator.hpp>
# include <boost/pending/iterator_tests.hpp> # include <boost/pending/iterator_tests.hpp>
# include <boost/iterator/is_readable_iterator.hpp>
# include <boost/iterator/is_lvalue_iterator.hpp>
namespace boost { namespace boost {
void is_readable(readable_iterator_tag) { }
void is_writable(writable_iterator_tag) { }
void is_swappable(swappable_iterator_tag) { }
void is_constant_lvalue(readable_lvalue_iterator_tag) { }
void is_mutable_lvalue(writable_lvalue_iterator_tag) { }
// Preconditions: *i == v // Preconditions: *i == v
template <class Iterator, class T> template <class Iterator, class T>
void readable_iterator_test(const Iterator i1, T v) void readable_iterator_test(const Iterator i1, T v)
@ -45,8 +41,12 @@ void readable_iterator_test(const Iterator i1, T v)
T v2 = r2; T v2 = r2;
assert(v1 == v); assert(v1 == v);
assert(v2 == v); assert(v2 == v);
typedef typename access_category<Iterator>::type result_category;
is_readable(result_category()); # if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
// I think we don't really need this as it checks the same things as
// the above code.
BOOST_STATIC_ASSERT(is_readable_iterator<Iterator>::value);
# endif
} }
template <class Iterator, class T> template <class Iterator, class T>
@ -54,7 +54,6 @@ void writable_iterator_test(Iterator i, T v)
{ {
Iterator i2(i); // Copy Constructible Iterator i2(i); // Copy Constructible
*i2 = v; *i2 = v;
is_writable(typename access_category<Iterator>::type());
} }
template <class Iterator> template <class Iterator>
@ -65,8 +64,6 @@ void swappable_iterator_test(Iterator i, Iterator j)
iter_swap(i2, j2); iter_swap(i2, j2);
typename detail::iterator_traits<Iterator>::value_type ai = *i, aj = *j; typename detail::iterator_traits<Iterator>::value_type ai = *i, aj = *j;
assert(bi == aj && bj == ai); assert(bi == aj && bj == ai);
typedef typename access_category<Iterator>::type result_category;
is_swappable(result_category());
} }
template <class Iterator, class T> template <class Iterator, class T>
@ -78,12 +75,13 @@ void constant_lvalue_iterator_test(Iterator i, T v1)
BOOST_STATIC_ASSERT((is_same<const value_type&, reference>::value)); BOOST_STATIC_ASSERT((is_same<const value_type&, reference>::value));
const T& v2 = *i2; const T& v2 = *i2;
assert(v1 == v2); assert(v1 == v2);
typedef typename access_category<Iterator>::type result_category; # if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
is_constant_lvalue(result_category()); BOOST_STATIC_ASSERT(is_lvalue_iterator<Iterator>::value);
# endif
} }
template <class Iterator, class T> template <class Iterator, class T>
void mutable_lvalue_iterator_test(Iterator i, T v1, T v2) void writable_lvalue_iterator_test(Iterator i, T v1, T v2)
{ {
Iterator i2(i); Iterator i2(i);
typedef typename detail::iterator_traits<Iterator>::value_type value_type; typedef typename detail::iterator_traits<Iterator>::value_type value_type;
@ -94,8 +92,9 @@ void mutable_lvalue_iterator_test(Iterator i, T v1, T v2)
*i = v2; *i = v2;
T& v4 = *i2; T& v4 = *i2;
assert(v2 == v4); assert(v2 == v4);
typedef typename access_category<Iterator>::type result_category; # if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
is_mutable_lvalue(result_category()); BOOST_STATIC_ASSERT(is_lvalue_iterator<Iterator>::value);
# endif
} }
template <class Iterator, class T> template <class Iterator, class T>

View File

@ -286,7 +286,7 @@ int main()
# ifndef BOOST_NO_SLIST # ifndef BOOST_NO_SLIST
test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >(); test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
# endif # endif
// Also prove that we can handle raw pointers. // Also prove that we can handle raw pointers.
int array[2000]; int array[2000];
test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1)); test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1));

View File

@ -181,11 +181,22 @@ struct constant_iterator
: base_t(it) {} : base_t(it) {}
}; };
char (& traversal(boost::incrementable_traversal_tag) )[1]; char (& traversal2(boost::incrementable_traversal_tag) )[1];
char (& traversal(boost::single_pass_traversal_tag ) )[2]; char (& traversal2(boost::single_pass_traversal_tag ) )[2];
char (& traversal(boost::forward_traversal_tag ) )[3]; char (& traversal2(boost::forward_traversal_tag ) )[3];
char (& traversal(boost::bidirectional_traversal_tag) )[4]; char (& traversal2(boost::bidirectional_traversal_tag) )[4];
char (& traversal(boost::random_access_traversal_tag) )[5]; char (& traversal2(boost::random_access_traversal_tag) )[5];
template <class Cat>
struct traversal3
{
static typename boost::iterator_category_to_traversal<Cat>::type x;
BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(traversal2(x)));
typedef char (&type)[value];
};
template <class Cat>
typename traversal3<Cat>::type traversal(Cat);
int int
main() main()
@ -244,7 +255,7 @@ main()
test = static_assert_same<Iter::pointer, int const*>::value; test = static_assert_same<Iter::pointer, int const*>::value;
#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) #if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
BOOST_STATIC_ASSERT(boost::is_mutable_lvalue_iterator<BaseIter>::value); BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<BaseIter>::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<Iter>::value); BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<Iter>::value);
#endif #endif