Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r80901 - in trunk: boost/iterator boost/iterator/detail libs/iterator/test
From: jeffrey.hellrung_at_[hidden]
Date: 2012-10-07 22:02:10


Author: jeffrey.hellrung
Date: 2012-10-07 22:02:09 EDT (Sun, 07 Oct 2012)
New Revision: 80901
URL: http://svn.boost.org/trac/boost/changeset/80901

Log:
- BREAKING CHANGE: iterator_facade::pointer now corresponds to the actual result of iterator_facade::operator-> rather than Value*. This required an adjustment to a test.
- The logic for determining the result of iterator_facade::operator[] has been factored out into a separate detail header in preparation for its potential use in iterator_range to avoid iterator_range::operator[] from returning a reference to a temporary.
Added:
   trunk/boost/iterator/detail/operator_brackets_dispatch.hpp (contents, props changed)
Text files modified:
   trunk/boost/iterator/iterator_facade.hpp | 151 ++++++++++-----------------------------
   trunk/libs/iterator/test/indirect_iter_member_types.cpp | 2
   2 files changed, 42 insertions(+), 111 deletions(-)

Added: trunk/boost/iterator/detail/operator_brackets_dispatch.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/iterator/detail/operator_brackets_dispatch.hpp 2012-10-07 22:02:09 EDT (Sun, 07 Oct 2012)
@@ -0,0 +1,88 @@
+// (C) Copyright David Abrahams 2002.
+// (C) Copyright Jeremy Siek 2002.
+// (C) Copyright Thomas Witt 2002.
+// (C) Copyright Jeffrey Lee Hellrung, Jr. 2012.
+// 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_OPERATOR_BRACKETS_DISPATCH_07102012JLH_HPP
+#define BOOST_OPERATOR_BRACKETS_DISPATCH_07102012JLH_HPP
+
+#include <boost/iterator/detail/facade_iterator_category.hpp>
+
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/mpl/if.hpp>
+
+namespace boost { namespace detail {
+
+// operator[] must return a proxy in case iterator destruction invalidates
+// referents.
+// To see why, consider the following implementation of operator[]:
+// reference operator[](difference_type n) const
+// { return *(*this + n); }
+// The problem here is that operator[] would return a reference created from
+// a temporary iterator.
+
+template <class Value>
+struct operator_brackets_value
+{
+ typedef Value result_type;
+ template <class Iterator>
+ static result_type apply(Iterator const & i)
+ { return *i; }
+};
+
+template <class Iterator, class Reference>
+struct operator_brackets_const_proxy
+{
+ class result_type
+ {
+ Iterator const m_i;
+ explicit result_type(Iterator const & i) : m_i(i) { }
+ friend struct operator_brackets_const_proxy;
+ void operator=(result_type&);
+ public:
+ operator Reference() const { return *m_i; }
+ };
+ static result_type apply(Iterator const & i)
+ { return result_type(i); }
+};
+
+template <class Iterator, class Reference>
+struct operator_brackets_proxy
+{
+ class result_type
+ {
+ Iterator const m_i;
+ explicit result_type(Iterator const & i) : m_i(i) { }
+ friend struct operator_brackets_proxy;
+ void operator=(result_type&);
+ public:
+ operator Reference() const { return *m_i; }
+ operator_brackets_proxy const & operator=(
+ typename Iterator::value_type const & x) const
+ { *m_i = x; return *this; }
+ };
+ static result_type apply(Iterator const & i)
+ { return result_type(i); }
+};
+
+template <class Iterator, class ValueType, class Reference>
+struct operator_brackets_dispatch
+{
+ typedef typename mpl::if_c<
+ iterator_writability_disabled<ValueType,Reference>::value,
+ typename mpl::if_c<
+ boost::is_POD<ValueType>::value,
+ operator_brackets_value<typename boost::remove_const<ValueType>::type>,
+ operator_brackets_const_proxy<Iterator,Reference>
+ >::type,
+ operator_brackets_proxy<Iterator,Reference>
+ >::type type;
+};
+
+} } // namespace detail / namespace boost
+
+#endif // #ifndef BOOST_OPERATOR_BRACKETS_DISPATCH_07102012JLH_HPP

Modified: trunk/boost/iterator/iterator_facade.hpp
==============================================================================
--- trunk/boost/iterator/iterator_facade.hpp (original)
+++ trunk/boost/iterator/iterator_facade.hpp 2012-10-07 22:02:09 EDT (Sun, 07 Oct 2012)
@@ -1,6 +1,7 @@
 // (C) Copyright David Abrahams 2002.
 // (C) Copyright Jeremy Siek 2002.
 // (C) Copyright Thomas Witt 2002.
+// (C) copyright Jeffrey Lee Hellrung, Jr. 2012.
 // 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)
@@ -13,6 +14,7 @@
 
 #include <boost/iterator/detail/facade_iterator_category.hpp>
 #include <boost/iterator/detail/enable_if.hpp>
+#include <boost/iterator/detail/operator_brackets_dispatch.hpp>
 
 #include <boost/static_assert.hpp>
 #include <boost/utility/addressof.hpp>
@@ -75,7 +77,7 @@
           , Return
           , int[3]
>::type type;
- };
+ };
 #else
       : ::boost::iterators::enable_if<
            mpl::or_<
@@ -85,7 +87,7 @@
          , Return
>
     {};
-#endif
+#endif
 
     //
     // Generates associated types for an iterator_facade with the
@@ -94,7 +96,7 @@
     template <
         class ValueParam
       , class CategoryOrTraversal
- , class Reference
+ , class Reference
       , class Difference
>
     struct iterator_facade_types
@@ -102,16 +104,16 @@
         typedef typename facade_iterator_category<
             CategoryOrTraversal, ValueParam, Reference
>::type iterator_category;
-
+
         typedef typename remove_const<ValueParam>::type value_type;
-
+
         // Not the real associated pointer type
         typedef typename mpl::eval_if<
             boost::detail::iterator_writability_disabled<ValueParam,Reference>
           , add_pointer<const value_type>
           , add_pointer<value_type>
>::type pointer;
-
+
 # if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
     && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \
         || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \
@@ -157,7 +159,7 @@
      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
@@ -209,7 +211,7 @@
         {
             return stored_iterator;
         }
-
+
      private:
         mutable value_type stored_value;
         Iterator stored_iterator;
@@ -221,7 +223,7 @@
     struct is_non_proxy_reference_impl
     {
         static Reference r;
-
+
         template <class R>
         static typename mpl::if_<
             is_convertible<
@@ -231,17 +233,17 @@
           , 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
+# else
     template <class Reference, class Value>
     struct is_non_proxy_reference
       : is_convertible<
@@ -250,8 +252,8 @@
           , Value const volatile*
>
     {};
-# endif
-
+# endif
+
     // A metafunction to choose the result type of postfix ++
     //
     // Because the C++98 input iterator requirements say that *r++ has
@@ -273,7 +275,7 @@
             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_<
@@ -296,7 +298,7 @@
     // standard's requirements. If *i is not a reference type, we must still
     // produce an lvalue to which a pointer can be formed. We do that by
     // returning a proxy object containing an instance of the reference object.
- template <class Reference, class Pointer>
+ template <class Reference>
     struct operator_arrow_dispatch // proxy references
     {
         struct proxy
@@ -315,10 +317,10 @@
         }
     };
 
- template <class T, class Pointer>
- struct operator_arrow_dispatch<T&, Pointer> // "real" references
+ template <class T>
+ struct operator_arrow_dispatch<T&> // "real" references
     {
- typedef Pointer result_type;
+ typedef T* result_type;
         static result_type apply(T& x)
         {
             return boost::addressof(x);
@@ -328,79 +330,12 @@
 # if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
     // Deal with ETI
     template<>
- struct operator_arrow_dispatch<int, int>
+ struct operator_arrow_dispatch<int>
     {
         typedef int result_type;
     };
 # endif
 
- // 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;
-
- public:
- operator_brackets_proxy(Iterator const& iter)
- : m_iter(iter)
- {}
-
- operator reference() const
- {
- return *m_iter;
- }
-
- operator_brackets_proxy& operator=(value_type const& val)
- {
- *m_iter = val;
- return *this;
- }
-
- private:
- Iterator m_iter;
- };
-
- // 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::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>
- >
- >
- {};
-
- template <class Iterator, class Value, class Reference>
- struct operator_brackets_result
- {
- typedef typename mpl::if_<
- use_operator_brackets_proxy<Value,Reference>
- , operator_brackets_proxy<Iterator>
- , Value
- >::type type;
- };
-
- template <class Iterator>
- 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::false_)
- {
- return *iter;
- }
-
     struct choose_difference_type
     {
         template <class I1, class I2>
@@ -414,13 +349,13 @@
             , typename I1::difference_type
             , typename I2::difference_type
>
-# else
+# else
           mpl::eval_if<
               is_convertible<I2,I1>
             , iterator_difference<I1>
             , iterator_difference<I2>
>
-# endif
+# endif
         {};
 
     };
@@ -438,7 +373,7 @@
     operator op( \
         iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
       , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
-# else
+# else
 # define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
     template < \
         class Derived1, class V1, class TC1, class Reference1, class Difference1 \
@@ -451,7 +386,7 @@
     operator op( \
         iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
       , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
-# endif
+# endif
 
 # define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \
     template <class Derived, class V, class TC, class R, class D> \
@@ -468,12 +403,12 @@
   //
   class iterator_core_access
   {
-# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
       // Tasteless as this may seem, making all members public allows member templates
       // to work in the absence of member template friends.
    public:
 # else
-
+
       template <class I, class V, class TC, class R, class D> friend class iterator_facade;
 
 # define BOOST_ITERATOR_FACADE_RELATION(op) \
@@ -616,14 +551,15 @@
> associated_types;
 
       typedef boost::detail::operator_arrow_dispatch<
- Reference
- , typename associated_types::pointer
- > operator_arrow_dispatch_;
+ Reference> operator_arrow_dispatch_;
+
+ typedef typename boost::detail::operator_brackets_dispatch<
+ Derived, Value, Reference>::type operator_brackets_dispatch_;
 
    protected:
       // For use by derived classes
       typedef iterator_facade<Derived,Value,CategoryOrTraversal,Reference,Difference> iterator_facade_;
-
+
    public:
 
       typedef typename associated_types::value_type value_type;
@@ -643,16 +579,11 @@
       {
           return operator_arrow_dispatch_::apply(*this->derived());
       }
-
- typename boost::detail::operator_brackets_result<Derived,Value,reference>::type
+
+ typename operator_brackets_dispatch_::result_type
       operator[](difference_type n) const
       {
- typedef boost::detail::use_operator_brackets_proxy<Value,Reference> use_proxy;
-
- return boost::detail::make_operator_brackets_result<Derived>(
- this->derived() + n
- , use_proxy()
- );
+ return operator_brackets_dispatch_::apply(this->derived() + n);
       }
 
       Derived& operator++()
@@ -671,7 +602,7 @@
           return tmp;
       }
 # endif
-
+
       Derived& operator--()
       {
           iterator_core_access::decrement(this->derived());
@@ -726,14 +657,14 @@
   {
       typename boost::detail::postfix_increment_result<I,V,R,TC>::type
           tmp(*static_cast<I*>(&i));
-
+
       ++i;
-
+
       return tmp;
   }
-# endif
+# endif
+
 
-
   //
   // Comparison operator implementation. The library supplied operators
   // enables the user to provide fully interoperable constant/mutable

Modified: trunk/libs/iterator/test/indirect_iter_member_types.cpp
==============================================================================
--- trunk/libs/iterator/test/indirect_iter_member_types.cpp (original)
+++ trunk/libs/iterator/test/indirect_iter_member_types.cpp 2012-10-07 22:02:09 EDT (Sun, 07 Oct 2012)
@@ -82,7 +82,7 @@
     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(Iter::pointer, int*);
+ STATIC_ASSERT_SAME(Iter::pointer, long*);
     STATIC_ASSERT_SAME(Iter::difference_type, short);
   }
   return 0;


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk