Boost logo

Boost-Commit :

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&lt;UnaryFunction(iterator_traits&lt;Iterator&gt;::reference)&gt;::type</span></tt>.
+<tt class="docutils literal"><span class="pre">result_of&lt;const UnaryFunction(iterator_traits&lt;Iterator&gt;::reference)&gt;::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&lt;remove_reference&lt;reference&gt;</span> <span class="pre">&gt;::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&lt;UnaryFunction(iterator_traits&lt;Iterator&gt;::reference)&gt;::type</span></tt>.</p>
+<tt class="docutils literal"><span class="pre">result_of&lt;const UnaryFunction(iterator_traits&lt;Iterator&gt;::reference)&gt;::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


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