// (C) Copyright David Abrahams 2002.
// (C) Copyright Jeremy Siek 2002.
// (C) Copyright Thomas Witt 2002.
-// Permission to copy, use, modify,
-// sell and distribute this software is granted provided this
-// copyright notice appears in all copies. This software is provided
-// "as is" without express or implied warranty, and with no claim as
-// to its suitability for any purpose.
+// 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)
#ifndef BOOST_ITERATOR_FACADE_23022003THW_HPP
#define BOOST_ITERATOR_FACADE_23022003THW_HPP
-#include <boost/static_assert.hpp>
-
#include <boost/iterator.hpp>
#include <boost/iterator/interoperable.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/iterator/detail/facade_iterator_category.hpp>
#include <boost/iterator/detail/enable_if.hpp>
+#include <boost/implicit_cast.hpp>
+#include <boost/static_assert.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_reference.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_pod.hpp>
-#include <boost/mpl/apply_if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/if.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/and.hpp>
+#include <boost/mpl/not.hpp>
#include <boost/mpl/always.hpp>
#include <boost/mpl/apply.hpp>
-
-#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
-# include <boost/mpl/if.hpp>
-#endif
+#include <boost/mpl/identity.hpp>
#include <boost/iterator/detail/config_def.hpp> // this goes last
typedef bool type;
};
};
-
+
//
// enable if for use in operator implementation.
//
, class Return
>
struct enable_if_interoperable
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+ {
+ typedef typename mpl::if_<
+ mpl::or_<
+ is_convertible<Facade1, Facade2>
+ , is_convertible<Facade2, Facade1>
+ >
+ , Return
+ , int[3]
+ >::type type;
+ };
+#else
: ::boost::iterators::enable_if<
mpl::or_<
is_convertible<Facade1, Facade2>
>
, Return
>
- {
- };
+ {};
+#endif
//
// Generates associated types for an iterator_facade with the
typedef typename remove_const<ValueParam>::type value_type;
- typedef typename mpl::apply_if<
+ typedef typename mpl::eval_if<
detail::iterator_writability_disabled<ValueParam,Reference>
- , add_pointer<typename add_const<value_type>::type>
+ , add_pointer<const value_type>
, add_pointer<value_type>
>::type pointer;
# endif
};
+ // iterators whose dereference operators reference the same value
+ // for all iterators into the same sequence (like many input
+ // iterators) need help with their postfix ++: the referenced
+ // value must be read and stored away before the increment occurs
+ // so that *a++ yields the originally referenced element and not
+ // the next one.
+ template <class Iterator>
+ class postfix_increment_proxy
+ {
+ typedef typename iterator_value<Iterator>::type value_type;
+ public:
+ explicit postfix_increment_proxy(Iterator const& x)
+ : stored_value(*x)
+ {}
+
+ // Returning a mutable reference allows nonsense like
+ // (*r++).mutate(), but it imposes fewer assumptions about the
+ // behavior of the value_type. In particular, recall taht
+ // (*r).mutate() is legal if operator* returns by value.
+ value_type&
+ operator*() const
+ {
+ return this->stored_value;
+ }
+ private:
+ mutable value_type stored_value;
+ };
+
+ //
+ // In general, we can't determine that such an iterator isn't
+ // writable -- we also need to store a copy of the old iterator so
+ // that it can be written into.
+ template <class Iterator>
+ class writable_postfix_increment_proxy
+ {
+ typedef typename iterator_value<Iterator>::type value_type;
+ public:
+ explicit writable_postfix_increment_proxy(Iterator const& x)
+ : stored_value(*x)
+ , stored_iterator(x)
+ {}
+
+ // Dereferencing must return a proxy so that both *r++ = o and
+ // value_type(*r++) can work. In this case, *r is the same as
+ // *r++, and the conversion operator below is used to ensure
+ // readability.
+ writable_postfix_increment_proxy const&
+ operator*() const
+ {
+ return *this;
+ }
+
+ // Provides readability of *r++
+ operator value_type&() const
+ {
+ return stored_value;
+ }
+
+ // Provides writability of *r++
+ template <class T>
+ T const& operator=(T const& x) const
+ {
+ *this->stored_iterator = x;
+ return x;
+ }
+
+ // This overload just in case only non-const objects are writable
+ template <class T>
+ T& operator=(T& x) const
+ {
+ *this->stored_iterator = x;
+ return x;
+ }
+
+ // Provides X(r++)
+ operator Iterator const&() const
+ {
+ return stored_iterator;
+ }
+
+ private:
+ mutable value_type stored_value;
+ Iterator stored_iterator;
+ };
+
+# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+ template <class Reference, class Value>
+ struct is_non_proxy_reference_impl
+ {
+ static Reference r;
+
+ template <class R>
+ static typename mpl::if_<
+ is_convertible<
+ R const volatile*
+ , Value const volatile*
+ >
+ , char[1]
+ , char[2]
+ >::type& helper(R const&);
+
+ BOOST_STATIC_CONSTANT(bool, value = sizeof(helper(r)) == 1);
+ };
+
+ template <class Reference, class Value>
+ struct is_non_proxy_reference
+ : mpl::bool_<
+ is_non_proxy_reference_impl<Reference, Value>::value
+ >
+ {};
+# else
+ template <class Reference, class Value>
+ struct is_non_proxy_reference
+ : is_convertible<
+ typename remove_reference<Reference>::type
+ const volatile*
+ , Value const volatile*
+ >
+ {};
+# endif
+
+ // A metafunction to choose the result type of postfix ++
+ //
+ // Because the C++98 input iterator requirements say that *r++ has
+ // type T (value_type), implementations of some standard
+ // algorithms like lexicographical_compare may use constructions
+ // like:
+ //
+ // *r++ < *s++
+ //
+ // If *r++ returns a proxy (as required if r is writable but not
+ // multipass), this sort of expression will fail unless the proxy
+ // supports the operator<. Since there are any number of such
+ // operations, we're not going to try to support them. Therefore,
+ // even if r++ returns a proxy, *r++ will only return a proxy if
+ // *r also returns a proxy.
+ template <class Iterator, class Value, class Reference, class CategoryOrTraversal>
+ struct postfix_increment_result
+ : mpl::eval_if<
+ mpl::and_<
+ // A proxy is only needed for readable iterators
+ is_convertible<Reference,Value const&>
+
+ // No multipass iterator can have values that disappear
+ // before positions can be re-visited
+ , mpl::not_<
+ is_convertible<
+ typename iterator_category_to_traversal<CategoryOrTraversal>::type
+ , forward_traversal_tag
+ >
+ >
+ >
+ , mpl::if_<
+ is_non_proxy_reference<Reference,Value>
+ , postfix_increment_proxy<Iterator>
+ , writable_postfix_increment_proxy<Iterator>
+ >
+ , mpl::identity<Iterator>
+ >
+ {};
// operator->() needs special support for input iterators to strictly meet the
// standard's requirements. If *i is not a reference type, we must still
- // produce a (constant) lvalue to which a pointer can be formed. We do that by
+ // produce a lvalue to which a pointer can be formed. We do that by
// returning an instantiation of this special proxy class template.
-
template <class T>
struct operator_arrow_proxy
{
operator_arrow_proxy(T const* px) : m_value(*px) {}
- const T* operator->() const { return &m_value; }
+ T* operator->() const { return &m_value; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
- operator const T*() const { return &m_value; }
- T m_value;
+ operator T*() const { return &m_value; }
+ mutable T m_value;
};
// A metafunction that gets the result type for operator->. Also
// has a static function make() which builds the result from a
// Reference
- template <class Value, class Reference, class Pointer>
+ template <class ValueType, class Reference, class Pointer>
struct operator_arrow_result
{
// CWPro8.3 won't accept "operator_arrow_result::type", and we
typedef typename mpl::if_<
is_reference<Reference>
, Pointer
- , operator_arrow_proxy<Value>
+ , operator_arrow_proxy<ValueType>
>::type type;
static type make(Reference x)
{
- return type(&x);
+ return implicit_cast<type>(&x);
}
};
-# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
+# if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// Deal with ETI
template<>
struct operator_arrow_result<int, int, int>
};
# endif
- //
- // Iterator is actually an iterator_facade, so we do not have to
- // go through iterator_traits to access the traits.
- //
+ // A proxy return type for operator[], needed to deal with
+ // iterators that may invalidate referents upon destruction.
+ // Consider the temporary iterator in *(a + n)
template <class Iterator>
class operator_brackets_proxy
{
+ // Iterator is actually an iterator_facade, so we do not have to
+ // go through iterator_traits to access the traits.
typedef typename Iterator::reference reference;
typedef typename Iterator::value_type value_type;
Iterator m_iter;
};
- template <class Value, class Reference>
+ // A metafunction that determines whether operator[] must return a
+ // proxy, or whether it can simply return a copy of the value_type.
+ template <class ValueType, 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>
+ : mpl::not_<
+ mpl::and_<
+ // Really we want an is_copy_constructible trait here,
+ // but is_POD will have to suffice in the meantime.
+ boost::is_POD<ValueType>
+ , iterator_writability_disabled<ValueType,Reference>
+ >
>
{};
{
typedef typename mpl::if_<
use_operator_brackets_proxy<Value,Reference>
- , Value
, operator_brackets_proxy<Iterator>
+ , Value
>::type type;
};
template <class Iterator>
- operator_brackets_proxy<Iterator> make_operator_brackets_result(Iterator const& iter, mpl::false_)
+ operator_brackets_proxy<Iterator> make_operator_brackets_result(Iterator const& iter, mpl::true_)
{
return operator_brackets_proxy<Iterator>(iter);
}
template <class Iterator>
- typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::true_)
+ typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::false_)
{
return *iter;
}
:
# ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP
iterator_difference<I1>
-# elif BOOST_WORKAROUND(BOOST_MSVC, == 1200)
+# elif BOOST_WORKAROUND(BOOST_MSVC, < 1300)
mpl::if_<
is_convertible<I2,I1>
, typename I1::difference_type
, typename I2::difference_type
>
# else
- mpl::apply_if<
+ mpl::eval_if<
is_convertible<I2,I1>
, iterator_difference<I1>
, iterator_difference<I2>
// Macros which describe the declarations of binary operators
# ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
-# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
- template < \
- class Derived1, class V1, class TC1, class R1, class D1 \
- , class Derived2, class V2, class TC2, class R2, class D2 \
- > \
- prefix typename mpl::apply2<result_type,Derived1,Derived2>::type \
- operator op( \
- iterator_facade<Derived1, V1, TC1, R1, D1> const& lhs \
+# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
+ template < \
+ class Derived1, class V1, class TC1, class R1, class D1 \
+ , class Derived2, class V2, class TC2, class R2, class D2 \
+ > \
+ prefix typename mpl::apply2<result_type,Derived1,Derived2>::type \
+ operator op( \
+ iterator_facade<Derived1, V1, TC1, R1, D1> const& lhs \
, iterator_facade<Derived2, V2, TC2, R2, D2> const& rhs)
# else
# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
class Derived1, class V1, class TC1, class R1, class D1 \
, class Derived2, class V2, class TC2, class R2, class D2 \
> \
- prefix typename detail::enable_if_interoperable< \
+ prefix typename detail::enable_if_interoperable< \
Derived1, Derived2 \
, typename mpl::apply2<result_type,Derived1,Derived2>::type \
>::type \
;
BOOST_ITERATOR_FACADE_PLUS_HEAD(
- friend
+ friend inline
, (iterator_facade<Derived, V, TC, R, D> const&
, typename Derived::difference_type)
)
;
BOOST_ITERATOR_FACADE_PLUS_HEAD(
- friend
+ friend inline
, (typename Derived::difference_type
, iterator_facade<Derived, V, TC, R, D> const&)
)
return f2.distance_to(f1);
}
+ //
+ // Curiously Recurring Template interface.
+ //
+ template <class I, class V, class TC, class R, class D>
+ static I& derived(iterator_facade<I,V,TC,R,D>& facade)
+ {
+ return *static_cast<I*>(&facade);
+ }
+
+ template <class I, class V, class TC, class R, class D>
+ static I const& derived(iterator_facade<I,V,TC,R,D> const& facade)
+ {
+ return *static_cast<I const*>(&facade);
+ }
+
private:
// objects of this class are useless
iterator_core_access(); //undefined
//
// Curiously Recurring Template interface.
//
- typedef Derived derived_t;
-
Derived& derived()
{
- return static_cast<Derived&>(*this);
+ return *static_cast<Derived*>(this);
}
Derived const& derived() const
{
- return static_cast<Derived const&>(*this);
+ return *static_cast<Derived const*>(this);
}
typedef detail::iterator_facade_types<
Value, CategoryOrTraversal, Reference, Difference
> associated_types;
+
+ protected:
+ // For use by derived classes
+ typedef iterator_facade<Derived,Value,CategoryOrTraversal,Reference,Difference> iterator_facade_;
public:
>::make(*this->derived());
}
- typename detail::operator_brackets_result<Derived,Value,Reference>::type
+ typename detail::operator_brackets_result<Derived,Value,reference>::type
operator[](difference_type n) const
{
typedef detail::use_operator_brackets_proxy<Value,Reference> use_proxy;
return this->derived();
}
- Derived operator++(int)
+# if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ typename detail::postfix_increment_result<Derived,Value,Reference,CategoryOrTraversal>::type
+ operator++(int)
{
- Derived tmp(this->derived());
+ typename detail::postfix_increment_result<Derived,Value,Reference,CategoryOrTraversal>::type
+ tmp(this->derived());
++*this;
return tmp;
}
-
+# endif
+
Derived& operator--()
{
iterator_core_access::decrement(this->derived());
return result -= x;
}
-# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
+# if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// There appears to be a bug which trashes the data of classes
// derived from iterator_facade when they are assigned unless we
// define this assignment operator. This bug is only revealed
# endif
};
+# if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ template <class I, class V, class TC, class R, class D>
+ inline typename detail::postfix_increment_result<I,V,R,TC>::type
+ operator++(
+ iterator_facade<I,V,TC,R,D>& i
+ , int
+ )
+ {
+ typename detail::postfix_increment_result<I,V,R,TC>::type
+ tmp(*static_cast<I*>(&i));
+
+ ++i;
+
+ return tmp;
+ }
+# endif
+
+
//
- // Operator implementation. The library supplied operators
+ // Comparison operator implementation. The library supplied operators
// enables the user to provide fully interoperable constant/mutable
// iterator types. I.e. the library provides all operators
// for all mutable/constant iterator combinations.
is_interoperable< Derived1, Derived2 >::value \
)); \
return_prefix iterator_core_access::base_op( \
- static_cast<Derived1 const&>(lhs) \
- , static_cast<Derived2 const&>(rhs) \
+ *static_cast<Derived1 const*>(&lhs) \
+ , *static_cast<Derived2 const*>(&rhs) \
, BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \
); \
}