Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r77723 - in trunk: boost/iterator libs/iterator/test
From: jewillco_at_[hidden]
Date: 2012-04-02 14:19:45


Author: jewillco
Date: 2012-04-02 14:19:44 EDT (Mon, 02 Apr 2012)
New Revision: 77723
URL: http://svn.boost.org/trac/boost/changeset/77723

Log:
Applied patches from #5697; refs #5697
Text files modified:
   trunk/boost/iterator/iterator_facade.hpp | 72 ++++++++++++++++------------------
   trunk/libs/iterator/test/iterator_facade.cpp | 82 +++++++++++++++++++++++++++++++++------
   2 files changed, 102 insertions(+), 52 deletions(-)

Modified: trunk/boost/iterator/iterator_facade.hpp
==============================================================================
--- trunk/boost/iterator/iterator_facade.hpp (original)
+++ trunk/boost/iterator/iterator_facade.hpp 2012-04-02 14:19:44 EDT (Mon, 02 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: trunk/libs/iterator/test/iterator_facade.cpp
==============================================================================
--- trunk/libs/iterator/test/iterator_facade.cpp (original)
+++ trunk/libs/iterator/test/iterator_facade.cpp 2012-04-02 14:19:44 EDT (Mon, 02 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();
 }


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