diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 94ec84a..757f0ef 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -100,7 +100,7 @@ In short, there are many useful iterators that do not fit into the current standard iterator categories. As a result, the following bad things happen: -- Iterators are often miss-categorized. +- Iterators are often mis-categorized. - Algorithm requirements are more strict than necessary, because they cannot separate the need for random access or bidirectional @@ -402,8 +402,8 @@ Iterator Traversal Concepts [lib.iterator.traversal] In the tables below, ``X`` is an iterator type, ``a`` and ``b`` are constant objects of type ``X``, ``r`` and ``s`` are mutable objects of -type ``X``, ``T`` is ``std::iterator_traits::value_type``, -``v`` is a constant object of type ``T``, and ``u`` is an identifier. +type ``X``, ``T`` is ``std::iterator_traits::value_type``, and +``v`` is a constant object of type ``T``. Incrementable Iterators [lib.incrementable.iterators] diff --git a/include/boost/iterator/iterator_archetypes.hpp b/include/boost/iterator/iterator_archetypes.hpp index 05950c1..d5649cf 100644 --- a/include/boost/iterator/iterator_archetypes.hpp +++ b/include/boost/iterator/iterator_archetypes.hpp @@ -116,7 +116,13 @@ namespace boost template bool operator==(traversal_archetype_ const&, traversal_archetype_ const&); - + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + // doesn't seem to pick up != from equality_comparable + template + bool operator!=(traversal_archetype_ const&, + traversal_archetype_ const&); +#endif template <> struct traversal_archetype_impl { @@ -274,39 +280,56 @@ namespace boost }; }; - template - struct traversal_archetype - : detail::operator_brackets< typename remove_cv::type, - AccessCategory, - TraversalCategory >, - detail::traversal_archetype_ + + template + struct iterator_archetype; + + template + struct traversal_archetype_base + : detail::operator_brackets< + typename remove_cv::type + , AccessCategory + , TraversalCategory + > + , detail::traversal_archetype_< + iterator_archetype + , Value + , TraversalCategory + > { }; template struct iterator_archetype - : public traversal_archetype< - iterator_archetype - , Value, AccessCategory, TraversalCategory - > + : public traversal_archetype_base , public access_archetype -# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) + + // These broken libraries require derivation from std::iterator + // (or related magic) in order to handle iter_swap and other + // iterator operations +# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ + || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) , public std::iterator< iterator_tag , typename access_archetype::value_type - , typename traversal_archetype< - iterator_archetype - , Value, AccessCategory, TraversalCategory + , typename traversal_archetype_base< + Value, AccessCategory, TraversalCategory >::difference_type > # endif { -# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) + // Derivation from std::iterator above caused ambiguity, so now + // we have to declare all the types here. +# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ + || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) typedef typename access_archetype::value_type value_type; - typedef typename traversal_archetype< - iterator_archetype - , Value, AccessCategory, TraversalCategory + typedef typename access_archetype::pointer pointer; + + typedef typename access_archetype::reference reference; + + typedef typename traversal_archetype_base< + Value, AccessCategory, TraversalCategory >::difference_type difference_type; # endif diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index 55b600d..a901d40 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -110,33 +110,36 @@ namespace boost template struct operator_arrow_proxy { - operator_arrow_proxy(const T& x) : m_value(x) {} - const 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 const T*() const { return &m_value; } - T m_value; + operator_arrow_proxy(T const* px) : m_value(*px) {} + const 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 const T*() const { return &m_value; } + T m_value; }; - template - struct operator_arrow_pointer - { - operator_arrow_pointer(Reference x) : m_p(&x) {} - operator Pointer() const { return m_p; } - Pointer m_p; - }; - + // A metafunction that gets the result type for operator->. Also + // has a static function make() which builds the result from a + // Reference template struct operator_arrow_result - : mpl::if_< + { + // 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_tag< readable_lvalue_iterator_tag , typename access_category_tag::type > , Pointer , operator_arrow_proxy - > - { + >::type type; + + static type make(Reference x) + { + return type(&x); + } }; # if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) @@ -370,7 +373,6 @@ namespace boost return iterator_core_access::dereference(this->derived()); } - // Needs eventual help for input iterators typename detail::operator_arrow_result< value_type , iterator_category @@ -379,14 +381,12 @@ namespace boost >::type operator->() const { - typedef typename detail::operator_arrow_result< + return detail::operator_arrow_result< value_type , iterator_category , reference - , detail::operator_arrow_pointer - >::type result_t; - - return result_t(*this->derived()); + , pointer + >::make(*this->derived()); } typename detail::operator_brackets_result::type diff --git a/test/iterator_adaptor_test.cpp b/test/iterator_adaptor_test.cpp index 6399052..a06d340 100644 --- a/test/iterator_adaptor_test.cpp +++ b/test/iterator_adaptor_test.cpp @@ -188,6 +188,7 @@ main() BOOST_STATIC_ASSERT((boost::is_convertible::value)); #endif } + { // Test computation of default when the Value is const typedef ptr_iterator Iter1; diff --git a/test/iterator_archetype_cc.cpp b/test/iterator_archetype_cc.cpp index 0279600..1edf5e5 100644 --- a/test/iterator_archetype_cc.cpp +++ b/test/iterator_archetype_cc.cpp @@ -20,6 +20,6 @@ int main() boost::function_requires< boost_concepts::WritableLvalueIteratorConcept >(); boost::function_requires< boost_concepts::RandomAccessTraversalConcept >(); } - + return 0; // keep msvc happy }