$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r78184 - in branches/release: boost/iterator libs/iterator libs/iterator/doc libs/iterator/test
From: jeffrey.hellrung_at_[hidden]
Date: 2012-04-24 17:28:09
Author: jeffrey.hellrung
Date: 2012-04-24 17:28:07 EDT (Tue, 24 Apr 2012)
New Revision: 78184
URL: http://svn.boost.org/trac/boost/changeset/78184
Log:
merging from trunk; fix #5127 from M. Morin; fix for refs #5697
Properties modified: 
   branches/release/boost/iterator/   (props changed)
   branches/release/boost/iterator/iterator_facade.hpp   (contents, props changed)
   branches/release/libs/iterator/   (props changed)
Text files modified: 
   branches/release/boost/iterator/iterator_facade.hpp             |    72 ++++++++++++++++------------------      
   branches/release/boost/iterator/transform_iterator.hpp          |     2                                         
   branches/release/libs/iterator/doc/transform_iterator.html      |     6 +-                                      
   branches/release/libs/iterator/doc/transform_iterator_ref.rst   |     6 +-                                      
   branches/release/libs/iterator/test/iterator_facade.cpp         |    82 +++++++++++++++++++++++++++++++++------ 
   branches/release/libs/iterator/test/transform_iterator_test.cpp |    12 ++++-                                   
   6 files changed, 118 insertions(+), 62 deletions(-)
Modified: branches/release/boost/iterator/iterator_facade.hpp
==============================================================================
--- branches/release/boost/iterator/iterator_facade.hpp	(original)
+++ branches/release/boost/iterator/iterator_facade.hpp	2012-04-24 17:28:07 EDT (Tue, 24 Apr 2012)
@@ -14,8 +14,8 @@
 #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/utility/addressof.hpp>
 
 #include <boost/type_traits/is_same.hpp>
 #include <boost/type_traits/add_const.hpp>
@@ -294,46 +294,43 @@
 
     // 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 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) {}
-        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 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 ValueType, class Reference, class Pointer>
-    struct operator_arrow_result
-    {
-        // CWPro8.3 won't accept "operator_arrow_result::type", and we
-        // need that type below, so metafunction forwarding would be a
-        // losing proposition here.
-        typedef typename mpl::if_<
-            is_reference<Reference>
-          , Pointer
-          , operator_arrow_proxy<ValueType>
-        >::type type;
+    // produce a 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>
+    struct operator_arrow_dispatch // proxy references
+    {
+        struct proxy
+        {
+            explicit proxy(Reference const & x) : m_ref(x) {}
+            Reference* operator->() { return boost::addressof(m_ref); }
+            // This function is needed for MWCW and BCC, which won't call
+            // operator-> again automatically per 13.3.1.2 para 8
+            operator Reference*() { return boost::addressof(m_ref); }
+            Reference m_ref;
+        };
+        typedef proxy result_type;
+        static result_type apply(Reference const & x)
+        {
+            return result_type(x);
+        }
+    };
 
-        static type make(Reference x)
+    template <class T, class Pointer>
+    struct operator_arrow_dispatch<T&, Pointer> // "real" references
+    {
+        typedef Pointer result_type;
+        static result_type apply(T& x)
         {
-            return boost::implicit_cast<type>(&x);
+            return boost::addressof(x);
         }
     };
 
 # if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
     // Deal with ETI
     template<>
-    struct operator_arrow_result<int, int, int>
+    struct operator_arrow_dispatch<int, int>
     {
-        typedef int type;
+        typedef int result_type;
     };
 # endif
 
@@ -618,11 +615,10 @@
          Value, CategoryOrTraversal, Reference, Difference
       > associated_types;
 
-      typedef boost::detail::operator_arrow_result<
-        typename associated_types::value_type
-        , Reference
+      typedef boost::detail::operator_arrow_dispatch<
+          Reference
         , typename associated_types::pointer
-      > pointer_;
+      > operator_arrow_dispatch_;
 
    protected:
       // For use by derived classes
@@ -634,7 +630,7 @@
       typedef Reference reference;
       typedef Difference difference_type;
 
-      typedef typename pointer_::type pointer;
+      typedef typename operator_arrow_dispatch_::result_type pointer;
 
       typedef typename associated_types::iterator_category iterator_category;
 
@@ -645,7 +641,7 @@
 
       pointer operator->() const
       {
-          return pointer_::make(*this->derived());
+          return operator_arrow_dispatch_::apply(*this->derived());
       }
         
       typename boost::detail::operator_brackets_result<Derived,Value,reference>::type
Modified: branches/release/boost/iterator/transform_iterator.hpp
==============================================================================
--- branches/release/boost/iterator/transform_iterator.hpp	(original)
+++ branches/release/boost/iterator/transform_iterator.hpp	2012-04-24 17:28:07 EDT (Tue, 24 Apr 2012)
@@ -46,7 +46,7 @@
         // the function.
         typedef typename ia_dflt_help<
             Reference
-          , result_of<UnaryFunc(typename std::iterator_traits<Iterator>::reference)>
+          , result_of<const UnaryFunc(typename std::iterator_traits<Iterator>::reference)>
         >::type reference;
 
         // To get the default for Value: remove any reference on the
Modified: branches/release/libs/iterator/doc/transform_iterator.html
==============================================================================
--- branches/release/libs/iterator/doc/transform_iterator.html	(original)
+++ branches/release/libs/iterator/doc/transform_iterator.html	2012-04-24 17:28:07 EDT (Tue, 24 Apr 2012)
@@ -99,7 +99,7 @@
 </pre>
 <p>If <tt class="docutils literal"><span class="pre">Reference</span></tt> is <tt class="docutils literal"><span class="pre">use_default</span></tt> then the <tt class="docutils literal"><span class="pre">reference</span></tt> member of
 <tt class="docutils literal"><span class="pre">transform_iterator</span></tt> is
-<tt class="docutils literal"><span class="pre">result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type</span></tt>.
+<tt class="docutils literal"><span class="pre">result_of<const UnaryFunction(iterator_traits<Iterator>::reference)>::type</span></tt>.
 Otherwise, <tt class="docutils literal"><span class="pre">reference</span></tt> is <tt class="docutils literal"><span class="pre">Reference</span></tt>.</p>
 <p>If <tt class="docutils literal"><span class="pre">Value</span></tt> is <tt class="docutils literal"><span class="pre">use_default</span></tt> then the <tt class="docutils literal"><span class="pre">value_type</span></tt> member is
 <tt class="docutils literal"><span class="pre">remove_cv<remove_reference<reference></span> <span class="pre">>::type</span></tt>.  Otherwise,
@@ -117,10 +117,10 @@
 <div class="section" id="transform-iterator-requirements">
 <h1><a class="toc-backref" href="#id3"><tt class="docutils literal"><span class="pre">transform_iterator</span></tt> requirements</a></h1>
 <p>The type <tt class="docutils literal"><span class="pre">UnaryFunction</span></tt> must be Assignable, Copy Constructible, and
-the expression <tt class="docutils literal"><span class="pre">f(*i)</span></tt> must be valid where <tt class="docutils literal"><span class="pre">f</span></tt> is an object of
+the expression <tt class="docutils literal"><span class="pre">f(*i)</span></tt> must be valid where <tt class="docutils literal"><span class="pre">f</span></tt> is a const object of
 type <tt class="docutils literal"><span class="pre">UnaryFunction</span></tt>, <tt class="docutils literal"><span class="pre">i</span></tt> is an object of type <tt class="docutils literal"><span class="pre">Iterator</span></tt>, and
 where the type of <tt class="docutils literal"><span class="pre">f(*i)</span></tt> must be
-<tt class="docutils literal"><span class="pre">result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type</span></tt>.</p>
+<tt class="docutils literal"><span class="pre">result_of<const UnaryFunction(iterator_traits<Iterator>::reference)>::type</span></tt>.</p>
 <p>The argument <tt class="docutils literal"><span class="pre">Iterator</span></tt> shall model Readable Iterator.</p>
 </div>
 <div class="section" id="transform-iterator-models">
Modified: branches/release/libs/iterator/doc/transform_iterator_ref.rst
==============================================================================
--- branches/release/libs/iterator/doc/transform_iterator_ref.rst	(original)
+++ branches/release/libs/iterator/doc/transform_iterator_ref.rst	2012-04-24 17:28:07 EDT (Tue, 24 Apr 2012)
@@ -41,7 +41,7 @@
 
 If ``Reference`` is ``use_default`` then the ``reference`` member of
 ``transform_iterator`` is
-``result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type``.
+``result_of<const UnaryFunction(iterator_traits<Iterator>::reference)>::type``.
 Otherwise, ``reference`` is ``Reference``.
 
 If ``Value`` is ``use_default`` then the ``value_type`` member is
@@ -64,10 +64,10 @@
 ...................................
 
 The type ``UnaryFunction`` must be Assignable, Copy Constructible, and
-the expression ``f(*i)`` must be valid where ``f`` is an object of
+the expression ``f(*i)`` must be valid where ``f`` is a const object of
 type ``UnaryFunction``, ``i`` is an object of type ``Iterator``, and
 where the type of ``f(*i)`` must be
-``result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type``.
+``result_of<const UnaryFunction(iterator_traits<Iterator>::reference)>::type``.
 
 The argument ``Iterator`` shall model Readable Iterator.  
 
Modified: branches/release/libs/iterator/test/iterator_facade.cpp
==============================================================================
--- branches/release/libs/iterator/test/iterator_facade.cpp	(original)
+++ branches/release/libs/iterator/test/iterator_facade.cpp	2012-04-24 17:28:07 EDT (Tue, 24 Apr 2012)
@@ -7,6 +7,10 @@
 #include <boost/iterator/iterator_facade.hpp>
 #include <boost/iterator/new_iterator_tests.hpp>
 
+#include <boost/call_traits.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/utility/enable_if.hpp>
+
 // This is a really, really limited test so far.  All we're doing
 // right now is checking that the postfix++ proxy for single-pass
 // iterators works properly.
@@ -87,26 +91,76 @@
     }
 };
 
+template <class T>
+struct wrapper
+{
+    T m_x;
+    explicit wrapper(typename boost::call_traits<T>::param_type x)
+        : m_x(x)
+    { }
+    template <class U>
+    wrapper(const wrapper<U>& other,
+        typename boost::enable_if< boost::is_convertible<U,T> >::type* = 0)
+        : m_x(other.m_x)
+    { }
+};
+
+struct iterator_with_proxy_reference
+    : boost::iterator_facade<
+          iterator_with_proxy_reference
+        , wrapper<int>
+        , boost::incrementable_traversal_tag
+        , wrapper<int&>
+      >
+{
+    int& m_x;
+    explicit iterator_with_proxy_reference(int& x)
+        : m_x(x)
+    { }
+
+    void increment()
+    { }
+    wrapper<int&> dereference() const
+    { return wrapper<int&>(m_x); }
+};
+
 template <class T, class U>
 void same_type(U const&)
 { BOOST_MPL_ASSERT((boost::is_same<T,U>)); }
 
 int main()
 {
-    int state = 0;
-    boost::readable_iterator_test(counter_iterator<int const&>(&state), 0);
-    state = 3;
-    boost::readable_iterator_test(counter_iterator<proxy>(&state), 3);
-    boost::writable_iterator_test(counter_iterator<proxy>(&state), 9, 7);
-    BOOST_TEST(state == 8);
-
-    // test for a fix to http://tinyurl.com/zuohe
-    // These two lines should be equivalent (and both compile)
-    input_iter p;
-    (*p).mutator();
-    p->mutator();
+    {
+        int state = 0;
+        boost::readable_iterator_test(counter_iterator<int const&>(&state), 0);
+        state = 3;
+        boost::readable_iterator_test(counter_iterator<proxy>(&state), 3);
+        boost::writable_iterator_test(counter_iterator<proxy>(&state), 9, 7);
+        BOOST_TEST(state == 8);
+    }
+
+    {
+        // test for a fix to http://tinyurl.com/zuohe
+        // These two lines should be equivalent (and both compile)
+        input_iter p;
+        (*p).mutator();
+        p->mutator();
+
+        same_type<input_iter::pointer>(p.operator->());
+    }
+
+    {
+        int x = 0;
+        iterator_with_proxy_reference i(x);
+        BOOST_TEST(x == 0);
+        BOOST_TEST(i.m_x == 0);
+        ++(*i).m_x;
+        BOOST_TEST(x == 1);
+        BOOST_TEST(i.m_x == 1);
+        ++i->m_x;
+        BOOST_TEST(x == 2);
+        BOOST_TEST(i.m_x == 2);
+    }
 
-    same_type<input_iter::pointer>(p.operator->());
-    
     return boost::report_errors();
 }
Modified: branches/release/libs/iterator/test/transform_iterator_test.cpp
==============================================================================
--- branches/release/libs/iterator/test/transform_iterator_test.cpp	(original)
+++ branches/release/libs/iterator/test/transform_iterator_test.cpp	2012-04-24 17:28:07 EDT (Tue, 24 Apr 2012)
@@ -12,6 +12,7 @@
 //       Moved test of transform iterator into its own file. It to
 //       to be in iterator_adaptor_test.cpp.
 
+#include <boost/assert.hpp>
 #include <boost/config.hpp>
 #include <algorithm>
 #include <boost/iterator/transform_iterator.hpp>
@@ -106,12 +107,17 @@
 {
     //Implement result_of protocol
     template <class FArgs> struct result;
-    template <class F, class T> struct result<F(T       )> {typedef T type;};
-    template <class F, class T> struct result<F(T&      )> {typedef T type;};
-    template <class F, class T> struct result<F(const T&)> {typedef T type;};
+    template <class F, class T> struct result<const F(T       )> {typedef T type;};
+    template <class F, class T> struct result<const F(T&      )> {typedef T type;};
+    template <class F, class T> struct result<const F(const T&)> {typedef T type;};
+    template <class F, class T> struct result<F(T       )> {typedef void type;};
+    template <class F, class T> struct result<F(T&      )> {typedef void type;};
+    template <class F, class T> struct result<F(const T&)> {typedef void type;};
 
     template <class T> 
     T operator()(const T& _arg) const {return _arg*2;}
+    template <class T> 
+    void operator()(const T& _arg) { BOOST_ASSERT(0); }
 };
 
 int