From 8f41e88f85adcb4189dcbb07e4bd8ef8d7894593 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 25 Jan 2001 04:57:16 +0000 Subject: [PATCH 01/18] fixed bug in assignment operator under VC++, which was the cause of the access violation error in graph/test/graph.cpp. The root of this bug is in compressed pair, which VC++ has a hard time generating a correct operator= for. [SVN r8767] --- include/boost/pending/iterator_adaptors.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 8ceb505..f4a5b12 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -333,6 +333,14 @@ public: policies().initialize(iter()); } +#ifdef BOOST_MSVC + // This is required to prevent a bug in how VC++ generates + // the assignment operator for compressed_pair. + iterator_adaptor& operator= (const iterator_adaptor& x) { + m_iter_p = x.m_iter_p; + return *this; + } +#endif reference operator*() const { return policies().dereference(type(), iter()); } From b6aa32721f482f7fcafdf0170400898aea57bc79 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 30 Jan 2001 16:00:37 +0000 Subject: [PATCH 02/18] Inital checkin [SVN r8813] --- include/boost/half_open_range.hpp | 366 ++++++++++++++++++++++++++++++ 1 file changed, 366 insertions(+) create mode 100644 include/boost/half_open_range.hpp diff --git a/include/boost/half_open_range.hpp b/include/boost/half_open_range.hpp new file mode 100644 index 0000000..d430c6d --- /dev/null +++ b/include/boost/half_open_range.hpp @@ -0,0 +1,366 @@ +// (C) Copyright Jeremy Siek and David Abrahams 2000-2001. Permission to copy, +// use, modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided "as is" +// without express or implied warranty, and with no claim as to its suitability +// for any purpose. +// +// Revision History: +// 30 Jan 2001 Initial Checkin (David Abrahams) + +#ifndef BOOST_HALF_OPEN_RANGE_HPP_ +# define BOOST_HALF_OPEN_RANGE_HPP_ + +# include +# include +# include +# include +# include +# include + +namespace boost { + +namespace detail { + +// Template class choose_finish -- allows us to maintain the invariant that +// start() <= finish() on half_open_range specializations that support random +// access. +template +struct choose_finish +{ + template + struct rebind + { + static T choose(const T&, const T& finish) + { return finish; } + }; +}; + +template <> +struct choose_finish +{ + template + struct rebind + { + static T choose(const T& start, const T& finish) + { return finish < start ? start : finish; } + }; +}; +} + +template +struct half_open_range +{ + typedef iterator_adaptor, + counting_iterator_traits > iterator; + + private: // utility type definitions + typedef std::less less_value; + typedef typename boost::detail::iterator_traits::iterator_category category; + + public: + typedef iterator const_iterator; + typedef typename counting_iterator_traits::value_type value_type; + typedef typename counting_iterator_traits::difference_type difference_type; + typedef typename counting_iterator_traits::reference reference; + typedef typename counting_iterator_traits::reference const_reference; + typedef typename counting_iterator_traits::pointer pointer; + typedef typename counting_iterator_traits::pointer const_pointer; + + // It would be nice to select an unsigned type, but this is appropriate + // since the library makes an attempt to select a difference_type which can + // hold the difference between any two iterators. + typedef typename counting_iterator_traits::difference_type size_type; + + half_open_range(Incrementable start, Incrementable finish) + : m_start(start), + m_finish( + detail::choose_finish::template rebind::choose(start, finish)) + {} + + // Implicit conversion from std::pair allows us + // to accept the results of std::equal_range(), for example. + half_open_range(const std::pair& x) + : m_start(x.first), + m_finish( + detail::choose_finish::template rebind::choose(x.first,x.second)) + {} + + half_open_range& operator=(const std::pair& x) + { + m_start = x.first; + m_finish = + detail::choose_finish::template rebind::choose(x.first,x.second); + } + + iterator begin() const { return iterator(m_start); } + iterator end() const { return iterator(m_finish); } + + Incrementable front() const { assert(!this->empty()); return m_start; } + Incrementable back() const { assert(!this->empty()); return boost::prior(m_finish); } + + Incrementable start() const { return m_start; } + Incrementable finish() const { return m_finish; } + + size_type size() const { return boost::detail::distance(begin(), end()); } + + bool empty() const + { + return m_finish == m_start; + } + + void swap(half_open_range& x) { + std::swap(m_start, x.m_start); + std::swap(m_finish, x.m_finish); + } + + public: // functions requiring random access elements + + // REQUIRES: x is reachable from this->front() + bool contains(const value_type& x) const + { + BOOST_STATIC_ASSERT((boost::is_same::value)); + return !less_value()(x, m_start) && less_value()(x, m_finish); + } + + bool contains(const half_open_range& x) const + { + BOOST_STATIC_ASSERT((boost::is_same::value)); + return x.empty() || !less_value()(x.m_start, m_start) && !less_value()(m_finish, x.m_finish); + } + + bool intersects(const half_open_range& x) const + { + BOOST_STATIC_ASSERT((boost::is_same::value)); + return less_value()( + less_value()(this->m_start, x.m_start) ? x.m_start : this->m_start, + less_value()(this->m_finish, x.m_finish) ? this->m_finish : x.m_finish); + } + + half_open_range& operator&=(const half_open_range& x) + { + BOOST_STATIC_ASSERT((boost::is_same::value)); + + if (less_value()(this->m_start, x.m_start)) + this->m_start = x.m_start; + + if (less_value()(x.m_finish, this->m_finish)) + this->m_finish = x.m_finish; + + if (less_value()(this->m_finish, this->m_start)) + this->m_start = this->m_finish; + + return *this; + } + + half_open_range& operator|=(const half_open_range& x) + { + BOOST_STATIC_ASSERT((boost::is_same::value)); + + if (!x.empty()) + { + if (this->empty()) + { + *this = x; + } + else + { + if (less_value()(x.m_start, this->m_start)) + this->m_start = x.m_start; + + if (less_value()(this->m_finish, x.m_finish)) + this->m_finish = x.m_finish; + } + } + return *this; + } + + // REQUIRES: x is reachable from this->front() + const_iterator find(const value_type& x) const + { + BOOST_STATIC_ASSERT((boost::is_same::value)); + + return const_iterator(this->contains(x) ? x : m_finish); + } + + // REQUIRES: index >= 0 && index < size() + value_type operator[](size_type index) const + { + assert(index >= 0 && index < size()); + return m_start + index; + } + + value_type at(size_type index) const + { + if (index < 0 || index >= size()) + throw std::out_of_range(std::string("half_open_range")); + return m_start + index; + } + + private: // data members + Incrementable m_start, m_finish; +}; + +template +half_open_range operator|( + half_open_range x, + const half_open_range& y) +{ + return x |= y; +} + +template +half_open_range operator&( + half_open_range x, + const half_open_range& y) +{ + return x &= y; +} + +template +inline bool operator==( + const half_open_range& x, + const half_open_range& y) +{ + const bool y_empty = y.empty(); + return x.empty() ? y_empty : !y_empty && x.start() == y.start() && x.finish() == y.finish(); +} + +template +inline bool operator!=( + const half_open_range& x, + const half_open_range& y) +{ + return !(x == y); +} + +template +inline half_open_range +make_half_open_range(Incrementable first, Incrementable last) +{ + return half_open_range(first, last); +} + +template +bool intersects( + const half_open_range& x, + const half_open_range& y) +{ + return x.intersects(y); +} + +template +bool contains( + const half_open_range& x, + const half_open_range& y) +{ + return x.contains(y); +} + +} // namespace boost + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +namespace std { +template struct less > + : binary_function< + boost::half_open_range, + boost::half_open_range,bool> +{ + bool operator()( + const boost::half_open_range& x, + const boost::half_open_range& y) const + { + less cmp; + return !y.empty() && ( + cmp(x.start(), y.start()) + || !cmp(y.start(), x.start()) + && cmp(x.finish(), y.finish())); + } +}; + +template struct less_equal > + : binary_function< + boost::half_open_range, + boost::half_open_range,bool> +{ + bool operator()( + const boost::half_open_range& x, + const boost::half_open_range& y) const + { + typedef boost::half_open_range range; + less cmp; + return !cmp(y,x); + } +}; +template struct greater > + : binary_function< + boost::half_open_range, + boost::half_open_range,bool> +{ + bool operator()( + const boost::half_open_range& x, + const boost::half_open_range& y) const + { + typedef boost::half_open_range range; + less cmp; + return cmp(y,x); + } +}; + +template struct greater_equal > + : binary_function< + boost::half_open_range, + boost::half_open_range,bool> +{ + bool operator()( + const boost::half_open_range& x, + const boost::half_open_range& y) const + { + typedef boost::half_open_range range; + less cmp; + return !cmp(x,y); + } +}; +} // namespace std + +#else + +namespace boost { +// Can't partially specialize std::less et al, so we must provide the operators +template +bool operator<(const half_open_range& x, + const half_open_range& y) +{ + return !y.empty() && ( + x.empty() || std::less()(x.start(), y.start()) + || !std::less()(y.start(), x.start()) + && std::less()(x.finish(), y.finish())); +} + +template +bool operator>(const half_open_range& x, + const half_open_range& y) +{ + return y < x; +} + +template +bool operator<=(const half_open_range& x, + const half_open_range& y) +{ + return !(y < x); +} + +template +bool operator>=(const half_open_range& x, + const half_open_range& y) +{ + return !(x < y); +} +} // namespace boost + +#endif + + +#endif // BOOST_HALF_OPEN_RANGE_HPP_ From bb2ffadade154af496071cd07ecf8466ddba48e3 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Feb 2001 18:25:55 +0000 Subject: [PATCH 03/18] Added lvalue test [SVN r8922] --- include/boost/pending/iterator_tests.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp index 15a5ec4..fcdbb76 100644 --- a/include/boost/pending/iterator_tests.hpp +++ b/include/boost/pending/iterator_tests.hpp @@ -3,7 +3,9 @@ // This is meant to be the beginnings of a comprehensive, generic // test suite for STL concepts such as iterators and containers. - +// +// Revision History: +// 04 Feb 2001 Added lvalue test (David Abrahams) #include #include @@ -87,6 +89,10 @@ template void forward_iterator_test(Iterator i, T v1, T v2) { input_iterator_test(i, v1, v2); + + // Test for lvalue + const T* p = &*i; + (void)p; } // Preconditions: *i == v1, *++i == v2 From 25f9acabac6c2d2ba5041a6b513f6fe93d52c5c9 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Feb 2001 19:00:03 +0000 Subject: [PATCH 04/18] corrected preconditions [SVN r8925] --- include/boost/pending/iterator_tests.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp index fcdbb76..13b83de 100644 --- a/include/boost/pending/iterator_tests.hpp +++ b/include/boost/pending/iterator_tests.hpp @@ -5,7 +5,9 @@ // test suite for STL concepts such as iterators and containers. // // Revision History: -// 04 Feb 2001 Added lvalue test (David Abrahams) +// 04 Feb 2001 Added lvalue test, corrected preconditions +// (David Abrahams) + #include #include @@ -95,7 +97,7 @@ void forward_iterator_test(Iterator i, T v1, T v2) (void)p; } -// Preconditions: *i == v1, *++i == v2 +// Preconditions: *i == v1, *++i == v2, --i template void bidirectional_iterator_test(Iterator i, T v1, T v2) { @@ -122,7 +124,7 @@ void bidirectional_iterator_test(Iterator i, T v1, T v2) // mutable_bidirectional_iterator_test -// Preconditions: [i,i+N) is a valid range +// Preconditions: [i-1,i+N) is a valid range template void random_access_iterator_test(Iterator i, int N, TrueVals vals) { From 93b54c15c868c6e0709e12752ca8a0a45dcd4400 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Feb 2001 19:11:30 +0000 Subject: [PATCH 05/18] Inital checkin [SVN r8927] --- include/boost/iterator_adaptors.hpp | 843 ++++++++++++++++++++++++++++ 1 file changed, 843 insertions(+) create mode 100644 include/boost/iterator_adaptors.hpp diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp new file mode 100644 index 0000000..ba1878d --- /dev/null +++ b/include/boost/iterator_adaptors.hpp @@ -0,0 +1,843 @@ +// (C) Copyright David Abrahams 2000. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +// +// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. + +#ifndef BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ +#define BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ + +#include +#include +#include +#include +#include + +// I was having some problems with VC6. I couldn't tell whether our hack for +// stock GCC was causing problems so I needed an easy way to turn it on and +// off. Now we can test the hack with various compilers and still have an +// "out" if it doesn't work. -dwa 7/31/00 +#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 && !defined(__STL_USE_NAMESPACES) +# define BOOST_RELOPS_AMBIGUITY_BUG 1 +#endif + +namespace boost { + +//============================================================================ +// Concept checking classes that express the requirements for iterator +// policies and adapted types. These classes are mostly for +// documentation purposes, and are not used in this header file. They +// merely provide a more succinct statement of what is expected of the +// iterator policies. + +template +struct TrivialIteratorPoliciesConcept +{ + typedef typename Traits::reference Reference; + void constraints() { + function_requires< AssignableConcept >(); + function_requires< DefaultConstructibleConcept >(); + function_requires< AssignableConcept >(); + function_requires< DefaultConstructibleConcept >(); + + const_constraints(); + } + void const_constraints() const { + Reference r = p.dereference(type(), x); + b = p.equal(x, x); + ignore_unused_variable_warning(r); + } + Policies p; + Adapted x; + mutable bool b; +}; + +// Add InputIteratorPoliciesConcept? + +template +struct ForwardIteratorPoliciesConcept +{ + typedef typename Traits::iterator_category iterator_category; + void constraints() { + function_requires< + TrivialIteratorPoliciesConcept + >(); + + p.increment(x); + std::forward_iterator_tag t = iterator_category(); + ignore_unused_variable_warning(t); + } + Policies p; + Adapted x; + iterator_category category; +}; + +template +struct BidirectionalIteratorPoliciesConcept +{ + typedef typename Traits::iterator_category iterator_category; + void constraints() { + function_requires< + ForwardIteratorPoliciesConcept + >(); + + p.decrement(x); + std::bidirectional_iterator_tag t = iterator_category(); + ignore_unused_variable_warning(t); + } + Policies p; + Adapted x; +}; + +template +struct RandomAccessIteratorPoliciesConcept +{ + typedef typename Traits::difference_type DifferenceType; + typedef typename Traits::iterator_category iterator_category; + void constraints() { + function_requires< + BidirectionalIteratorPoliciesConcept + >(); + + p.advance(x, n); + std::random_access_iterator_tag t = iterator_category(); + const_constraints(); + ignore_unused_variable_warning(t); + } + void const_constraints() const { + n = p.distance(type(), x, x); + b = p.less(x, x); + } + Policies p; + Adapted x; + mutable DifferenceType n; + mutable bool b; +}; + + +//============================================================================ +// Default policies for iterator adaptors. You can use this as a base +// class if you want to customize particular policies. +struct default_iterator_policies +{ + // Some of these members were defined static, but Borland got confused + // and thought they were non-const. Also, Sun C++ does not like static + // function templates. + + template + void initialize(Iterator&) + { } + + template + Reference dereference(type, const Iterator& x) const + { return *x; } + + template + void increment(Iterator& x) + { ++x; } + + template + void decrement(Iterator& x) + { --x; } + + template + void advance(Iterator& x, DifferenceType n) + { x += n; } + + template + Difference distance(type, const Iterator1& x, + const Iterator2& y) const + { return y - x; } + + template + bool equal(const Iterator1& x, const Iterator2& y) const + { return x == y; } + + template + bool less(const Iterator1& x, const Iterator2& y) const + { return x < y; } +}; + +// putting the comparisons in a base class avoids the g++ +// ambiguous overload bug due to the relops operators + +#ifdef BOOST_RELOPS_AMBIGUITY_BUG +template +struct iterator_comparisons : Base { }; + +template +inline bool operator==(const iterator_comparisons& xb, + const iterator_comparisons& yb) +{ + const D1& x = static_cast(xb); + const D2& y = static_cast(yb); + return x.policies().equal(x.iter(), y.iter()); +} + +template +inline bool operator!=(const iterator_comparisons& xb, + const iterator_comparisons& yb) +{ + const D1& x = static_cast(xb); + const D2& y = static_cast(yb); + return !x.policies().equal(x.iter(), y.iter()); +} + +template +inline bool operator<(const iterator_comparisons& xb, + const iterator_comparisons& yb) +{ + const D1& x = static_cast(xb); + const D2& y = static_cast(yb); + return x.policies().less(x.iter(), y.iter()); +} + +template +inline bool operator>(const iterator_comparisons& xb, + const iterator_comparisons& yb) +{ + const D1& x = static_cast(xb); + const D2& y = static_cast(yb); + return x.policies().less(y.iter(), x.iter()); +} + +template +inline bool operator>=(const iterator_comparisons& xb, + const iterator_comparisons& yb) +{ + const D1& x = static_cast(xb); + const D2& y = static_cast(yb); + return !x.policies().less(x.iter(), y.iter()); +} + +template +inline bool operator<=(const iterator_comparisons& xb, + const iterator_comparisons& yb) +{ + const D1& x = static_cast(xb); + const D2& y = static_cast(yb); + return !x.policies().less(y.iter(), x.iter()); +} +#endif + +//============================================================================ +// Some compilers (SGI MIPSpro 7.1.3.3) instantiate/compile member functions +// whether or not they are used. The following functions make sure that +// when the base iterators do not support particular operators, those +// operators do not get used. + +namespace detail { + +#if defined(__sgi) && !defined(__GNUC__) + // Dummy versions for iterators that don't support various operators + template + inline typename Iter::pointer + operator_arrow(const Iter&, std::input_iterator_tag) { + return typename Iter::pointer(); + } + template + inline typename Iter::pointer + operator_arrow(const Iter&, std::output_iterator_tag) { + return typename Iter::pointer(); + } + + template + inline void advance_impl(Iter&, Diff, std::input_iterator_tag) { } + template + inline void advance_impl(Iter&, Diff, std::output_iterator_tag) { } + + template + inline void decrement_impl(Iter&, std::input_iterator_tag) { } + template + inline void decrement_impl(Iter&, std::output_iterator_tag) { } +#endif + + // Real versions + template + inline typename Iter::pointer + operator_arrow(const Iter& i, std::forward_iterator_tag) { + return &(*i); + } + + template + inline void + advance_impl(Iter& i, Diff n, std::random_access_iterator_tag) { + i.policies().advance(i.iter(), n); + } + + template + inline void + decrement_impl(Iter& i, std::bidirectional_iterator_tag) { + i.policies().decrement(i.iter()); + } + +} // namespace detail + +//============================================================================ +// iterator_adaptor - A generalized adaptor around an existing +// iterator, which is itself an iterator +// +// Iterator - the iterator type being wrapped. +// +// Policies - a set of policies determining how the resulting iterator +// works. +// +// Traits - a class satisfying the same requirements as a specialization of +// std::iterator_traits for the resulting iterator. +// +template +#endif + > +struct iterator_adaptor : +#ifdef BOOST_RELOPS_AMBIGUITY_BUG + iterator_comparisons< + iterator_adaptor, +#endif + boost::iterator +#ifdef BOOST_RELOPS_AMBIGUITY_BUG +> +#endif +{ + typedef iterator_adaptor Self; +public: + typedef typename Traits::difference_type difference_type; + typedef typename Traits::value_type value_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + typedef typename Traits::iterator_category iterator_category; + typedef Iterator iterator_type; + + iterator_adaptor() { } + + iterator_adaptor(const Iterator& it, const Policies& p = Policies()) + : m_iter_p(it, p) { + policies().initialize(iter()); + } + + template + iterator_adaptor (const iterator_adaptor& src) + : m_iter_p(src.iter(), src.policies()) { + policies().initialize(iter()); + } + +#ifdef BOOST_MSVC + // This is required to prevent a bug in how VC++ generates + // the assignment operator for compressed_pair. + iterator_adaptor& operator= (const iterator_adaptor& x) { + m_iter_p = x.m_iter_p; + return *this; + } +#endif + reference operator*() const { + return policies().dereference(type(), iter()); + } + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning( disable : 4284 ) +#endif + + pointer operator->() const + { return detail::operator_arrow(*this, iterator_category()); } + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + + value_type operator[](difference_type n) const + { return *(*this + n); } + + Self& operator++() { +#ifdef __MWERKS__ + // Odd bug, MWERKS couldn't deduce the type for the member template + // Workaround by explicitly specifying the type. + policies().increment(iter()); +#else + policies().increment(iter()); +#endif + return *this; + } + + Self operator++(int) { Self tmp(*this); ++*this; return tmp; } + + Self& operator--() { + detail::decrement_impl(*this, iterator_category()); + return *this; + } + + Self operator--(int) { Self tmp(*this); --*this; return tmp; } + + Self& operator+=(difference_type n) { + detail::advance_impl(*this, n, iterator_category()); + return *this; + } + + Self& operator-=(difference_type n) { + detail::advance_impl(*this, -n, iterator_category()); + return *this; + } + + iterator_type base() const { return m_iter_p.first(); } + +private: + typedef Policies policies_type; + compressed_pair m_iter_p; +public: // too many compilers have trouble when these are private. + Policies& policies() { return m_iter_p.second(); } + const Policies& policies() const { return m_iter_p.second(); } + Iterator& iter() { return m_iter_p.first(); } + const Iterator& iter() const { return m_iter_p.first(); } +}; + + +template +iterator_adaptor +operator-(iterator_adaptor p, const typename Traits::difference_type x) +{ + return p -= x; +} + +template +iterator_adaptor +operator+(iterator_adaptor p, typename Traits::difference_type x) +{ + return p += x; +} + +template +iterator_adaptor +operator+(typename Traits::difference_type x, iterator_adaptor p) +{ + return p += x; +} + +template +typename Traits1::difference_type operator-( + const iterator_adaptor& x, + const iterator_adaptor& y ) +{ + typedef typename Traits1::difference_type difference_type; + return x.policies().distance(type(), y.iter(), x.iter()); +} + +#ifndef BOOST_RELOPS_AMBIGUITY_BUG +template +inline bool +operator==(const iterator_adaptor& x, const iterator_adaptor& y) { + return x.policies().equal(x.iter(), y.iter()); +} + +template +inline bool +operator<(const iterator_adaptor& x, const iterator_adaptor& y) { + return x.policies().less(x.iter(), y.iter()); +} + +template +inline bool +operator>(const iterator_adaptor& x, + const iterator_adaptor& y) { + return x.policies().less(y.iter(), x.iter()); +} + +template +inline bool +operator>=(const iterator_adaptor& x, const iterator_adaptor& y) { + return !x.policies().less(x.iter(), y.iter()); +} + +template +inline bool +operator<=(const iterator_adaptor& x, + const iterator_adaptor& y) { + return !x.policies().less(y.iter(), x.iter()); +} + +template +inline bool +operator!=(const iterator_adaptor& x, + const iterator_adaptor& y) { + return !x.policies().equal(x.iter(), y.iter()); +} +#endif + +//============================================================================= +// iterator_adaptors - A type generator that simplifies creating +// mutable/const pairs of iterator adaptors. + +template , + class ConstTraits = std::iterator_traits, +#endif + class Policies = default_iterator_policies> +class iterator_adaptors +{ +public: + typedef iterator_adaptor iterator; + typedef iterator_adaptor + const_iterator; +}; + + +//============================================================================= +// Transform Iterator Adaptor +// +// Upon deference, apply some unary function object and return the +// result by value. + +template +struct transform_iterator_policies : public default_iterator_policies +{ + transform_iterator_policies() { } + transform_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { } + + template + Reference dereference(type, const Iterator& iter) const + { return m_f(*iter); } + + AdaptableUnaryFunction m_f; +}; + +template +struct transform_iterator_traits { + typedef typename AdaptableUnaryFunction::result_type value_type; + typedef value_type reference; + typedef value_type* pointer; + typedef typename IteratorTraits::difference_type difference_type; + typedef typename IteratorTraits::iterator_category iterator_category; +}; + +template +#else + class Traits +#endif + > +struct transform_iterator +{ + typedef transform_iterator_traits + TransTraits; + typedef iterator_adaptor, TransTraits> + type; +}; + + +//============================================================================= +// Indirect Iterators Adaptor + +// Given a pointer to pointers (or iterator to iterators), +// apply a double dereference inside operator*(). +// +// We use the term "outer" to refer to the first level iterator type +// and "inner" to refer to the second level iterator type. For +// example, given T**, T* is the inner iterator type and T** is the +// outer iterator type. Also, const T* would be the const inner +// iterator. + +// We tried to implement this with transform_iterator, but that required +// using boost::remove_ref, which is not compiler portable. + +struct indirect_iterator_policies : public default_iterator_policies +{ + template + Reference dereference(type, const Iterator& x) const + { return **x; } +}; + +template , + class InnerTraits = std::iterator_traits +#endif + > +struct indirect_traits +{ + typedef typename OuterTraits::difference_type difference_type; + typedef typename InnerTraits::value_type value_type; + typedef typename InnerTraits::pointer pointer; + typedef typename InnerTraits::reference reference; + typedef typename OuterTraits::iterator_category iterator_category; +}; + +template mutable indirect iterator + // Immutable -> immutable indirect iterator +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + class OuterTraits, + class InnerTraits +#else + class OuterTraits = std::iterator_traits, + class InnerTraits = std::iterator_traits +#endif + > +struct indirect_iterator +{ + typedef iterator_adaptor + > type; +}; + +template , + class InnerTraits = std::iterator_traits, + class ConstInnerTraits = std::iterator_traits +#endif + > +struct indirect_iterators +{ + typedef iterator_adaptors, + indirect_traits, + indirect_iterator_policies + > Adaptors; + typedef typename Adaptors::iterator iterator; + typedef typename Adaptors::const_iterator const_iterator; +}; + + +//============================================================================= +// Reverse Iterators Adaptor + +struct reverse_iterator_policies : public default_iterator_policies +{ + template + Reference dereference(type, const Iterator& x) const + { return *boost::prior(x); } + + template + void increment(Iterator& x) const + { --x; } + + template + void decrement(Iterator& x) const + { ++x; } + + template + void advance(Iterator& x, DifferenceType n) const + { x -= n; } + + template + Difference distance(type, const Iterator1& x, + const Iterator2& y) const + { return x - y; } + + template + bool equal(const Iterator1& x, const Iterator2& y) const + { return x == y; } + + template + bool less(const Iterator1& x, const Iterator2& y) const + { return y < x; } +}; + +template +#else + class Traits +#endif + > +struct reverse_iterator +{ + typedef iterator_adaptor type; +}; + +template +#else + class ConstTraits +#endif + > +struct const_reverse_iterator +{ + typedef iterator_adaptor type; +}; + +template , + class ConstTraits = std::iterator_traits +#else + class Traits, + class ConstTraits +#endif + > +struct reverse_iterators +{ + typedef iterator_adaptors Adaptor; + typedef typename Adaptor::iterator iterator; + typedef typename Adaptor::const_iterator const_iterator; +}; + +//============================================================================= +// Projection Iterators Adaptor + +template +struct projection_iterator_policies : public default_iterator_policies +{ + projection_iterator_policies() { } + projection_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { } + + template + Reference dereference (type, Iterator const& iter) const { + return m_f(*iter); + } + + AdaptableUnaryFunction m_f; +}; + +template +struct projection_iterator_traits { + typedef typename AdaptableUnaryFunction::result_type value_type; + typedef value_type& reference; + typedef value_type* pointer; + typedef typename Traits::difference_type difference_type; + typedef typename Traits::iterator_category iterator_category; +}; + +template +struct const_projection_iterator_traits { + typedef typename AdaptableUnaryFunction::result_type value_type; + typedef value_type const& reference; + typedef value_type const* pointer; + typedef typename Traits::difference_type difference_type; + typedef typename Traits::iterator_category iterator_category; +}; + +template +#else + class Traits +#endif + > +struct projection_iterator { + typedef projection_iterator_traits + Projection_Traits; + typedef iterator_adaptor, + Projection_Traits> type; +}; + +template +#else + class Traits +#endif + > +struct const_projection_iterator { + typedef const_projection_iterator_traits Projection_Traits; + typedef iterator_adaptor, + Projection_Traits> type; +}; + +template , + class ConstTraits = std::iterator_traits +#else + class Traits, + class ConstTraits +#endif + > +struct projection_iterators { + typedef projection_iterator_traits + Projection_Traits; + typedef const_projection_iterator_traits Const_Projection_Traits; + typedef iterator_adaptors > Adaptors; + typedef typename Adaptors::iterator iterator; + typedef typename Adaptors::const_iterator const_iterator; +}; + +//============================================================================= +// Filter Iterator Adaptor + + template + class filter_iterator_policies : public default_iterator_policies { + public: + filter_iterator_policies() { } + + filter_iterator_policies(const Predicate& p, const Iterator& end) + : m_predicate(p), m_end(end) { } + + void initialize(Iterator& x) { + advance(x); + } + void increment(Iterator& x) { + ++x; + advance(x); + } + private: + void advance(Iterator& iter) + { + while (m_end != iter && !m_predicate(*iter)) + ++iter; + } + Predicate m_predicate; + Iterator m_end; + }; + + template +#else + class Traits +#endif + > + class filter_iterator { + typedef filter_iterator_policies Policies; + public: + typedef iterator_adaptor type; + }; + + +} // namespace boost + +#endif + + + From 90299982a6f2f188e075ab82f139eb62b0dc1d9e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Feb 2001 19:38:28 +0000 Subject: [PATCH 06/18] Added counting_iterator_generator; updated comments [SVN r8928] --- include/boost/counting_iterator.hpp | 31 ++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index 2279c93..bbbe994 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -4,7 +4,7 @@ // without express or implied warranty, and with no claim as to its suitability // for any purpose. // -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org for most recent version including documentation. // // Supplies: // @@ -15,16 +15,21 @@ // value progresses through consecutive values of Incrementable when the // iterator is derferenced. // +// template struct counting_iterator_generator; +// +// A "type generator" whose nested type "type" is a counting iterator as +// described above. +// // template -// iterator_adaptor, -// counting_iterator_traits > -// counting_iterator(Incrementable); +// typename counting_iterator_generator::type +// counting_iterator(Incrementable); // // A function which produces an adapted counting iterator over values of // Incrementable. // // Revision History +// 04 Feb 2001 Added counting_iterator_generator; updated comments +// (David Abrahams) // 24 Jan 2001 initial revision, based on Jeremy Siek's // boost/pending/integer_range.hpp (David Abrahams) @@ -33,7 +38,7 @@ # include # include -# include +# include # include # include # ifndef BOOST_NO_LIMITS @@ -161,11 +166,18 @@ struct counting_iterator_policies : public default_iterator_policies } }; +// A type generator for counting iterators +template +struct counting_iterator_generator +{ + typedef iterator_adaptor, + counting_iterator_traits > type; +}; + // Manufacture a counting iterator for an arbitrary incrementable type template -inline iterator_adaptor, - counting_iterator_traits > +inline typename counting_iterator_generator::type counting_iterator(Incrementable x) { return iterator_adaptor >(x); } + } // namespace boost #endif // BOOST_COUNTING_ITERATOR_HPP_DWA20000119 From 05336f45c416dae73ed35a7b650997e1827f0237 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Feb 2001 20:33:45 +0000 Subject: [PATCH 07/18] Support for user-defined iterator categories [SVN r8930] --- include/boost/half_open_range.hpp | 101 ++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 26 deletions(-) diff --git a/include/boost/half_open_range.hpp b/include/boost/half_open_range.hpp index d430c6d..ac8d057 100644 --- a/include/boost/half_open_range.hpp +++ b/include/boost/half_open_range.hpp @@ -5,6 +5,7 @@ // for any purpose. // // Revision History: +// 04 Feb 2001 Support for user-defined iterator categories (David Abrahams) // 30 Jan 2001 Initial Checkin (David Abrahams) #ifndef BOOST_HALF_OPEN_RANGE_HPP_ @@ -16,35 +17,69 @@ # include # include # include +# include namespace boost { namespace detail { -// Template class choose_finish -- allows us to maintain the invariant that -// start() <= finish() on half_open_range specializations that support random -// access. -template -struct choose_finish -{ - template - struct rebind - { - static T choose(const T&, const T& finish) - { return finish; } - }; -}; + // Template class choose_finish -- allows us to maintain the invariant that + // start() <= finish() on half_open_range specializations that support random + // access. +#ifdef __MWERKS__ + template + const T& choose_finish(const T&, const T& finish, std::input_iterator_tag) + { + return finish; + } -template <> -struct choose_finish -{ - template - struct rebind - { - static T choose(const T& start, const T& finish) - { return finish < start ? start : finish; } - }; -}; + template + const T& choose_finish(const T&, const T& finish, std::output_iterator_tag) + { + return finish; + } + + template + const T& choose_finish(const T& start, const T& finish, std::random_access_iterator_tag) + { + return finish < start ? start : finish; + } +#else + template struct finish_chooser; + + template <> + struct finish_chooser + { + template + struct rebind + { + static T choose(const T&, const T& finish) + { return finish; } + }; + }; + + template <> + struct finish_chooser + { + template + struct rebind + { + static T choose(const T& start, const T& finish) + { return finish < start ? start : finish; } + }; + }; + + template + struct choose_finish + { + static const Incrementable choose(const Incrementable& start, const Incrementable& finish) + { + return finish_chooser<( + boost::is_convertible::value + )>::template rebind::choose(start, finish); + } + }; +#endif } template @@ -75,7 +110,12 @@ struct half_open_range half_open_range(Incrementable start, Incrementable finish) : m_start(start), m_finish( - detail::choose_finish::template rebind::choose(start, finish)) +#ifndef __MWERKS__ + detail::choose_finish::choose(start, finish) +#else + detail::choose_finish(start, finish, category()) +#endif + ) {} // Implicit conversion from std::pair allows us @@ -83,14 +123,23 @@ struct half_open_range half_open_range(const std::pair& x) : m_start(x.first), m_finish( - detail::choose_finish::template rebind::choose(x.first,x.second)) +#ifndef __MWERKS__ + detail::choose_finish::choose(x.first, x.second) +#else + detail::choose_finish(x.first, x.second, category()) +#endif + ) {} half_open_range& operator=(const std::pair& x) { m_start = x.first; m_finish = - detail::choose_finish::template rebind::choose(x.first,x.second); +#ifndef __MWERKS__ + detail::choose_finish::choose(x.first, x.second); +#else + detail::choose_finish(x.first, x.second, category(); +#endif } iterator begin() const { return iterator(m_start); } From 41c334d7185f7d3b8ffcad721e9347b3671290bf Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Feb 2001 20:35:23 +0000 Subject: [PATCH 08/18] MWERKS bug workaround [SVN r8931] --- include/boost/iterator_adaptors.hpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index ba1878d..f5351fe 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -9,6 +9,9 @@ // copyright notice appears in all copies. This software is provided // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. +// +// Revision History: +// 04 Feb 2001 MWERKS bug workaround #ifndef BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ #define BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ @@ -807,7 +810,11 @@ struct projection_iterators { void initialize(Iterator& x) { advance(x); } - void increment(Iterator& x) { + + // dwa 2/4/01 - The Iter template argument neccessary for compatibility with + // a MWCW bug workaround + template + void increment(Iter& x) { ++x; advance(x); } From 893b5c0e2592d0791c5fbb31cd1d544b0743a352 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Feb 2001 23:34:29 +0000 Subject: [PATCH 09/18] Moved contents to boost/iterator_adaptors.hpp [SVN r8933] --- include/boost/pending/iterator_adaptors.hpp | 844 +------------------- 1 file changed, 1 insertion(+), 843 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index f4a5b12..548b9ba 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -1,843 +1 @@ -// (C) Copyright David Abrahams 2000. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -// -// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -#ifndef BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ -#define BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ - -#include -#include -#include -#include -#include - -// I was having some problems with VC6. I couldn't tell whether our hack for -// stock GCC was causing problems so I needed an easy way to turn it on and -// off. Now we can test the hack with various compilers and still have an -// "out" if it doesn't work. -dwa 7/31/00 -#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 && !defined(__STL_USE_NAMESPACES) -# define BOOST_RELOPS_AMBIGUITY_BUG 1 -#endif - -namespace boost { - -//============================================================================ -// Concept checking classes that express the requirements for iterator -// policies and adapted types. These classes are mostly for -// documentation purposes, and are not used in this header file. They -// merely provide a more succinct statement of what is expected of the -// iterator policies. - -template -struct TrivialIteratorPoliciesConcept -{ - typedef typename Traits::reference Reference; - void constraints() { - function_requires< AssignableConcept >(); - function_requires< DefaultConstructibleConcept >(); - function_requires< AssignableConcept >(); - function_requires< DefaultConstructibleConcept >(); - - const_constraints(); - } - void const_constraints() const { - Reference r = p.dereference(type(), x); - b = p.equal(x, x); - ignore_unused_variable_warning(r); - } - Policies p; - Adapted x; - mutable bool b; -}; - -// Add InputIteratorPoliciesConcept? - -template -struct ForwardIteratorPoliciesConcept -{ - typedef typename Traits::iterator_category iterator_category; - void constraints() { - function_requires< - TrivialIteratorPoliciesConcept - >(); - - p.increment(x); - std::forward_iterator_tag t = iterator_category(); - ignore_unused_variable_warning(t); - } - Policies p; - Adapted x; - iterator_category category; -}; - -template -struct BidirectionalIteratorPoliciesConcept -{ - typedef typename Traits::iterator_category iterator_category; - void constraints() { - function_requires< - ForwardIteratorPoliciesConcept - >(); - - p.decrement(x); - std::bidirectional_iterator_tag t = iterator_category(); - ignore_unused_variable_warning(t); - } - Policies p; - Adapted x; -}; - -template -struct RandomAccessIteratorPoliciesConcept -{ - typedef typename Traits::difference_type DifferenceType; - typedef typename Traits::iterator_category iterator_category; - void constraints() { - function_requires< - BidirectionalIteratorPoliciesConcept - >(); - - p.advance(x, n); - std::random_access_iterator_tag t = iterator_category(); - const_constraints(); - ignore_unused_variable_warning(t); - } - void const_constraints() const { - n = p.distance(type(), x, x); - b = p.less(x, x); - } - Policies p; - Adapted x; - mutable DifferenceType n; - mutable bool b; -}; - - -//============================================================================ -// Default policies for iterator adaptors. You can use this as a base -// class if you want to customize particular policies. -struct default_iterator_policies -{ - // Some of these members were defined static, but Borland got confused - // and thought they were non-const. Also, Sun C++ does not like static - // function templates. - - template - void initialize(Iterator&) - { } - - template - Reference dereference(type, const Iterator& x) const - { return *x; } - - template - void increment(Iterator& x) - { ++x; } - - template - void decrement(Iterator& x) - { --x; } - - template - void advance(Iterator& x, DifferenceType n) - { x += n; } - - template - Difference distance(type, const Iterator1& x, - const Iterator2& y) const - { return y - x; } - - template - bool equal(const Iterator1& x, const Iterator2& y) const - { return x == y; } - - template - bool less(const Iterator1& x, const Iterator2& y) const - { return x < y; } -}; - -// putting the comparisons in a base class avoids the g++ -// ambiguous overload bug due to the relops operators - -#ifdef BOOST_RELOPS_AMBIGUITY_BUG -template -struct iterator_comparisons : Base { }; - -template -inline bool operator==(const iterator_comparisons& xb, - const iterator_comparisons& yb) -{ - const D1& x = static_cast(xb); - const D2& y = static_cast(yb); - return x.policies().equal(x.iter(), y.iter()); -} - -template -inline bool operator!=(const iterator_comparisons& xb, - const iterator_comparisons& yb) -{ - const D1& x = static_cast(xb); - const D2& y = static_cast(yb); - return !x.policies().equal(x.iter(), y.iter()); -} - -template -inline bool operator<(const iterator_comparisons& xb, - const iterator_comparisons& yb) -{ - const D1& x = static_cast(xb); - const D2& y = static_cast(yb); - return x.policies().less(x.iter(), y.iter()); -} - -template -inline bool operator>(const iterator_comparisons& xb, - const iterator_comparisons& yb) -{ - const D1& x = static_cast(xb); - const D2& y = static_cast(yb); - return x.policies().less(y.iter(), x.iter()); -} - -template -inline bool operator>=(const iterator_comparisons& xb, - const iterator_comparisons& yb) -{ - const D1& x = static_cast(xb); - const D2& y = static_cast(yb); - return !x.policies().less(x.iter(), y.iter()); -} - -template -inline bool operator<=(const iterator_comparisons& xb, - const iterator_comparisons& yb) -{ - const D1& x = static_cast(xb); - const D2& y = static_cast(yb); - return !x.policies().less(y.iter(), x.iter()); -} -#endif - -//============================================================================ -// Some compilers (SGI MIPSpro 7.1.3.3) instantiate/compile member functions -// whether or not they are used. The following functions make sure that -// when the base iterators do not support particular operators, those -// operators do not get used. - -namespace detail { - -#if defined(__sgi) && !defined(__GNUC__) - // Dummy versions for iterators that don't support various operators - template - inline typename Iter::pointer - operator_arrow(const Iter&, std::input_iterator_tag) { - return typename Iter::pointer(); - } - template - inline typename Iter::pointer - operator_arrow(const Iter&, std::output_iterator_tag) { - return typename Iter::pointer(); - } - - template - inline void advance_impl(Iter&, Diff, std::input_iterator_tag) { } - template - inline void advance_impl(Iter&, Diff, std::output_iterator_tag) { } - - template - inline void decrement_impl(Iter&, std::input_iterator_tag) { } - template - inline void decrement_impl(Iter&, std::output_iterator_tag) { } -#endif - - // Real versions - template - inline typename Iter::pointer - operator_arrow(const Iter& i, std::forward_iterator_tag) { - return &(*i); - } - - template - inline void - advance_impl(Iter& i, Diff n, std::random_access_iterator_tag) { - i.policies().advance(i.iter(), n); - } - - template - inline void - decrement_impl(Iter& i, std::bidirectional_iterator_tag) { - i.policies().decrement(i.iter()); - } - -} // namespace detail - -//============================================================================ -// iterator_adaptor - A generalized adaptor around an existing -// iterator, which is itself an iterator -// -// Iterator - the iterator type being wrapped. -// -// Policies - a set of policies determining how the resulting iterator -// works. -// -// Traits - a class satisfying the same requirements as a specialization of -// std::iterator_traits for the resulting iterator. -// -template -#endif - > -struct iterator_adaptor : -#ifdef BOOST_RELOPS_AMBIGUITY_BUG - iterator_comparisons< - iterator_adaptor, -#endif - boost::iterator -#ifdef BOOST_RELOPS_AMBIGUITY_BUG -> -#endif -{ - typedef iterator_adaptor Self; -public: - typedef typename Traits::difference_type difference_type; - typedef typename Traits::value_type value_type; - typedef typename Traits::pointer pointer; - typedef typename Traits::reference reference; - typedef typename Traits::iterator_category iterator_category; - typedef Iterator iterator_type; - - iterator_adaptor() { } - - iterator_adaptor(const Iterator& it, const Policies& p = Policies()) - : m_iter_p(it, p) { - policies().initialize(iter()); - } - - template - iterator_adaptor (const iterator_adaptor& src) - : m_iter_p(src.iter(), src.policies()) { - policies().initialize(iter()); - } - -#ifdef BOOST_MSVC - // This is required to prevent a bug in how VC++ generates - // the assignment operator for compressed_pair. - iterator_adaptor& operator= (const iterator_adaptor& x) { - m_iter_p = x.m_iter_p; - return *this; - } -#endif - reference operator*() const { - return policies().dereference(type(), iter()); - } - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning( disable : 4284 ) -#endif - - pointer operator->() const - { return detail::operator_arrow(*this, iterator_category()); } - -#ifdef _MSC_VER -# pragma warning(pop) -#endif - - reference operator[](difference_type n) const - { return *(*this + n); } - - Self& operator++() { -#ifdef __MWERKS__ - // Odd bug, MWERKS couldn't deduce the type for the member template - // Workaround by explicitly specifying the type. - policies().increment(iter()); -#else - policies().increment(iter()); -#endif - return *this; - } - - Self operator++(int) { Self tmp(*this); ++*this; return tmp; } - - Self& operator--() { - detail::decrement_impl(*this, iterator_category()); - return *this; - } - - Self operator--(int) { Self tmp(*this); --*this; return tmp; } - - Self& operator+=(difference_type n) { - detail::advance_impl(*this, n, iterator_category()); - return *this; - } - - Self& operator-=(difference_type n) { - detail::advance_impl(*this, -n, iterator_category()); - return *this; - } - - iterator_type base() const { return m_iter_p.first(); } - -private: - typedef Policies policies_type; - compressed_pair m_iter_p; -public: // too many compilers have trouble when these are private. - Policies& policies() { return m_iter_p.second(); } - const Policies& policies() const { return m_iter_p.second(); } - Iterator& iter() { return m_iter_p.first(); } - const Iterator& iter() const { return m_iter_p.first(); } -}; - - -template -iterator_adaptor -operator-(iterator_adaptor p, const typename Traits::difference_type x) -{ - return p -= x; -} - -template -iterator_adaptor -operator+(iterator_adaptor p, typename Traits::difference_type x) -{ - return p += x; -} - -template -iterator_adaptor -operator+(typename Traits::difference_type x, iterator_adaptor p) -{ - return p += x; -} - -template -typename Traits1::difference_type operator-( - const iterator_adaptor& x, - const iterator_adaptor& y ) -{ - typedef typename Traits1::difference_type difference_type; - return x.policies().distance(type(), y.iter(), x.iter()); -} - -#ifndef BOOST_RELOPS_AMBIGUITY_BUG -template -inline bool -operator==(const iterator_adaptor& x, const iterator_adaptor& y) { - return x.policies().equal(x.iter(), y.iter()); -} - -template -inline bool -operator<(const iterator_adaptor& x, const iterator_adaptor& y) { - return x.policies().less(x.iter(), y.iter()); -} - -template -inline bool -operator>(const iterator_adaptor& x, - const iterator_adaptor& y) { - return x.policies().less(y.iter(), x.iter()); -} - -template -inline bool -operator>=(const iterator_adaptor& x, const iterator_adaptor& y) { - return !x.policies().less(x.iter(), y.iter()); -} - -template -inline bool -operator<=(const iterator_adaptor& x, - const iterator_adaptor& y) { - return !x.policies().less(y.iter(), x.iter()); -} - -template -inline bool -operator!=(const iterator_adaptor& x, - const iterator_adaptor& y) { - return !x.policies().equal(x.iter(), y.iter()); -} -#endif - -//============================================================================= -// iterator_adaptors - A type generator that simplifies creating -// mutable/const pairs of iterator adaptors. - -template , - class ConstTraits = std::iterator_traits, -#endif - class Policies = default_iterator_policies> -class iterator_adaptors -{ -public: - typedef iterator_adaptor iterator; - typedef iterator_adaptor - const_iterator; -}; - - -//============================================================================= -// Transform Iterator Adaptor -// -// Upon deference, apply some unary function object and return the -// result by value. - -template -struct transform_iterator_policies : public default_iterator_policies -{ - transform_iterator_policies() { } - transform_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { } - - template - Reference dereference(type, const Iterator& iter) const - { return m_f(*iter); } - - AdaptableUnaryFunction m_f; -}; - -template -struct transform_iterator_traits { - typedef typename AdaptableUnaryFunction::result_type value_type; - typedef value_type reference; - typedef value_type* pointer; - typedef typename IteratorTraits::difference_type difference_type; - typedef typename IteratorTraits::iterator_category iterator_category; -}; - -template -#else - class Traits -#endif - > -struct transform_iterator -{ - typedef transform_iterator_traits - TransTraits; - typedef iterator_adaptor, TransTraits> - type; -}; - - -//============================================================================= -// Indirect Iterators Adaptor - -// Given a pointer to pointers (or iterator to iterators), -// apply a double dereference inside operator*(). -// -// We use the term "outer" to refer to the first level iterator type -// and "inner" to refer to the second level iterator type. For -// example, given T**, T* is the inner iterator type and T** is the -// outer iterator type. Also, const T* would be the const inner -// iterator. - -// We tried to implement this with transform_iterator, but that required -// using boost::remove_ref, which is not compiler portable. - -struct indirect_iterator_policies : public default_iterator_policies -{ - template - Reference dereference(type, const Iterator& x) const - { return **x; } -}; - -template , - class InnerTraits = std::iterator_traits -#endif - > -struct indirect_traits -{ - typedef typename OuterTraits::difference_type difference_type; - typedef typename InnerTraits::value_type value_type; - typedef typename InnerTraits::pointer pointer; - typedef typename InnerTraits::reference reference; - typedef typename OuterTraits::iterator_category iterator_category; -}; - -template mutable indirect iterator - // Immutable -> immutable indirect iterator -#ifdef BOOST_NO_STD_ITERATOR_TRAITS - class OuterTraits, - class InnerTraits -#else - class OuterTraits = std::iterator_traits, - class InnerTraits = std::iterator_traits -#endif - > -struct indirect_iterator -{ - typedef iterator_adaptor - > type; -}; - -template , - class InnerTraits = std::iterator_traits, - class ConstInnerTraits = std::iterator_traits -#endif - > -struct indirect_iterators -{ - typedef iterator_adaptors, - indirect_traits, - indirect_iterator_policies - > Adaptors; - typedef typename Adaptors::iterator iterator; - typedef typename Adaptors::const_iterator const_iterator; -}; - - -//============================================================================= -// Reverse Iterators Adaptor - -struct reverse_iterator_policies : public default_iterator_policies -{ - template - Reference dereference(type, const Iterator& x) const - { return *boost::prior(x); } - - template - void increment(Iterator& x) const - { --x; } - - template - void decrement(Iterator& x) const - { ++x; } - - template - void advance(Iterator& x, DifferenceType n) const - { x -= n; } - - template - Difference distance(type, const Iterator1& x, - const Iterator2& y) const - { return x - y; } - - template - bool equal(const Iterator1& x, const Iterator2& y) const - { return x == y; } - - template - bool less(const Iterator1& x, const Iterator2& y) const - { return y < x; } -}; - -template -#else - class Traits -#endif - > -struct reverse_iterator -{ - typedef iterator_adaptor type; -}; - -template -#else - class ConstTraits -#endif - > -struct const_reverse_iterator -{ - typedef iterator_adaptor type; -}; - -template , - class ConstTraits = std::iterator_traits -#else - class Traits, - class ConstTraits -#endif - > -struct reverse_iterators -{ - typedef iterator_adaptors Adaptor; - typedef typename Adaptor::iterator iterator; - typedef typename Adaptor::const_iterator const_iterator; -}; - -//============================================================================= -// Projection Iterators Adaptor - -template -struct projection_iterator_policies : public default_iterator_policies -{ - projection_iterator_policies() { } - projection_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { } - - template - Reference dereference (type, Iterator const& iter) const { - return m_f(*iter); - } - - AdaptableUnaryFunction m_f; -}; - -template -struct projection_iterator_traits { - typedef typename AdaptableUnaryFunction::result_type value_type; - typedef value_type& reference; - typedef value_type* pointer; - typedef typename Traits::difference_type difference_type; - typedef typename Traits::iterator_category iterator_category; -}; - -template -struct const_projection_iterator_traits { - typedef typename AdaptableUnaryFunction::result_type value_type; - typedef value_type const& reference; - typedef value_type const* pointer; - typedef typename Traits::difference_type difference_type; - typedef typename Traits::iterator_category iterator_category; -}; - -template -#else - class Traits -#endif - > -struct projection_iterator { - typedef projection_iterator_traits - Projection_Traits; - typedef iterator_adaptor, - Projection_Traits> type; -}; - -template -#else - class Traits -#endif - > -struct const_projection_iterator { - typedef const_projection_iterator_traits Projection_Traits; - typedef iterator_adaptor, - Projection_Traits> type; -}; - -template , - class ConstTraits = std::iterator_traits -#else - class Traits, - class ConstTraits -#endif - > -struct projection_iterators { - typedef projection_iterator_traits - Projection_Traits; - typedef const_projection_iterator_traits Const_Projection_Traits; - typedef iterator_adaptors > Adaptors; - typedef typename Adaptors::iterator iterator; - typedef typename Adaptors::const_iterator const_iterator; -}; - -//============================================================================= -// Filter Iterator Adaptor - - template - class filter_iterator_policies : public default_iterator_policies { - public: - filter_iterator_policies() { } - - filter_iterator_policies(const Predicate& p, const Iterator& end) - : m_predicate(p), m_end(end) { } - - void initialize(Iterator& x) { - advance(x); - } - void increment(Iterator& x) { - ++x; - advance(x); - } - private: - void advance(Iterator& iter) - { - while (m_end != iter && !m_predicate(*iter)) - ++iter; - } - Predicate m_predicate; - Iterator m_end; - }; - - template -#else - class Traits -#endif - > - class filter_iterator { - typedef filter_iterator_policies Policies; - public: - typedef iterator_adaptor type; - }; - - -} // namespace boost - -#endif - - - +#include From 3e6796ab9120f8fe98ad4200135e7de57203d021 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Feb 2001 23:35:26 +0000 Subject: [PATCH 10/18] Fixed lvalue test [SVN r8934] --- include/boost/pending/iterator_tests.hpp | 44 +++++++++++++++++++----- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp index 13b83de..2694da5 100644 --- a/include/boost/pending/iterator_tests.hpp +++ b/include/boost/pending/iterator_tests.hpp @@ -1,5 +1,5 @@ #ifndef BOOST_ITERATOR_TESTS_HPP -#define BOOST_ITERATOR_TESTS_HPP +# define BOOST_ITERATOR_TESTS_HPP // This is meant to be the beginnings of a comprehensive, generic // test suite for STL concepts such as iterators and containers. @@ -8,8 +8,10 @@ // 04 Feb 2001 Added lvalue test, corrected preconditions // (David Abrahams) -#include -#include +# include +# include +# include +# include namespace boost { @@ -87,21 +89,47 @@ void input_iterator_test(Iterator i, T v1, T v2) // how to test output iterator? + +template struct lvalue_test +{ + template static void check(Iterator) + { +# ifndef BOOST_NO_STD_ITERATOR_TRAITS + typedef typename std::iterator_traits::reference reference; + typedef typename std::iterator_traits::value_type value_type; +# else + typedef typename Iterator::reference reference; + typedef typename Iterator::value_type value_type; +# endif + BOOST_STATIC_ASSERT(boost::is_reference::value); + BOOST_STATIC_ASSERT((boost::is_same::value + || boost::is_same::value + )); + } +}; + +# ifdef BOOST_NO_STD_ITERATOR_TRAITS +template <> struct lvalue_test { + template static void check(T) {} +}; +#endif + template void forward_iterator_test(Iterator i, T v1, T v2) { input_iterator_test(i, v1, v2); - - // Test for lvalue - const T* p = &*i; - (void)p; + + // borland doesn't allow non-type template parameters +# if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551) + lvalue_test<(boost::is_pointer::value)>::check(i); +#endif } // Preconditions: *i == v1, *++i == v2, --i template void bidirectional_iterator_test(Iterator i, T v1, T v2) { - input_iterator_test(i, v1, v2); + forward_iterator_test(i, v1, v2); ++i; Iterator i1 = i, i2 = i; From 7aea7b7881d6e1cd91be9ea27fbe94fbb0cac0ed Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Feb 2001 23:37:01 +0000 Subject: [PATCH 11/18] Factored counting_iterator stuff into boost/counting_iterator.hpp [SVN r8935] --- include/boost/pending/integer_range.hpp | 60 +++++-------------------- 1 file changed, 10 insertions(+), 50 deletions(-) diff --git a/include/boost/pending/integer_range.hpp b/include/boost/pending/integer_range.hpp index 24a62f2..e1b8720 100644 --- a/include/boost/pending/integer_range.hpp +++ b/include/boost/pending/integer_range.hpp @@ -1,63 +1,27 @@ -// (C) Copyright David Abrahams 2000. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. +// (C) Copyright David Abrahams and Jeremy Siek 2000-2001. Permission to copy, +// use, modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided "as is" +// without express or implied warranty, and with no claim as to its suitability +// for any purpose. // -// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. +// Revision History: +// 04 Jan 2001 Factored counting_iterator stuff into +// boost/counting_iterator.hpp (David Abrahams) #ifndef BOOST_INTEGER_RANGE_HPP_ #define BOOST_INTEGER_RANGE_HPP_ #include - -#if 1 -// Still evaluating whether VC++ can handle this. -#define BOOST_USE_ITERATOR_ADAPTORS -#endif - -#ifdef BOOST_USE_ITERATOR_ADAPTORS -#include -#else -#include -#endif +#include namespace boost { //============================================================================= // Counting Iterator and Integer Range Class -#ifdef BOOST_USE_ITERATOR_ADAPTORS -template -struct counting_iterator_policies : public default_iterator_policies -{ - IntegerType - dereference(type, const IntegerType& i) const - { return i; } -}; -template -struct counting_iterator_traits { - typedef IntegerType value_type; - typedef IntegerType reference; - typedef value_type* pointer; - typedef std::ptrdiff_t difference_type; - typedef std::random_access_iterator_tag iterator_category; -}; -#endif - template struct integer_range { -#ifdef BOOST_USE_ITERATOR_ADAPTORS - typedef iterator_adaptor, - counting_iterator_traits > iterator; -#else - typedef int_iterator iterator; -#endif + typedef typename counting_iterator_generator::type iterator; typedef iterator const_iterator; typedef IntegerType value_type; @@ -92,8 +56,4 @@ make_integer_range(IntegerType first, IntegerType last) } // namespace boost -#ifdef BOOST_USE_ITERATOR_ADAPTORS -#undef BOOST_USE_ITERATOR_ADAPTORS -#endif - #endif // BOOST_INTEGER_RANGE_HPP_ From 332f18cf9f176b17d79d6f7338a7a94279c1d562 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 4 Feb 2001 23:45:57 +0000 Subject: [PATCH 12/18] changed category for transform iterator traits to input iterator [SVN r8936] --- include/boost/iterator_adaptors.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index f5351fe..8ba4354 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -524,7 +524,7 @@ struct transform_iterator_traits { typedef value_type reference; typedef value_type* pointer; typedef typename IteratorTraits::difference_type difference_type; - typedef typename IteratorTraits::iterator_category iterator_category; + typedef std::input_iterator_tag iterator_category; }; template Date: Mon, 5 Feb 2001 05:38:44 +0000 Subject: [PATCH 13/18] start of iterator concept tests [SVN r8938] --- development/libs/iterator/concept_tests.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 development/libs/iterator/concept_tests.cpp diff --git a/development/libs/iterator/concept_tests.cpp b/development/libs/iterator/concept_tests.cpp new file mode 100644 index 0000000..9ef2ed9 --- /dev/null +++ b/development/libs/iterator/concept_tests.cpp @@ -0,0 +1,13 @@ +#include + +int +main() +{ + boost::function_requires< + boost_concepts::MutableLvalueRandomAccessIteratorConcept >(); + + boost::function_requires< + boost_concepts::ConstantLvalueRandomAccessIteratorConcept >(); + + return 0; +} From 5e1bc30db9a36c4855ec30a0c45802f21c9e8ba6 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 5 Feb 2001 05:39:43 +0000 Subject: [PATCH 14/18] 1st draft [SVN r8939] --- development/boost/iterator_concepts.hpp | 282 ++++++++++++++++++++++++ development/boost/iterator_traits.hpp | 60 +++++ 2 files changed, 342 insertions(+) create mode 100644 development/boost/iterator_concepts.hpp create mode 100644 development/boost/iterator_traits.hpp diff --git a/development/boost/iterator_concepts.hpp b/development/boost/iterator_concepts.hpp new file mode 100644 index 0000000..acea6e3 --- /dev/null +++ b/development/boost/iterator_concepts.hpp @@ -0,0 +1,282 @@ +#ifndef BOOST_ITERATOR_CONCEPTS_HPP +#define BOOST_ITERATOR_CONCEPTS_HPP + +#include +#include + +namespace boost_concepts { + // Used a different namespace here (instead of "boost") so that the + // concept descriptions do not take for granted the names in + // namespace boost. + + + //=========================================================================== + + template + class ReadableIteratorConcept { + public: + typedef typename boost::iterator_traits::value_type value_type; + typedef typename boost::iterator_traits::reference reference; + typedef typename boost::iterator_traits::return_category + return_category; + + void constraints() { + boost::function_requires< boost::SGIAssignableConcept >(); + boost::function_requires< boost::EqualityComparableConcept >(); + boost::function_requires< boost::DefaultConstructibleConcept >(); + + boost::function_requires< + boost::ConvertibleConcept >(); + + reference r = *i; // or perhaps read(x) + value_type v(r); + boost::ignore_unused_variable_warning(v); + } + Iterator i; + }; + + template + class WritableIteratorConcept { + public: + typedef typename boost::iterator_traits::return_category + return_category; + + void constraints() { + boost::function_requires< boost::SGIAssignableConcept >(); + boost::function_requires< boost::EqualityComparableConcept >(); + boost::function_requires< boost::DefaultConstructibleConcept >(); + + boost::function_requires< + boost::ConvertibleConcept >(); + + *i = v; // an alternative could be something like write(x, v) + } + ValueType v; + Iterator i; + }; + + template + class ConstantLvalueIteratorConcept { + public: + typedef typename boost::iterator_traits::value_type value_type; + typedef typename boost::iterator_traits::reference reference; + typedef typename boost::iterator_traits::return_category + return_category; + + void constraints() { + boost::function_requires< ReadableIteratorConcept >(); + + boost::function_requires< + boost::ConvertibleConcept >(); + + typedef typename boost::require_same::type req; + + reference v = *i; + boost::ignore_unused_variable_warning(v); + } + Iterator i; + }; + + template + class MutableLvalueIteratorConcept { + public: + typedef typename boost::iterator_traits::value_type value_type; + typedef typename boost::iterator_traits::reference reference; + typedef typename boost::iterator_traits::return_category + return_category; + + void constraints() { + boost::function_requires< ReadableIteratorConcept >(); + boost::function_requires< WritableIteratorConcept >(); + + boost::function_requires< + boost::ConvertibleConcept >(); + + typedef typename boost::require_same::type req; + + reference v = *i; + boost::ignore_unused_variable_warning(v); + } + Iterator i; + }; + + //=========================================================================== + + template + class SinglePassIteratorConcept { + public: + typedef typename boost::iterator_traits::motion_category + motion_category; + typedef typename boost::iterator_traits::difference_type + difference_type; + + void constraints() { + boost::function_requires< boost::SGIAssignableConcept >(); + boost::function_requires< boost::EqualityComparableConcept >(); + boost::function_requires< boost::DefaultConstructibleConcept >(); + + boost::function_requires< + boost::ConvertibleConcept >(); + + // difference_type must be a signed integral type + + ++i; + (void)i++; + } + + Iterator i; + }; + + template + class ForwardIteratorConcept { + public: + typedef typename boost::iterator_traits::motion_category + motion_category; + + void constraints() { + boost::function_requires< SinglePassIteratorConcept >(); + + boost::function_requires< + boost::ConvertibleConcept >(); + } + }; + + template + class BidirectionalIteratorConcept { + public: + typedef typename boost::iterator_traits::motion_category + motion_category; + + void constraints() { + boost::function_requires< ForwardIteratorConcept >(); + + boost::function_requires< + boost::ConvertibleConcept >(); + + --i; + (void)i--; + } + Iterator i; + }; + + template + class RandomAccessIteratorConcept { + public: + typedef typename boost::iterator_traits::motion_category + motion_category; + typedef typename boost::iterator_traits::difference_type + difference_type; + + void constraints() { + boost::function_requires< BidirectionalIteratorConcept >(); + + boost::function_requires< + boost::ConvertibleConcept >(); + + i += n; + i = i + n; + i = n + i; + i -= n; + i = i - n; + n = i - j; + } + difference_type n; + Iterator i, j; + }; + + //=========================================================================== + + template + class ReadableRandomAccessIteratorConcept { + public: + typedef typename boost::iterator_traits::value_type value_type; + typedef typename boost::iterator_traits::reference reference; + typedef typename boost::iterator_traits::difference_type + difference_type; + + void constraints() { + boost::function_requires< RandomAccessIteratorConcept >(); + boost::function_requires< ReadableIteratorConcept >(); + + reference r = i[n]; + value_type v(r); + boost::ignore_unused_variable_warning(v); + } + difference_type n; + Iterator i; + }; + + template + class WritableRandomAccessIteratorConcept { + public: + typedef typename boost::iterator_traits::value_type value_type; + typedef typename boost::iterator_traits::difference_type + difference_type; + + void constraints() { + boost::function_requires< RandomAccessIteratorConcept >(); + boost::function_requires< WritableIteratorConcept >(); + + i[n] = v; + boost::ignore_unused_variable_warning(v); + } + difference_type n; + value_type v; + Iterator i; + }; + + template + class ConstantLvalueRandomAccessIteratorConcept { + public: + typedef typename boost::iterator_traits::value_type value_type; + typedef typename boost::iterator_traits::reference reference; + typedef typename boost::iterator_traits::difference_type + difference_type; + + void constraints() { + boost::function_requires< RandomAccessIteratorConcept >(); + boost::function_requires< ReadableIteratorConcept >(); + + typedef typename boost::require_same::type req; + + reference v = i[n]; + boost::ignore_unused_variable_warning(v); + } + difference_type n; + value_type v; + Iterator i; + }; + + template + class MutableLvalueRandomAccessIteratorConcept { + public: + typedef typename boost::iterator_traits::value_type value_type; + typedef typename boost::iterator_traits::reference reference; + typedef typename boost::iterator_traits::difference_type + difference_type; + + void constraints() { + boost::function_requires< RandomAccessIteratorConcept >(); + boost::function_requires< WritableIteratorConcept >(); + boost::function_requires< ReadableIteratorConcept >(); + + typedef typename boost::require_same::type req; + + reference v = i[n]; + boost::ignore_unused_variable_warning(v); + } + difference_type n; + value_type v; + Iterator i; + }; + +} // namespace boost_concepts + + +#endif // BOOST_ITERATOR_CONCEPTS_HPP diff --git a/development/boost/iterator_traits.hpp b/development/boost/iterator_traits.hpp new file mode 100644 index 0000000..585f194 --- /dev/null +++ b/development/boost/iterator_traits.hpp @@ -0,0 +1,60 @@ +#ifndef BOOST_ITERATOR_TRAITS_HPP +#define BOOST_ITERATOR_TRAITS_HPP + +#include +#include + +namespace boost { + + template + struct iterator_traits { + typedef typename Iterator::value_type value_type; + typedef typename Iterator::reference reference; + typedef typename Iterator::pointer pointer; + typedef typename Iterator::difference_type difference_type; + typedef typename Iterator::return_category return_category; + typedef typename Iterator::motion_category motion_category; + }; + + // Motion Categories + struct single_pass_iterator_tag { }; + struct forward_iterator_tag : public single_pass_iterator_tag { }; + struct bidirectional_iterator_tag : public forward_iterator_tag { }; + struct random_access_iterator_tag : public bidirectional_iterator_tag { }; + + // Return Type Categories + struct readable_iterator_tag { }; + struct writable_iterator_tag { }; + struct mutable_lvalue_iterator_tag : virtual public writable_iterator_tag, + virtual public readable_iterator_tag { }; + struct constant_lvalue_iterator_tag : public readable_iterator_tag { }; + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + namespace detail { + template + struct pointer_return_category { + typedef constant_lvalue_iterator_tag type; + }; + template <> + struct pointer_return_category { + typedef mutable_lvalue_iterator_tag type; + }; + } // namespace detail + + template + struct iterator_traits { + typedef T value_type; + typedef T& reference; + typedef T* pointer; + typedef std::ptrdiff_t difference_type; + typedef typename detail::pointer_return_category::value>::type + return_category; + typedef random_access_iterator_tag motion_category; + }; + +#endif + +} // namespace boost + +#endif // BOOST_ITERATOR_TRAITS_HPP From d17e8dae9bb80ecd912bb9ccd952e36fa8bae2ad Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 6 Feb 2001 23:59:02 +0000 Subject: [PATCH 15/18] codewarrior bug workaround [SVN r8989] --- include/boost/pending/iterator_tests.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp index 2694da5..9bde614 100644 --- a/include/boost/pending/iterator_tests.hpp +++ b/include/boost/pending/iterator_tests.hpp @@ -103,7 +103,7 @@ template struct lvalue_test # endif BOOST_STATIC_ASSERT(boost::is_reference::value); BOOST_STATIC_ASSERT((boost::is_same::value - || boost::is_same::value + || boost::is_same::value )); } }; From 07482538edd7b62e98d30dba2fa9c135cd4a0799 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Feb 2001 05:15:42 +0000 Subject: [PATCH 16/18] Produce operator-> proxy objects for InputIterators Added static assertions to do some basic concept checks Renamed single-type generators -> xxx_generator Renamed const/nonconst iterator generators -> xxx_pair_generator Added make_transform_iterator(iter, function) The existence of boost::detail::iterator_traits allowed many template arguments to be defaulted. Some arguments had to be moved to accomplish it. [SVN r8994] --- include/boost/iterator_adaptors.hpp | 219 +++++++++++++++++----------- 1 file changed, 137 insertions(+), 82 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 8ba4354..479e90c 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -11,24 +11,44 @@ // to its suitability for any purpose. // // Revision History: -// 04 Feb 2001 MWERKS bug workaround + +// 06 Feb 2001 +// Produce operator-> proxy objects for InputIterators +// +// Added static assertions to do some basic concept checks +// +// Renamed single-type generators -> xxx_generator +// Renamed const/nonconst iterator generators -> xxx_pair_generator +// +// Added make_transform_iterator(iter, function) +// +// The existence of boost::detail::iterator_traits allowed many +// template arguments to be defaulted. Some arguments had to be +// moved to accomplish it. +// +// 04 Feb 2001 MWERKS bug workaround, concept checking for proper +// reference types (David Abrahams) #ifndef BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ -#define BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ +# define BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ -#include -#include -#include -#include -#include +# include +# include +# include +# include +# include +# include +# include +# include +# include // I was having some problems with VC6. I couldn't tell whether our hack for // stock GCC was causing problems so I needed an easy way to turn it on and // off. Now we can test the hack with various compilers and still have an // "out" if it doesn't work. -dwa 7/31/00 -#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 && !defined(__STL_USE_NAMESPACES) -# define BOOST_RELOPS_AMBIGUITY_BUG 1 -#endif +# if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 && !defined(__STL_USE_NAMESPACES) +# define BOOST_RELOPS_AMBIGUITY_BUG 1 +# endif namespace boost { @@ -241,11 +261,6 @@ namespace detail { // Dummy versions for iterators that don't support various operators template inline typename Iter::pointer - operator_arrow(const Iter&, std::input_iterator_tag) { - return typename Iter::pointer(); - } - template - inline typename Iter::pointer operator_arrow(const Iter&, std::output_iterator_tag) { return typename Iter::pointer(); } @@ -262,12 +277,49 @@ namespace detail { #endif // Real versions + + // 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 (constant) lvalue to which a pointer can be formed. We do that by + // returning an instantiation of this special proxy class template. + + template + struct operator_arrow_proxy + { + operator_arrow_proxy(const T& x) : m_value(x) {} + const T* operator->() const { return &m_value; } + T m_value; + }; + + template + inline operator_arrow_proxy + operator_arrow(const Iter& i, std::input_iterator_tag) { + return operator_arrow_proxy(*i); + } + template inline typename Iter::pointer operator_arrow(const Iter& i, std::forward_iterator_tag) { return &(*i); } + template + struct operator_arrow_result_generator + { + typedef typename Traits::iterator_category category; + typedef operator_arrow_proxy proxy; + typedef typename Traits::pointer pointer; + typedef typename boost::detail::if_true<( + boost::is_convertible::value + & !boost::is_convertible::value + )>::template + then< + proxy, + // else + pointer + >::type type; + }; + template inline void advance_impl(Iter& i, Diff n, std::random_access_iterator_tag) { @@ -322,6 +374,15 @@ public: typedef typename Traits::iterator_category iterator_category; typedef Iterator iterator_type; + // Iterators should satisfy one of the known categories + BOOST_STATIC_ASSERT((boost::is_convertible::value + || boost::is_convertible::value)); + + // Iterators >= ForwardIterator must produce real references. + BOOST_STATIC_ASSERT((!boost::is_convertible::value + || boost::is_same::value + || boost::is_same::value)); + iterator_adaptor() { } iterator_adaptor(const Iterator& it, const Policies& p = Policies()) @@ -353,7 +414,8 @@ public: # pragma warning( disable : 4284 ) #endif - pointer operator->() const + typename boost::detail::operator_arrow_result_generator::type + operator->() const { return detail::operator_arrow(*this, iterator_category()); } #ifdef _MSC_VER @@ -478,7 +540,7 @@ operator!=(const iterator_adaptor& x, #endif //============================================================================= -// iterator_adaptors - A type generator that simplifies creating +// iterator_adaptor_pair_generator - A type generator that simplifies creating // mutable/const pairs of iterator adaptors. template , #endif class Policies = default_iterator_policies> -class iterator_adaptors +class iterator_adaptor_pair_generator { public: typedef iterator_adaptor iterator; @@ -529,21 +591,26 @@ struct transform_iterator_traits { template -#else - class Traits -#endif + class Traits = boost::detail::iterator_traits > -struct transform_iterator +struct transform_iterator_generator { typedef transform_iterator_traits - TransTraits; + transform_traits; typedef iterator_adaptor, TransTraits> + transform_iterator_policies, transform_traits> type; }; +template +typename transform_iterator_generator::type +make_transform_iterator( + const Iterator& base, + const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) +{ + typedef typename transform_iterator_generator::type result_t; + return result_t(base, f); +} //============================================================================= // Indirect Iterators Adaptor @@ -567,14 +634,15 @@ struct indirect_iterator_policies : public default_iterator_policies { return **x; } }; -template , - class InnerTraits = std::iterator_traits + class InnerIterator = typename std::iterator_traits::value_type, + class InnerTraits = std::iterator_traits, #endif + class OuterTraits = boost::detail::iterator_traits > struct indirect_traits { @@ -586,49 +654,49 @@ struct indirect_traits }; template mutable indirect iterator // Immutable -> immutable indirect iterator -#ifdef BOOST_NO_STD_ITERATOR_TRAITS - class OuterTraits, - class InnerTraits + class InnerTraits, #else - class OuterTraits = std::iterator_traits, - class InnerTraits = std::iterator_traits + class InnerIterator = typename std::iterator_traits::value_type, + class InnerTraits = std::iterator_traits, #endif + class OuterTraits = boost::detail::iterator_traits > -struct indirect_iterator +struct indirect_iterator_generator { typedef iterator_adaptor + InnerTraits, OuterTraits> > type; }; template , + class ConstInnerTraits = std::iterator_traits, + class InnerIterator = typename std::iterator_traits::value_type, class InnerTraits = std::iterator_traits, - class ConstInnerTraits = std::iterator_traits #endif + class OuterTraits = boost::detail::iterator_traits > -struct indirect_iterators +struct indirect_iterator_pair_generator { - typedef iterator_adaptors, + InnerTraits, OuterTraits>, indirect_traits, + ConstInnerTraits, OuterTraits>, indirect_iterator_policies - > Adaptors; - typedef typename Adaptors::iterator iterator; - typedef typename Adaptors::const_iterator const_iterator; + > pair_generator; + typedef typename pair_generator::iterator iterator; + typedef typename pair_generator::const_iterator const_iterator; }; @@ -674,7 +742,7 @@ template -struct reverse_iterator +struct reverse_iterator_generator { typedef iterator_adaptor type; @@ -687,7 +755,7 @@ template -struct const_reverse_iterator +struct const_reverse_iterator_generator { typedef iterator_adaptor type; @@ -702,12 +770,12 @@ template -struct reverse_iterators +struct reverse_iterator_pair_generator { - typedef iterator_adaptors Adaptor; - typedef typename Adaptor::iterator iterator; - typedef typename Adaptor::const_iterator const_iterator; + typedef iterator_adaptor_pair_generator pair_generator; + typedef typename pair_generator::iterator iterator; + typedef typename pair_generator::const_iterator const_iterator; }; //============================================================================= @@ -746,13 +814,9 @@ struct const_projection_iterator_traits { }; template -#else - class Traits -#endif + class Traits = boost::detail::iterator_traits > -struct projection_iterator { +struct projection_iterator_generator { typedef projection_iterator_traits Projection_Traits; typedef iterator_adaptor -#else - class Traits -#endif + class Traits = boost::detail::iterator_traits > -struct const_projection_iterator { +struct const_projection_iterator_generator { typedef const_projection_iterator_traits Projection_Traits; typedef iterator_adaptor, - class ConstTraits = std::iterator_traits -#else - class Traits, - class ConstTraits -#endif + class Traits = boost::detail::iterator_traits, + class ConstTraits = boost::detail::iterator_traits > -struct projection_iterators { +struct projection_iterator_pair_generator { typedef projection_iterator_traits Projection_Traits; typedef const_projection_iterator_traits Const_Projection_Traits; - typedef iterator_adaptors > Adaptors; - typedef typename Adaptors::iterator iterator; - typedef typename Adaptors::const_iterator const_iterator; + projection_iterator_policies > pair_generator; + typedef typename pair_generator::iterator iterator; + typedef typename pair_generator::const_iterator const_iterator; }; //============================================================================= @@ -835,7 +890,7 @@ struct projection_iterators { class Traits #endif > - class filter_iterator { + class filter_iterator_generator { typedef filter_iterator_policies Policies; public: typedef iterator_adaptor type; From 6eeeb23332f1aa9328003a50dcb3bf35c7146cd8 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Feb 2001 17:22:16 +0000 Subject: [PATCH 17/18] Removed iterator_adaptor_pair_generator and reverse_iterator_pair_generator (more such culling to come) Improved comments Changed all uses of std::iterator_traits as default arguments to boost::detail::iterator_traits for improved utility in non-generic contexts Fixed naming convention of non-template parameter names [SVN r9003] --- include/boost/iterator_adaptors.hpp | 154 +++++++++------------------- 1 file changed, 46 insertions(+), 108 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 479e90c..47d4001 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,18 @@ // // Revision History: +// 07 Feb 2001 +// Removed iterator_adaptor_pair_generator and +// reverse_iterator_pair_generator (more such culling to come) +// +// Improved comments +// +// Changed all uses of std::iterator_traits as default arguments +// to boost::detail::iterator_traits for improved utility in +// non-generic contexts +// +// Fixed naming convention of non-template parameter names +// // 06 Feb 2001 // Produce operator-> proxy objects for InputIterators // @@ -335,8 +347,8 @@ namespace detail { } // namespace detail //============================================================================ -// iterator_adaptor - A generalized adaptor around an existing -// iterator, which is itself an iterator +//iterator_adaptor - Adapts a generic piece of data as an iterator. Adaptation +// is especially easy if the data being adapted is itself an iterator // // Iterator - the iterator type being wrapped. // @@ -347,11 +359,7 @@ namespace detail { // std::iterator_traits for the resulting iterator. // template -#endif + class Traits = boost::detail::iterator_traits > struct iterator_adaptor : #ifdef BOOST_RELOPS_AMBIGUITY_BUG @@ -539,28 +547,6 @@ operator!=(const iterator_adaptor& x, } #endif -//============================================================================= -// iterator_adaptor_pair_generator - A type generator that simplifies creating -// mutable/const pairs of iterator adaptors. - -template , - class ConstTraits = std::iterator_traits, -#endif - class Policies = default_iterator_policies> -class iterator_adaptor_pair_generator -{ -public: - typedef iterator_adaptor iterator; - typedef iterator_adaptor - const_iterator; -}; - - //============================================================================= // Transform Iterator Adaptor // @@ -635,14 +621,9 @@ struct indirect_iterator_policies : public default_iterator_policies }; template ::value_type, - class InnerTraits = std::iterator_traits, -#endif - class OuterTraits = boost::detail::iterator_traits + class InnerIterator = typename boost::detail::iterator_traits::value_type, + class InnerTraits = boost::detail::iterator_traits, + class OuterTraits = boost::detail::iterator_traits // never needed (?) > struct indirect_traits { @@ -654,15 +635,10 @@ struct indirect_traits }; template mutable indirect iterator - // Immutable -> immutable indirect iterator - class InnerTraits, -#else - class InnerIterator = typename std::iterator_traits::value_type, - class InnerTraits = std::iterator_traits, -#endif - class OuterTraits = boost::detail::iterator_traits + // Mutable -> mutable indirect iterator; Immutable -> immutable indirect iterator + class InnerIterator = typename boost::detail::iterator_traits::value_type, + class InnerTraits = boost::detail::iterator_traits, + class OuterTraits = boost::detail::iterator_traits // never needed (?) > struct indirect_iterator_generator { @@ -675,28 +651,20 @@ struct indirect_iterator_generator template , - class InnerIterator = typename std::iterator_traits::value_type, - class InnerTraits = std::iterator_traits, -#endif - class OuterTraits = boost::detail::iterator_traits + class ConstInnerTraits = boost::detail::iterator_traits, + class InnerIterator = typename boost::detail::iterator_traits::value_type, + class InnerTraits = boost::detail::iterator_traits, + class OuterTraits = boost::detail::iterator_traits // never needed (?) > struct indirect_iterator_pair_generator { - typedef iterator_adaptor_pair_generator, - indirect_traits, - indirect_iterator_policies - > pair_generator; - typedef typename pair_generator::iterator iterator; - typedef typename pair_generator::const_iterator const_iterator; + typedef iterator_adaptor, + indirect_iterator_policies> iterator; + + typedef iterator_adaptor, + indirect_iterator_policies> const_iterator; }; @@ -736,11 +704,7 @@ struct reverse_iterator_policies : public default_iterator_policies }; template -#else - class Traits -#endif + class Traits = boost::detail::iterator_traits > struct reverse_iterator_generator { @@ -749,11 +713,7 @@ struct reverse_iterator_generator }; template -#else - class ConstTraits -#endif + class ConstTraits = boost::detail::iterator_traits > struct const_reverse_iterator_generator { @@ -761,23 +721,6 @@ struct const_reverse_iterator_generator ConstTraits> type; }; -template , - class ConstTraits = std::iterator_traits -#else - class Traits, - class ConstTraits -#endif - > -struct reverse_iterator_pair_generator -{ - typedef iterator_adaptor_pair_generator pair_generator; - typedef typename pair_generator::iterator iterator; - typedef typename pair_generator::const_iterator const_iterator; -}; - //============================================================================= // Projection Iterators Adaptor @@ -818,10 +761,10 @@ template struct projection_iterator_generator { typedef projection_iterator_traits - Projection_Traits; + projection_traits; typedef iterator_adaptor, - Projection_Traits> type; + projection_traits> type; }; template struct const_projection_iterator_generator { typedef const_projection_iterator_traits Projection_Traits; + Traits> projection_traits; typedef iterator_adaptor, - Projection_Traits> type; + projection_traits> type; }; template struct projection_iterator_pair_generator { typedef projection_iterator_traits - Projection_Traits; + projection_traits; typedef const_projection_iterator_traits Const_Projection_Traits; - typedef iterator_adaptor_pair_generator > pair_generator; - typedef typename pair_generator::iterator iterator; - typedef typename pair_generator::const_iterator const_iterator; + ConstTraits> const_projection_traits; + typedef iterator_adaptor, + projection_traits> iterator; + typedef iterator_adaptor, + const_projection_traits > const_iterator; }; //============================================================================= @@ -884,11 +826,7 @@ struct projection_iterator_pair_generator { }; template -#else - class Traits -#endif + class Traits = boost::detail::iterator_traits > class filter_iterator_generator { typedef filter_iterator_policies Policies; From 762e6030136ddb4fe74765abda634046fb8e8f9d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Feb 2001 22:27:02 +0000 Subject: [PATCH 18/18] rename counting_iterator() -> make_counting_iterator() [SVN r9015] --- include/boost/counting_iterator.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index bbbe994..1580756 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -22,12 +22,14 @@ // // template // typename counting_iterator_generator::type -// counting_iterator(Incrementable); +// make_counting_iterator(Incrementable); // // A function which produces an adapted counting iterator over values of // Incrementable. // // Revision History +// 07 Feb 2001 rename counting_iterator() -> make_counting_iterator() +// (David Abrahams) // 04 Feb 2001 Added counting_iterator_generator; updated comments // (David Abrahams) // 24 Jan 2001 initial revision, based on Jeremy Siek's @@ -178,7 +180,7 @@ struct counting_iterator_generator // Manufacture a counting iterator for an arbitrary incrementable type template inline typename counting_iterator_generator::type -counting_iterator(Incrementable x) +make_counting_iterator(Incrementable x) { return iterator_adaptor,