|
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