$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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;