From a8d93ccb414337a7f4dca8364fef2eb605454d27 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 7 Jul 2000 16:04:40 +0000 Subject: [PATCH 001/265] This commit was generated by cvs2svn to compensate for changes in r4, which included commits to RCS files with non-trunk default branches. [SVN r7621] --- .gitattributes | 96 ++++++++++++++++++++++++++++++++++++++ include/boost/iterator.hpp | 58 +++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 .gitattributes create mode 100644 include/boost/iterator.hpp diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3e84d7c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain diff --git a/include/boost/iterator.hpp b/include/boost/iterator.hpp new file mode 100644 index 0000000..82d555b --- /dev/null +++ b/include/boost/iterator.hpp @@ -0,0 +1,58 @@ +// integer.hpp workarounds for non-conforming standard libraries -----------// + +// (C) Copyright Boost.org 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. + +// See http://www.boost.org for most recent version including documentation. + +// Revision History +// 28 Jun 00 Workarounds to deal with known MSVC bugs (David Abrahams) +// 26 Jun 00 Initial version (Jeremy Siek) + +#ifndef BOOST_ITERATOR_HPP +#define BOOST_ITERATOR_HPP + +#include +#include + +namespace boost +{ +# ifdef BOOST_NO_STD_ITERATOR + template + struct iterator + { + typedef T value_type; + typedef Distance difference_type; + typedef Pointer pointer; + typedef Reference reference; + typedef Category iterator_category; + }; +# else + + // declare iterator_base in namespace detail to work around MSVC bugs which + // prevent derivation from an identically-named class in a different namespace. + namespace detail { + template +# if !defined(BOOST_MSVC_STD_ITERATOR) + struct iterator_base : std::iterator {}; +# else + struct iterator_base : std::iterator + { + typedef Reference reference; + typedef Pointer pointer; + typedef Distance difference_type; + }; +# endif + } + + template + struct iterator : detail::iterator_base {}; +# endif +} // namespace boost + +#endif // BOOST_ITERATOR_HPP From bbeeb170412de1bfb896762b19751057f304e219 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 18 Sep 2000 08:24:47 +0000 Subject: [PATCH 002/265] pending stuff from Boost Graph Library [SVN r7704] --- include/boost/pending/iterator_adaptors.hpp | 569 ++++++++++++++++++++ include/boost/pending/iterator_tests.hpp | 171 ++++++ 2 files changed, 740 insertions(+) create mode 100644 include/boost/pending/iterator_adaptors.hpp create mode 100644 include/boost/pending/iterator_tests.hpp diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp new file mode 100644 index 0000000..aec7b87 --- /dev/null +++ b/include/boost/pending/iterator_adaptors.hpp @@ -0,0 +1,569 @@ +// (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 + +#ifdef BOOST_MSVC +#include +#endif + +// 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 { + +#ifndef BOOST_MSVC + +// Just a "type envelope"; works around some MSVC deficiencies. +template +struct type {}; + +//============================================================================= +// Default policies for iterator adaptors. You can use this as a base +// class if you want to customize particular policies. +struct default_iterator_policies +{ + template + static Reference dereference(type, const Iterator& x) + { return *x; } + + template + static void increment(Iterator& x) + { ++x; } + + template + static void decrement(Iterator& x) + { --x; } + + template + static void advance(Iterator& x, DifferenceType n) + { x += n; } + + template + static Difference distance(type, const Iterator1& x, const Iterator2& y) + { return y - x; } + + template + static bool equal(const Iterator1& x, const Iterator2& y) + { return x == y; } + + template + static bool less(const Iterator1& x, const Iterator2& y) + { 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 + +//============================================================================= +// 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. +// +// NonconstIterator - the corresponding non-const iterator type for +// Iterator, if any. You don't need to supply this if you are not make a +// const/non-const iterator pair. +// +template , +#endif + class NonconstIterator = Iterator + > +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; + + iterator_adaptor() { } + + iterator_adaptor(const Iterator& iter, const Policies& p = Policies()) + : m_iter_p(iter, p) {} + +#ifdef BOOST_MSVC6_MEMBER_TEMPLATES + template + iterator_adaptor(const iterator_adaptor& rhs) + : m_iter_p(rhs.iter(), rhs.policies()) {} + + template + Self& operator=(const iterator_adaptor& rhs) + { + iter() = rhs.iter(); + policies() = rhs.policies(); + return *this; + } +#else + template + iterator_adaptor(const iterator_adaptor& rhs) + : m_iter_p(rhs.iter(), rhs.policies()) {} + + template + Self& operator=(const iterator_adaptor& rhs) + { + iter() = rhs.iter(); + policies() = rhs.policies(); + 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 &*this; } + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + + reference operator[](difference_type n) + { return *(*this + n); } + + Self& operator++() { + policies().increment(iter()); + return *this; + } + + Self operator++(int) { Self tmp(*this); ++*this; return tmp; } + + Self& operator--() { + policies().decrement(iter()); + return *this; + } + + Self operator--(int) { Self tmp(*this); --*this; return tmp; } + + Self& operator+=(difference_type n) { + policies().advance(iter(), n); + return *this; + } + + Self& operator-=(difference_type n) { + policies().advance(iter(), -n); + return *this; + } + +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, const typename Traits::difference_type x) +{ + return p += x; +} + +template +iterator_adaptor +operator+(const 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 + +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& x) const + { return m_f(*x); } + + 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, + Iterator> type; +}; + + +//============================================================================= +// Indirect Iterators Adaptor + +// Tried implementing 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 Traits = + std::iterator_traits +#endif + > +struct indirect_traits +{ + typedef typename IndirectTraits::difference_type difference_type; + typedef typename Traits::value_type value_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + typedef typename IndirectTraits::iterator_category iterator_category; +}; + +template , + class ConstIndirectTraits = + std::iterator_traits, + class Traits = + std::iterator_traits +#endif + > +struct indirect_iterators +{ + typedef typename IndirectTraits::value_type Iterator; + typedef typename Traits::value_type ValueType; + 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 +{ + 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 , + 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; +}; + +//============================================================================= +// Counting Iterator and Integer Range Class + +struct counting_iterator_policies : public default_iterator_policies +{ + template + 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 //#ifndef BOOST_MSVC + +template +struct integer_range { +#ifdef BOOST_MSVC + typedef int_iterator iterator; +#else + typedef iterator_adaptor, IntegerType> iterator; +#endif + typedef iterator const_iterator; + typedef IntegerType value_type; + typedef std::ptrdiff_t difference_type; + typedef IntegerType reference; + typedef IntegerType const_reference; + typedef const IntegerType* pointer; + typedef const IntegerType* const_pointer; + typedef IntegerType size_type; + + integer_range(IntegerType start, IntegerType finish) + : m_start(start), m_finish(finish) { } + + iterator begin() const { return iterator(m_start); } + iterator end() const { return iterator(m_finish); } + size_type size() const { return m_finish - m_start; } + bool empty() const { return m_finish == m_start; } + void swap(integer_range& x) { + std::swap(m_start, x.m_start); + std::swap(m_finish, x.m_finish); + } +protected: + IntegerType m_start, m_finish; +}; + + +} // namespace boost + +#endif + diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp new file mode 100644 index 0000000..df74d83 --- /dev/null +++ b/include/boost/pending/iterator_tests.hpp @@ -0,0 +1,171 @@ +#ifndef 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. + +#include + +namespace boost { + + // use this for the value type +struct dummyT { + dummyT() { } + dummyT(int x) : m_x(x) { } + int foo() const { return m_x; } + bool operator==(const dummyT& d) const { return m_x == d.m_x; } + int m_x; +}; + + +// Tests whether type Iterator satisfies the requirements for a +// TrivialIterator. +// Preconditions: i != j, *i == val +template +void trivial_iterator_test(Iterator i, Iterator j, T val) +{ + Iterator k; + assert(i == i); + assert(j == j); + assert(i != j); +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + T v = *i; +#else + typename std::iterator_traits::value_type v = *i; +#endif + assert(v == val); +#if 0 + // hmm, this will give a warning for transform_iterator... perhaps + // this should be separated out into a stand-alone test since there + // are several situations where it can't be used, like for + // integer_range::iterator. + assert(v == i->foo()); +#endif + k = i; + assert(k == k); + assert(k == i); + assert(k != j); + assert(*k == val); +} + + +// Preconditions: i != j +template +void mutable_trivial_iterator_test(Iterator i, Iterator j, T val) +{ + *i = val; + trivial_iterator_test(i, j, val); +} + + +// Preconditions: *i == v1, *++i == v2 +template +void input_iterator_test(Iterator i, T v1, T v2) +{ + Iterator i1 = i, i2 = i; + + assert(i == i1++); + assert(i != ++i2); + + trivial_iterator_test(i, i1, v1); + trivial_iterator_test(i, i2, v1); + + ++i; + assert(i == i1); + assert(i == i2); + ++i1; + ++i2; + + trivial_iterator_test(i, i1, v2); + trivial_iterator_test(i, i2, v2); +} + +// how to test output iterator? + +template +void forward_iterator_test(Iterator i, T v1, T v2) +{ + input_iterator_test(i, v1, v2); +} + +// Preconditions: *i == v1, *++i == v2 +template +void bidirectional_iterator_test(Iterator i, T v1, T v2) +{ + input_iterator_test(i, v1, v2); + ++i; + + Iterator i1 = i, i2 = i; + + assert(i == i1--); + assert(i != --i2); + + trivial_iterator_test(i, i1, v2); + trivial_iterator_test(i, i2, v2); + + --i; + assert(i == i1); + assert(i == i2); + --i1; + --i2; + + trivial_iterator_test(i, i1, v1); + trivial_iterator_test(i, i2, v1); +} + +// mutable_bidirectional_iterator_test + +// Preconditions: [i,i+N) is a valid range +template +void random_access_iterator_test(Iterator i, int N, TrueVals vals) +{ + bidirectional_iterator_test(i, vals[0], vals[1]); + Iterator j = i; + int c; + + for (c = 0; c < N-1; ++c) { + assert(i == j + c); + assert(*i == vals[c]); + assert(*i == j[c]); + assert(*i == *(j + c)); + assert(*i == *(c + j)); + ++i; + assert(i > j); + assert(i >= j); + assert(j <= i); + assert(j < i); + } + + Iterator k = j + N - 1; + for (c = 0; c < N-1; ++c) { + assert(i == k - c); + assert(*i == vals[N - 1 - c]); + assert(*i == j[N - 1 - c]); + assert(*i == *(k - c)); + assert(i > j); + assert(i >= j); + assert(j <= i); + assert(j < i); + --i; + } +} + +// Precondition: i != j +template +void const_nonconst_iterator_test(Iterator i, ConstIterator j) +{ + assert(i != j); + assert(j != i); + + ConstIterator k(i); + assert(k == i); + assert(i == k); + + k = i; + assert(k == i); + assert(i == k); +} + +} // namespace boost + +#endif // BOOST_ITERATOR_TESTS_HPP From 7b17be08a240677b0ed7b6b87008946b1fa5ceeb Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 18 Sep 2000 09:47:04 +0000 Subject: [PATCH 003/265] move integer_range to its own file [SVN r7716] --- include/boost/pending/iterator_adaptors.hpp | 59 --------------------- 1 file changed, 59 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index aec7b87..183857f 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -18,10 +18,6 @@ #include #include -#ifdef BOOST_MSVC -#include -#endif - // 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" @@ -32,8 +28,6 @@ namespace boost { -#ifndef BOOST_MSVC - // Just a "type envelope"; works around some MSVC deficiencies. template struct type {}; @@ -510,59 +504,6 @@ struct reverse_iterators typedef typename Adaptor::const_iterator const_iterator; }; -//============================================================================= -// Counting Iterator and Integer Range Class - -struct counting_iterator_policies : public default_iterator_policies -{ - template - 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 //#ifndef BOOST_MSVC - -template -struct integer_range { -#ifdef BOOST_MSVC - typedef int_iterator iterator; -#else - typedef iterator_adaptor, IntegerType> iterator; -#endif - typedef iterator const_iterator; - typedef IntegerType value_type; - typedef std::ptrdiff_t difference_type; - typedef IntegerType reference; - typedef IntegerType const_reference; - typedef const IntegerType* pointer; - typedef const IntegerType* const_pointer; - typedef IntegerType size_type; - - integer_range(IntegerType start, IntegerType finish) - : m_start(start), m_finish(finish) { } - - iterator begin() const { return iterator(m_start); } - iterator end() const { return iterator(m_finish); } - size_type size() const { return m_finish - m_start; } - bool empty() const { return m_finish == m_start; } - void swap(integer_range& x) { - std::swap(m_start, x.m_start); - std::swap(m_finish, x.m_finish); - } -protected: - IntegerType m_start, m_finish; -}; - - } // namespace boost #endif From 59a54ab5bd9728b3595fc0f613bc4193f57099fa Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 18 Sep 2000 09:49:29 +0000 Subject: [PATCH 004/265] moved integer_range to its own file [SVN r7717] --- include/boost/pending/detail/int_iterator.hpp | 68 +++++++++++++++++ include/boost/pending/integer_range.hpp | 76 +++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 include/boost/pending/detail/int_iterator.hpp create mode 100644 include/boost/pending/integer_range.hpp diff --git a/include/boost/pending/detail/int_iterator.hpp b/include/boost/pending/detail/int_iterator.hpp new file mode 100644 index 0000000..346774c --- /dev/null +++ b/include/boost/pending/detail/int_iterator.hpp @@ -0,0 +1,68 @@ +// (C) Copyright Jeremy Siek 1999. 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_INT_ITERATOR_H +#define BOOST_INT_ITERATOR_H + +#include +#if !defined BOOST_MSVC +#include +#endif +#include +//using namespace std; + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE +namespace boost { +#endif + +// this should use random_access_iterator_helper but I've had +// VC++ portablility problems with that. -JGS +template +class int_iterator +{ + typedef int_iterator self; +public: + typedef std::random_access_iterator_tag iterator_category; + typedef IntT value_type; + typedef IntT& reference; + typedef IntT* pointer; + typedef ptrdiff_t difference_type; + + inline int_iterator() : _i(0) { } + inline int_iterator(IntT i) : _i(i) { } + inline int_iterator(const self& x) : _i(x._i) { } + inline self& operator=(const self& x) { _i = x._i; return *this; } + inline IntT operator*() { return _i; } + inline IntT operator[](IntT n) { return _i + n; } + inline self& operator++() { ++_i; return *this; } + inline self operator++(int) { self t = *this; ++_i; return t; } + inline self& operator+=(IntT n) { _i += n; return *this; } + inline self operator+(IntT n) { self t = *this; t._i += n; return t; } + inline self& operator--() { --_i; return *this; } + inline self operator--(int) { self t = *this; --_i; return t; } + inline self& operator-=(IntT n) { _i -= n; return *this; } + inline IntT operator-(const self& x) const { return _i - x._i; } + inline bool operator==(const self& x) const { return _i == x._i; } + // vc++ had a problem finding != in random_access_iterator_helper + // need to look into this... for now implementing everything here -JGS + inline bool operator!=(const self& x) const { return _i != x._i; } + inline bool operator<(const self& x) const { return _i < x._i; } +protected: + IntT _i; +}; + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE +} /* namespace boost */ +#endif + +#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE +namespace boost { + using ::int_iterator; +} +#endif + + +#endif /* BOOST_INT_ITERATOR_H */ diff --git a/include/boost/pending/integer_range.hpp b/include/boost/pending/integer_range.hpp new file mode 100644 index 0000000..710ebe7 --- /dev/null +++ b/include/boost/pending/integer_range.hpp @@ -0,0 +1,76 @@ +// (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_INTEGER_RANGE_HPP_ +#define BOOST_INTEGER_RANGE_HPP_ + +#ifdef BOOST_MSVC +#include +#else +#include +#endif + +namespace boost { + +//============================================================================= +// Counting Iterator and Integer Range Class + +struct counting_iterator_policies : public default_iterator_policies +{ + template + 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; +}; + +template +struct integer_range { +#ifdef BOOST_MSVC + typedef int_iterator iterator; +#else + typedef iterator_adaptor, IntegerType> iterator; +#endif + typedef iterator const_iterator; + typedef IntegerType value_type; + typedef std::ptrdiff_t difference_type; + typedef IntegerType reference; + typedef IntegerType const_reference; + typedef const IntegerType* pointer; + typedef const IntegerType* const_pointer; + typedef IntegerType size_type; + + integer_range(IntegerType start, IntegerType finish) + : m_start(start), m_finish(finish) { } + + iterator begin() const { return iterator(m_start); } + iterator end() const { return iterator(m_finish); } + size_type size() const { return m_finish - m_start; } + bool empty() const { return m_finish == m_start; } + void swap(integer_range& x) { + std::swap(m_start, x.m_start); + std::swap(m_finish, x.m_finish); + } +protected: + IntegerType m_start, m_finish; +}; + +} // namespace boost + +#endif // BOOST_INTEGER_RANGE_HPP_ From 40b7a3e8aa1114bbdd7d1876ae01438212c952d4 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 18 Sep 2000 09:52:20 +0000 Subject: [PATCH 005/265] typo in #include [SVN r7718] --- include/boost/pending/integer_range.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/pending/integer_range.hpp b/include/boost/pending/integer_range.hpp index 710ebe7..37d4903 100644 --- a/include/boost/pending/integer_range.hpp +++ b/include/boost/pending/integer_range.hpp @@ -16,7 +16,7 @@ #ifdef BOOST_MSVC #include #else -#include +#include #endif namespace boost { From 76efd2456c44d9b7580ef3e19441bd030cd63cd6 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 22 Sep 2000 04:18:51 +0000 Subject: [PATCH 006/265] changes for visual c++ port [SVN r7764] --- include/boost/pending/integer_range.hpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/include/boost/pending/integer_range.hpp b/include/boost/pending/integer_range.hpp index 37d4903..f3c54c6 100644 --- a/include/boost/pending/integer_range.hpp +++ b/include/boost/pending/integer_range.hpp @@ -13,10 +13,14 @@ #ifndef BOOST_INTEGER_RANGE_HPP_ #define BOOST_INTEGER_RANGE_HPP_ -#ifdef BOOST_MSVC -#include -#else +#ifndef BOOST_MSVC +#define BOOST_USE_ITERATOR_ADAPTORS +#endif + +#ifdef BOOST_USE_ITERATOR_ADAPTORS #include +#else +#include #endif namespace boost { @@ -24,6 +28,7 @@ namespace boost { //============================================================================= // Counting Iterator and Integer Range Class +#ifdef BOOST_USE_ITERATOR_ADAPTORS struct counting_iterator_policies : public default_iterator_policies { template @@ -38,14 +43,15 @@ struct counting_iterator_traits { typedef std::ptrdiff_t difference_type; typedef std::random_access_iterator_tag iterator_category; }; +#endif template struct integer_range { -#ifdef BOOST_MSVC - typedef int_iterator iterator; -#else +#ifdef BOOST_USE_ITERATOR_ADAPTORS typedef iterator_adaptor, IntegerType> iterator; +#else + typedef int_iterator iterator; #endif typedef iterator const_iterator; typedef IntegerType value_type; @@ -73,4 +79,8 @@ protected: } // namespace boost +#ifndef BOOST_MSVC +#undef BOOST_USE_ITERATOR_ADAPTORS +#endif + #endif // BOOST_INTEGER_RANGE_HPP_ From 61d2d43ea54475a2183025e5beb194586af6fd48 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 24 Sep 2000 01:06:34 +0000 Subject: [PATCH 007/265] Use iterator adaptors with STLport. [SVN r7788] --- include/boost/pending/integer_range.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/pending/integer_range.hpp b/include/boost/pending/integer_range.hpp index f3c54c6..d6ab718 100644 --- a/include/boost/pending/integer_range.hpp +++ b/include/boost/pending/integer_range.hpp @@ -13,7 +13,7 @@ #ifndef BOOST_INTEGER_RANGE_HPP_ #define BOOST_INTEGER_RANGE_HPP_ -#ifndef BOOST_MSVC +#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT) #define BOOST_USE_ITERATOR_ADAPTORS #endif From c583cf87301e1dca0c3be0500641324d2c34f4f9 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 25 Sep 2000 21:19:29 +0000 Subject: [PATCH 008/265] removed tabs [SVN r7835] --- include/boost/pending/iterator_adaptors.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 183857f..8c185fb 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -475,7 +475,7 @@ struct reverse_iterator_policies template Difference distance(type, const Iterator1& x, - const Iterator2& y) const + const Iterator2& y) const { return x - y; } template From 50c9214b82f00ca0e6b7f04c97feefa4b27e9b4b Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Tue, 26 Sep 2000 07:29:12 +0000 Subject: [PATCH 009/265] completed conversion of properties to use _t and enums. Also noticed that problems regarding iterator_adaptor has gone away, so I've removed the ifdef's that took it out. [SVN r7840] --- include/boost/pending/integer_range.hpp | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/include/boost/pending/integer_range.hpp b/include/boost/pending/integer_range.hpp index d6ab718..7bd35a0 100644 --- a/include/boost/pending/integer_range.hpp +++ b/include/boost/pending/integer_range.hpp @@ -13,22 +13,13 @@ #ifndef BOOST_INTEGER_RANGE_HPP_ #define BOOST_INTEGER_RANGE_HPP_ -#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT) -#define BOOST_USE_ITERATOR_ADAPTORS -#endif - -#ifdef BOOST_USE_ITERATOR_ADAPTORS #include -#else -#include -#endif namespace boost { //============================================================================= // Counting Iterator and Integer Range Class -#ifdef BOOST_USE_ITERATOR_ADAPTORS struct counting_iterator_policies : public default_iterator_policies { template @@ -43,16 +34,12 @@ struct counting_iterator_traits { 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, IntegerType> iterator; -#else - typedef int_iterator iterator; -#endif + typedef iterator const_iterator; typedef IntegerType value_type; typedef std::ptrdiff_t difference_type; @@ -79,8 +66,4 @@ protected: } // namespace boost -#ifndef BOOST_MSVC -#undef BOOST_USE_ITERATOR_ADAPTORS -#endif - #endif // BOOST_INTEGER_RANGE_HPP_ From 24c3beb79135f91691e2b1cbe2fc56101c26332a Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Tue, 26 Sep 2000 22:09:34 +0000 Subject: [PATCH 010/265] rolled back the removal of the iterator_adaptor alternate code, added the graph test file [SVN r7851] --- include/boost/pending/integer_range.hpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/boost/pending/integer_range.hpp b/include/boost/pending/integer_range.hpp index 7bd35a0..35b735e 100644 --- a/include/boost/pending/integer_range.hpp +++ b/include/boost/pending/integer_range.hpp @@ -13,13 +13,22 @@ #ifndef BOOST_INTEGER_RANGE_HPP_ #define BOOST_INTEGER_RANGE_HPP_ +#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT) +#define BOOST_USE_ITERATOR_ADAPTORS +#endif + +#ifdef BOOST_USE_ITERATOR_ADAPTORS #include +#else +#include +#endif namespace boost { //============================================================================= // Counting Iterator and Integer Range Class +#ifdef BOOST_USE_ITERATOR_ADAPTORS struct counting_iterator_policies : public default_iterator_policies { template @@ -34,11 +43,16 @@ struct counting_iterator_traits { 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, IntegerType> iterator; +#else + typedef int_iterator iterator; +#endif typedef iterator const_iterator; typedef IntegerType value_type; @@ -66,4 +80,8 @@ protected: } // namespace boost +#ifdef BOOST_USE_ITERATOR_ADAPTORS +#undef BOOST_USE_ITERATOR_ADAPTORS +#endif + #endif // BOOST_INTEGER_RANGE_HPP_ From b54236986dbef9e8a18cbaf05b70e491f5567e32 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Wed, 27 Sep 2000 21:02:16 +0000 Subject: [PATCH 011/265] work around for VC++ bug, triggered by overloading of remove_edge [SVN r7860] --- include/boost/pending/integer_range.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/pending/integer_range.hpp b/include/boost/pending/integer_range.hpp index 35b735e..2357d46 100644 --- a/include/boost/pending/integer_range.hpp +++ b/include/boost/pending/integer_range.hpp @@ -13,6 +13,8 @@ #ifndef BOOST_INTEGER_RANGE_HPP_ #define BOOST_INTEGER_RANGE_HPP_ +#include + #if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT) #define BOOST_USE_ITERATOR_ADAPTORS #endif From cebe553621cb23f1d1913bc165350fbdcfb5d439 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Tue, 17 Oct 2000 00:16:05 +0000 Subject: [PATCH 012/265] ported the graph library to borland [SVN r7965] --- include/boost/pending/iterator_adaptors.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 8c185fb..dddd457 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -37,8 +37,11 @@ struct type {}; // 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. + template - static Reference dereference(type, const Iterator& x) + Reference dereference(type, const Iterator& x) const { return *x; } template @@ -54,15 +57,15 @@ struct default_iterator_policies { x += n; } template - static Difference distance(type, const Iterator1& x, const Iterator2& y) + Difference distance(type, const Iterator1& x, const Iterator2& y) const { return y - x; } template - static bool equal(const Iterator1& x, const Iterator2& y) + bool equal(const Iterator1& x, const Iterator2& y) const { return x == y; } template - static bool less(const Iterator1& x, const Iterator2& y) + bool less(const Iterator1& x, const Iterator2& y) const { return x < y; } }; From d3b8f893bc8462b92ffd5b4edf02d59d0dbc97d5 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 26 Oct 2000 14:04:50 +0000 Subject: [PATCH 013/265] changed reference type [SVN r8033] --- include/boost/pending/integer_range.hpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/include/boost/pending/integer_range.hpp b/include/boost/pending/integer_range.hpp index 2357d46..cb420c6 100644 --- a/include/boost/pending/integer_range.hpp +++ b/include/boost/pending/integer_range.hpp @@ -34,13 +34,14 @@ namespace boost { struct counting_iterator_policies : public default_iterator_policies { template - IntegerType dereference(type, const IntegerType& i) const + const IntegerType& + dereference(type, const IntegerType& i) const { return i; } }; template struct counting_iterator_traits { typedef IntegerType value_type; - typedef IntegerType reference; + typedef const IntegerType& reference; typedef value_type* pointer; typedef std::ptrdiff_t difference_type; typedef std::random_access_iterator_tag iterator_category; @@ -80,6 +81,13 @@ protected: IntegerType m_start, m_finish; }; +template +inline integer_range +make_integer_range(IntegerType first, IntegerType last) +{ + return integer_range(first, last); +} + } // namespace boost #ifdef BOOST_USE_ITERATOR_ADAPTORS From 3692175786a62d98c4c6436d956559327f5cbf3e Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 2 Nov 2000 02:29:53 +0000 Subject: [PATCH 014/265] added base() function [SVN r8098] --- include/boost/pending/iterator_adaptors.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index dddd457..996c510 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -174,10 +174,11 @@ public: 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& iter, const Policies& p = Policies()) + iterator_adaptor(const iterator_type& iter, const Policies& p = Policies()) : m_iter_p(iter, p) {} #ifdef BOOST_MSVC6_MEMBER_TEMPLATES @@ -249,6 +250,8 @@ public: return *this; } + iterator_type base() const { return m_iter_p.first(); } + private: typedef Policies policies_type; compressed_pair m_iter_p; From efcbd242293c72e3118d4128ac66991357914ec3 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 3 Nov 2000 04:25:13 +0000 Subject: [PATCH 015/265] port to Codewarrior 6.0 [SVN r8107] --- include/boost/pending/iterator_adaptors.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 996c510..0215b67 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -227,7 +227,13 @@ public: { 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; } From 9d659841a0043269425100d5b64b4cb9c663273c Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sat, 4 Nov 2000 23:15:10 +0000 Subject: [PATCH 016/265] don't use iterator adaptors at all under VC++, even with STLport until we can figure out why the INTERNAL COMPILER ERROR's are happening [SVN r8139] --- include/boost/pending/integer_range.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/pending/integer_range.hpp b/include/boost/pending/integer_range.hpp index cb420c6..7726936 100644 --- a/include/boost/pending/integer_range.hpp +++ b/include/boost/pending/integer_range.hpp @@ -15,7 +15,7 @@ #include -#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT) +#if !defined(BOOST_MSVC) #define BOOST_USE_ITERATOR_ADAPTORS #endif From ea1513596d734229fcf0c831d04c681cb2d57f05 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Tue, 7 Nov 2000 22:22:49 +0000 Subject: [PATCH 017/265] changed counting iterator policies to a template class to avoid using template member functions [SVN r8157] --- include/boost/pending/integer_range.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/boost/pending/integer_range.hpp b/include/boost/pending/integer_range.hpp index 7726936..3d396b4 100644 --- a/include/boost/pending/integer_range.hpp +++ b/include/boost/pending/integer_range.hpp @@ -15,7 +15,8 @@ #include -#if !defined(BOOST_MSVC) +#if 1 +// Still evaluating whether VC++ can handle this. #define BOOST_USE_ITERATOR_ADAPTORS #endif @@ -31,9 +32,9 @@ namespace boost { // Counting Iterator and Integer Range Class #ifdef BOOST_USE_ITERATOR_ADAPTORS +template struct counting_iterator_policies : public default_iterator_policies { - template const IntegerType& dereference(type, const IntegerType& i) const { return i; } @@ -51,7 +52,8 @@ struct counting_iterator_traits { template struct integer_range { #ifdef BOOST_USE_ITERATOR_ADAPTORS - typedef iterator_adaptor, counting_iterator_traits, IntegerType> iterator; #else typedef int_iterator iterator; From 87a3007c9257c7d7b991193db17d459323d1482e Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 10 Nov 2000 16:24:39 +0000 Subject: [PATCH 018/265] completed codewarrior workaround [SVN r8169] --- include/boost/pending/iterator_adaptors.hpp | 27 +++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 0215b67..33a88c5 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -20,8 +20,8 @@ // 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 +// 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 @@ -32,7 +32,7 @@ namespace boost { template struct type {}; -//============================================================================= +//============================================================================ // Default policies for iterator adaptors. You can use this as a base // class if you want to customize particular policies. struct default_iterator_policies @@ -57,7 +57,8 @@ struct default_iterator_policies { x += n; } template - Difference distance(type, const Iterator1& x, const Iterator2& y) const + Difference distance(type, const Iterator1& x, + const Iterator2& y) const { return y - x; } template @@ -131,7 +132,7 @@ inline bool operator<=(const iterator_comparisons& xb, } #endif -//============================================================================= +//============================================================================ // iterator_adaptor - A generalized adaptor around an existing // iterator, which is itself an iterator // @@ -167,7 +168,7 @@ struct iterator_adaptor : > #endif { - typedef iterator_adaptor Self; + typedef iterator_adaptor Self; public: typedef typename Traits::difference_type difference_type; typedef typename Traits::value_type value_type; @@ -178,7 +179,7 @@ public: iterator_adaptor() { } - iterator_adaptor(const iterator_type& iter, const Policies& p = Policies()) + iterator_adaptor(const iterator_type& iter, const Policies& p =Policies()) : m_iter_p(iter, p) {} #ifdef BOOST_MSVC6_MEMBER_TEMPLATES @@ -240,19 +241,31 @@ public: Self operator++(int) { Self tmp(*this); ++*this; return tmp; } Self& operator--() { +#ifdef __MWERKS__ + policies().decrement(iter()); +#else policies().decrement(iter()); +#endif return *this; } Self operator--(int) { Self tmp(*this); --*this; return tmp; } Self& operator+=(difference_type n) { +#ifdef __MWERKS__ + policies().advance(iter(), n); +#else policies().advance(iter(), n); +#endif return *this; } Self& operator-=(difference_type n) { +#ifdef __MWERKS__ + policies().advance(iter(), -n); +#else policies().advance(iter(), -n); +#endif return *this; } From 80bcc4e643b89c03ef05d89c00cf1b6178b2a008 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 20 Nov 2000 18:17:52 +0000 Subject: [PATCH 019/265] some concept checking changes as per review comments [SVN r8268] --- include/boost/pending/detail/int_iterator.hpp | 9 ++++++++- include/boost/pending/iterator_tests.hpp | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/boost/pending/detail/int_iterator.hpp b/include/boost/pending/detail/int_iterator.hpp index 346774c..9fcfffe 100644 --- a/include/boost/pending/detail/int_iterator.hpp +++ b/include/boost/pending/detail/int_iterator.hpp @@ -40,7 +40,7 @@ public: inline self& operator++() { ++_i; return *this; } inline self operator++(int) { self t = *this; ++_i; return t; } inline self& operator+=(IntT n) { _i += n; return *this; } - inline self operator+(IntT n) { self t = *this; t._i += n; return t; } + inline self operator+(IntT n) { self t = *this; t += n; return t; } inline self& operator--() { --_i; return *this; } inline self operator--(int) { self t = *this; --_i; return t; } inline self& operator-=(IntT n) { _i -= n; return *this; } @@ -50,10 +50,17 @@ public: // need to look into this... for now implementing everything here -JGS inline bool operator!=(const self& x) const { return _i != x._i; } inline bool operator<(const self& x) const { return _i < x._i; } + inline bool operator<=(const self& x) const { return _i <= x._i; } + inline bool operator>(const self& x) const { return _i > x._i; } + inline bool operator>=(const self& x) const { return _i >= x._i; } protected: IntT _i; }; +template +inline int_iterator +operator+(IntT n, int_iterator t) { t += n; return t; } + #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE } /* namespace boost */ #endif diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp index df74d83..981eb55 100644 --- a/include/boost/pending/iterator_tests.hpp +++ b/include/boost/pending/iterator_tests.hpp @@ -141,7 +141,8 @@ void random_access_iterator_test(Iterator i, int N, TrueVals vals) assert(i == k - c); assert(*i == vals[N - 1 - c]); assert(*i == j[N - 1 - c]); - assert(*i == *(k - c)); + Iterator q = k - c; + assert(*i == *q); assert(i > j); assert(i >= j); assert(j <= i); From 31fef5252afbdb9c31406ff00b9c78a3f4ec5cb5 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 24 Nov 2000 19:40:51 +0000 Subject: [PATCH 020/265] simplified version of iterator_adaptor, plus fix to indirect iterator and addition of projection iterator [SVN r8317] --- include/boost/pending/integer_range.hpp | 2 +- include/boost/pending/iterator_adaptors.hpp | 268 ++++++++++++++------ 2 files changed, 190 insertions(+), 80 deletions(-) diff --git a/include/boost/pending/integer_range.hpp b/include/boost/pending/integer_range.hpp index 3d396b4..6877d19 100644 --- a/include/boost/pending/integer_range.hpp +++ b/include/boost/pending/integer_range.hpp @@ -54,7 +54,7 @@ struct integer_range { #ifdef BOOST_USE_ITERATOR_ADAPTORS typedef iterator_adaptor, - counting_iterator_traits, IntegerType> iterator; + counting_iterator_traits > iterator; #else typedef int_iterator iterator; #endif diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 33a88c5..0f03cd6 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -13,9 +13,8 @@ #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 @@ -144,22 +143,17 @@ inline bool operator<=(const iterator_comparisons& xb, // Traits - a class satisfying the same requirements as a specialization of // std::iterator_traits for the resulting iterator. // -// NonconstIterator - the corresponding non-const iterator type for -// Iterator, if any. You don't need to supply this if you are not make a -// const/non-const iterator pair. -// template , + class Traits = std::iterator_traits #endif - class NonconstIterator = Iterator > struct iterator_adaptor : #ifdef BOOST_RELOPS_AMBIGUITY_BUG iterator_comparisons< - iterator_adaptor, + iterator_adaptor, #endif boost::iterator #endif { - typedef iterator_adaptor Self; + typedef iterator_adaptor Self; public: typedef typename Traits::difference_type difference_type; typedef typename Traits::value_type value_type; @@ -179,35 +173,15 @@ public: iterator_adaptor() { } - iterator_adaptor(const iterator_type& iter, const Policies& p =Policies()) + iterator_adaptor(const Iterator& iter, const Policies& p = Policies()) : m_iter_p(iter, p) {} -#ifdef BOOST_MSVC6_MEMBER_TEMPLATES - template - iterator_adaptor(const iterator_adaptor& rhs) - : m_iter_p(rhs.iter(), rhs.policies()) {} - - template - Self& operator=(const iterator_adaptor& rhs) - { - iter() = rhs.iter(); - policies() = rhs.policies(); - return *this; + template + iterator_adaptor (const iterator_adaptor& src) + : m_iter_p(src.iter(), src.policies()) { } -#else - template - iterator_adaptor(const iterator_adaptor& rhs) - : m_iter_p(rhs.iter(), rhs.policies()) {} - - template - Self& operator=(const iterator_adaptor& rhs) - { - iter() = rhs.iter(); - policies() = rhs.policies(); - return *this; - } -#endif - + reference operator*() const { return policies().dereference(type(), iter()); } @@ -281,73 +255,73 @@ public: // too many compilers have trouble when these are private. const Iterator& iter() const { return m_iter_p.first(); } }; -template -iterator_adaptor -operator-(iterator_adaptor p, const typename Traits::difference_type x) +template +iterator_adaptor +operator-(iterator_adaptor p, const typename Traits::difference_type x) { return p -= x; } -template -iterator_adaptor -operator+(iterator_adaptor p, const typename Traits::difference_type x) +template +iterator_adaptor +operator+(iterator_adaptor p, typename Traits::difference_type x) { return p += x; } -template -iterator_adaptor -operator+(const typename Traits::difference_type x, iterator_adaptor p) +template +iterator_adaptor +operator+(typename Traits::difference_type x, iterator_adaptor p) { return p += x; } -template +template typename Traits1::difference_type operator-( - const iterator_adaptor& x, - const iterator_adaptor& y ) + 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 +template inline bool -operator==(const iterator_adaptor& x, const iterator_adaptor& y) { +operator==(const iterator_adaptor& x, const iterator_adaptor& y) { return x.policies().equal(x.iter(), y.iter()); } -template +template inline bool -operator<(const iterator_adaptor& x, const iterator_adaptor& y) { +operator<(const iterator_adaptor& x, const iterator_adaptor& y) { return x.policies().less(x.iter(), y.iter()); } -template +template inline bool -operator>(const iterator_adaptor& x, - const iterator_adaptor& y) { +operator>(const iterator_adaptor& x, + const iterator_adaptor& y) { return x.policies().less(y.iter(), x.iter()); } -template +template inline bool -operator>=(const iterator_adaptor& x, const iterator_adaptor& y) { +operator>=(const iterator_adaptor& x, const iterator_adaptor& y) { return !x.policies().less(x.iter(), y.iter()); } -template +template inline bool -operator<=(const iterator_adaptor& x, - const iterator_adaptor& y) { +operator<=(const iterator_adaptor& x, + const iterator_adaptor& y) { return !x.policies().less(y.iter(), x.iter()); } -template +template inline bool -operator!=(const iterator_adaptor& x, - const iterator_adaptor& y) { +operator!=(const iterator_adaptor& x, + const iterator_adaptor& y) { return !x.policies().equal(x.iter(), y.iter()); } #endif @@ -359,17 +333,17 @@ operator!=(const iterator_adaptor& template , - class ConstTraits = std::iterator_traits, + class ConstTraits = std::iterator_traits, #endif class Policies = default_iterator_policies> class iterator_adaptors { public: - typedef iterator_adaptor iterator; - typedef iterator_adaptor + typedef iterator_adaptor iterator; + typedef iterator_adaptor const_iterator; }; @@ -412,8 +386,8 @@ struct transform_iterator typedef transform_iterator_traits TransTraits; typedef iterator_adaptor, TransTraits, - Iterator> type; + transform_iterator_policies, TransTraits> + type; }; @@ -449,27 +423,62 @@ struct indirect_traits typedef typename IndirectTraits::iterator_category iterator_category; }; -template , - class ConstIndirectTraits = - std::iterator_traits, - class Traits = - std::iterator_traits + class Traits = std::iterator_traits +#endif + > +struct indirect_iterator +{ + typedef typename Traits::value_type ValueType; + typedef iterator_adaptor + > type; +}; + +template , + class ConstTraits = std::iterator_traits +#endif + > +struct const_indirect_iterator +{ + typedef iterator_adaptor + > type; +}; + +template , + class Traits = std::iterator_traits, + class ConstTraits = std::iterator_traits #endif > struct indirect_iterators { - typedef typename IndirectTraits::value_type Iterator; typedef typename Traits::value_type ValueType; - typedef iterator_adaptors, - indirect_traits, + indirect_traits, indirect_iterator_policies > Adaptors; typedef typename Adaptors::iterator iterator; @@ -512,6 +521,32 @@ struct reverse_iterator_policies { 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 , @@ -529,7 +564,82 @@ struct reverse_iterators typedef typename Adaptor::const_iterator const_iterator; }; +template +struct projection_iterator_policies : + public default_iterator_policies { + template + Reference dereference (type, Iterator const& it) const { + return AdaptableUnaryFunction()(*it); + } +}; +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; +}; + } // namespace boost #endif + + From ffec5207fa5ffc1b85440694ff1c183ef0bfa0e9 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 24 Nov 2000 20:05:11 +0000 Subject: [PATCH 021/265] changed names to "Inner" and "Outer" [SVN r8318] --- include/boost/pending/iterator_adaptors.hpp | 81 ++++++++++----------- 1 file changed, 40 insertions(+), 41 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 0f03cd6..a0c550c 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -404,81 +404,80 @@ struct indirect_iterator_policies : public default_iterator_policies { return **x; } }; -template , - class Traits = - std::iterator_traits + class OuterTraits = std::iterator_traits, + class InnerTraits = std::iterator_traits #endif > struct indirect_traits { - typedef typename IndirectTraits::difference_type difference_type; - typedef typename Traits::value_type value_type; - typedef typename Traits::pointer pointer; - typedef typename Traits::reference reference; - typedef typename IndirectTraits::iterator_category iterator_category; + 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 , - class Traits = std::iterator_traits + class OuterTraits = std::iterator_traits, + class InnerTraits = std::iterator_traits #endif > struct indirect_iterator { - typedef typename Traits::value_type ValueType; - typedef iterator_adaptor + indirect_traits > type; }; -template , - class ConstTraits = std::iterator_traits + class OuterTraits = std::iterator_traits, + class ConstInnerTraits = std::iterator_traits #endif > struct const_indirect_iterator { - typedef iterator_adaptor + indirect_traits > type; }; -template , - class Traits = std::iterator_traits, - class ConstTraits = std::iterator_traits + class OuterTraits = std::iterator_traits, + class InnerTraits = std::iterator_traits, + class ConstInnerTraits = std::iterator_traits #endif > struct indirect_iterators { - typedef typename Traits::value_type ValueType; - typedef iterator_adaptors, - indirect_traits, + typedef iterator_adaptors, + indirect_traits, indirect_iterator_policies > Adaptors; typedef typename Adaptors::iterator iterator; From 04c0c043e004574137fff3b8a7cc7c9519d8d93a Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 24 Nov 2000 20:45:26 +0000 Subject: [PATCH 022/265] added projection iterator to the test [SVN r8320] --- include/boost/pending/iterator_adaptors.hpp | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index a0c550c..686a34b 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -440,24 +440,6 @@ struct indirect_iterator > type; }; -template , - class ConstInnerTraits = std::iterator_traits -#endif - > -struct const_indirect_iterator -{ - typedef iterator_adaptor - > type; -}; - template struct projection_iterator_policies : public default_iterator_policies { From 3852c810f38e655f24a9b3fb903bc6e6a440dda3 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 3 Dec 2000 06:20:23 +0000 Subject: [PATCH 023/265] various changes, almost forgot to check in [SVN r8379] --- include/boost/pending/iterator_adaptors.hpp | 49 ++++++++++++++++----- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 686a34b..d86c5ee 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -37,22 +37,23 @@ struct type {}; struct default_iterator_policies { // Some of these members were defined static, but Borland got confused - // and thought they were non-const. + // and thought they were non-const. Also, Sun C++ does not like static + // function templates. template Reference dereference(type, const Iterator& x) const { return *x; } template - static void increment(Iterator& x) + void increment(Iterator& x) { ++x; } template - static void decrement(Iterator& x) + void decrement(Iterator& x) { --x; } template - static void advance(Iterator& x, DifferenceType n) + void advance(Iterator& x, DifferenceType n) { x += n; } template @@ -350,6 +351,9 @@ public: //============================================================================= // 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 @@ -358,8 +362,8 @@ struct transform_iterator_policies : public default_iterator_policies transform_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { } template - Reference dereference(type, const Iterator& x) const - { return m_f(*x); } + Reference dereference(type, const Iterator& iter) const + { return m_f(*iter); } AdaptableUnaryFunction m_f; }; @@ -394,7 +398,16 @@ struct transform_iterator //============================================================================= // Indirect Iterators Adaptor -// Tried implementing this with transform_iterator, but that required +// 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 @@ -422,7 +435,9 @@ struct indirect_traits 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 @@ -549,13 +564,19 @@ struct reverse_iterators // Projection Iterators Adaptor template -struct projection_iterator_policies : - public default_iterator_policies { +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& it) const { - return AdaptableUnaryFunction()(*it); + 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; @@ -564,6 +585,7 @@ struct projection_iterator_traits { 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; @@ -572,6 +594,7 @@ struct const_projection_iterator_traits { typedef typename Traits::difference_type difference_type; typedef typename Traits::iterator_category iterator_category; }; + template @@ -586,6 +609,7 @@ struct projection_iterator { projection_iterator_policies, Projection_Traits> type; }; + template @@ -600,6 +624,7 @@ struct const_projection_iterator { projection_iterator_policies, Projection_Traits> type; }; + template , From 8cf1b8acb28d5f06128f905c06d124097a5228d1 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Wed, 13 Dec 2000 23:24:55 +0000 Subject: [PATCH 024/265] forgot #include [SVN r8461] --- include/boost/pending/iterator_tests.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp index 981eb55..7321eed 100644 --- a/include/boost/pending/iterator_tests.hpp +++ b/include/boost/pending/iterator_tests.hpp @@ -4,6 +4,7 @@ // This is meant to be the beginnings of a comprehensive, generic // test suite for STL concepts such as iterators and containers. +#include #include namespace boost { From e6191bc913a85e0e1a2e1606540f6f52e4d0d485 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 15 Dec 2000 19:31:16 +0000 Subject: [PATCH 025/265] operator[] needed to be const [SVN r8463] --- include/boost/pending/iterator_adaptors.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index d86c5ee..a267636 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -199,7 +199,7 @@ public: # pragma warning(pop) #endif - reference operator[](difference_type n) + reference operator[](difference_type n) const { return *(*this + n); } Self& operator++() { From 42ddb0d47b32f02e9fd5704c69968bb0544bf022 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 15 Dec 2000 21:51:02 +0000 Subject: [PATCH 026/265] added const in a couple places to make sure the iterator operators that should be const (like operator* and operator[]) are indeed const [SVN r8466] --- include/boost/pending/iterator_tests.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp index 7321eed..15a5ec4 100644 --- a/include/boost/pending/iterator_tests.hpp +++ b/include/boost/pending/iterator_tests.hpp @@ -23,7 +23,7 @@ struct dummyT { // TrivialIterator. // Preconditions: i != j, *i == val template -void trivial_iterator_test(Iterator i, Iterator j, T val) +void trivial_iterator_test(const Iterator i, const Iterator j, T val) { Iterator k; assert(i == i); @@ -52,7 +52,7 @@ void trivial_iterator_test(Iterator i, Iterator j, T val) // Preconditions: i != j template -void mutable_trivial_iterator_test(Iterator i, Iterator j, T val) +void mutable_trivial_iterator_test(const Iterator i, const Iterator j, T val) { *i = val; trivial_iterator_test(i, j, val); @@ -121,7 +121,7 @@ template void random_access_iterator_test(Iterator i, int N, TrueVals vals) { bidirectional_iterator_test(i, vals[0], vals[1]); - Iterator j = i; + const Iterator j = i; int c; for (c = 0; c < N-1; ++c) { From 0c68369f23e052e540bc200fa38f211e4ce9eaf9 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 17 Dec 2000 21:53:22 +0000 Subject: [PATCH 027/265] changed reference type of counting_iterator to avoid problems on VC++ [SVN r8474] --- include/boost/pending/integer_range.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/pending/integer_range.hpp b/include/boost/pending/integer_range.hpp index 6877d19..24a62f2 100644 --- a/include/boost/pending/integer_range.hpp +++ b/include/boost/pending/integer_range.hpp @@ -35,14 +35,14 @@ namespace boost { template struct counting_iterator_policies : public default_iterator_policies { - const IntegerType& - dereference(type, const IntegerType& i) const + IntegerType + dereference(type, const IntegerType& i) const { return i; } }; template struct counting_iterator_traits { typedef IntegerType value_type; - typedef const IntegerType& reference; + typedef IntegerType reference; typedef value_type* pointer; typedef std::ptrdiff_t difference_type; typedef std::random_access_iterator_tag iterator_category; From b634113dafdfbfcdc7ad5557c5f301f6947a72fb Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 28 Dec 2000 03:00:45 +0000 Subject: [PATCH 028/265] added concept checking classes for purposes of documentation (they don't get invoked) [SVN r8499] --- include/boost/pending/iterator_adaptors.hpp | 81 +++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index a267636..7b5c6c4 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -16,6 +16,7 @@ #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 @@ -31,6 +32,86 @@ namespace boost { template struct type {}; + +//============================================================================ +// 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); + } + Policies p; + Adapted x; + mutable bool b; +}; + +template +struct ForwardIteratorPoliciesConcept +{ + void constraints() { + function_requires< + TrivialIteratorPoliciesConcept + >(); + + p.increment(x); + } + Policies p; + Adapted x; +}; + +template +struct BidirectionalIteratorPoliciesConcept +{ + void constraints() { + function_requires< + ForwardIteratorPoliciesConcept + >(); + + p.decrement(x); + } + Policies p; + Adapted x; +}; + +template +struct RandomAccessIteratorPoliciesConcept +{ + typedef typename Traits::difference_type DifferenceType; + void constraints() { + function_requires< + BidirectionalIteratorPoliciesConcept + >(); + + p.advance(x, n); + const_constraints(); + } + 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. From 4314dd18aeba47416641c24724e0d2ceebc77ad2 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 12 Jan 2001 18:50:21 +0000 Subject: [PATCH 029/265] added for std::ptrdiff_t [SVN r8562] --- include/boost/iterator.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/iterator.hpp b/include/boost/iterator.hpp index 82d555b..34e4e4b 100644 --- a/include/boost/iterator.hpp +++ b/include/boost/iterator.hpp @@ -1,4 +1,4 @@ -// integer.hpp workarounds for non-conforming standard libraries -----------// +// interator.hpp workarounds for non-conforming standard libraries ---------// // (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and // distribute this software is granted provided this copyright notice appears @@ -8,6 +8,7 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 12 Jan 01 added for std::ptrdiff_t (Jens Maurer) // 28 Jun 00 Workarounds to deal with known MSVC bugs (David Abrahams) // 26 Jun 00 Initial version (Jeremy Siek) @@ -15,6 +16,7 @@ #define BOOST_ITERATOR_HPP #include +#include // std::ptrdiff_t #include namespace boost From e1b64d45e2f4a35403d52e348a3cfc63304d2c0a Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 14 Jan 2001 01:14:39 +0000 Subject: [PATCH 030/265] MIPSpro port, avoid using operators that are not defined [SVN r8584] --- include/boost/pending/iterator_adaptors.hpp | 54 ++++++++++++++++----- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 7b5c6c4..8838b9b 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -213,6 +213,45 @@ inline bool operator<=(const iterator_comparisons& xb, } #endif +//============================================================================ +// Some compilers (SGI MIPSpro) 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 { + + // Dummy version for iterators that don't support member access + template + inline typename Iter::pointer + operator_arrow(const Iter&, Cat) { + typedef typename Iter::pointer Pointer; + return Pointer(); + } + // Real version + template + inline typename Iter::pointer + operator_arrow(const Iter& i, std::forward_iterator_tag) { + return &(*i); + } + + // Dummy version for iterators that don't support member access + template + inline void advance_impl(const Iter&, Diff, Cat) { } + + // Real version + template + inline typename Iter::pointer + advance_impl(const Iter& i, Diff n, std::random_access_iterator_tag) { +#ifdef __MWERKS__ + i.policies().advance(iter(), n); +#else + i.policies().advance(iter(), n); +#endif + } + +} // namespace detail + //============================================================================ // iterator_adaptor - A generalized adaptor around an existing // iterator, which is itself an iterator @@ -274,7 +313,7 @@ public: #endif pointer operator->() const - { return &*this; } + { return detail::operator_arrow(*this, iterator_category()); } #ifdef _MSC_VER # pragma warning(pop) @@ -308,20 +347,12 @@ public: Self operator--(int) { Self tmp(*this); --*this; return tmp; } Self& operator+=(difference_type n) { -#ifdef __MWERKS__ - policies().advance(iter(), n); -#else - policies().advance(iter(), n); -#endif + detail::advance_impl(*this, n, iterator_category()); return *this; } Self& operator-=(difference_type n) { -#ifdef __MWERKS__ - policies().advance(iter(), -n); -#else - policies().advance(iter(), -n); -#endif + detail::advance_impl(*this, -n, iterator_category()); return *this; } @@ -337,6 +368,7 @@ public: // too many compilers have trouble when these are private. const Iterator& iter() const { return m_iter_p.first(); } }; + template iterator_adaptor operator-(iterator_adaptor p, const typename Traits::difference_type x) From d6ec67f6ed7f84e34e3b8c2062b6fb862aa5a2a4 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 14 Jan 2001 01:27:01 +0000 Subject: [PATCH 031/265] added version number for MIPSpro [SVN r8586] --- include/boost/pending/iterator_adaptors.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 8838b9b..6de86d0 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -214,7 +214,7 @@ inline bool operator<=(const iterator_comparisons& xb, #endif //============================================================================ -// Some compilers (SGI MIPSpro) instantiate/compile member functions +// 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. From 487acf8c1cbb0a70f9d0c4ed2f072394f2733db5 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 14 Jan 2001 19:21:29 +0000 Subject: [PATCH 032/265] iter() should be i.iter() [SVN r8594] --- include/boost/pending/iterator_adaptors.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 6de86d0..d313e3c 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -244,9 +244,9 @@ namespace detail { inline typename Iter::pointer advance_impl(const Iter& i, Diff n, std::random_access_iterator_tag) { #ifdef __MWERKS__ - i.policies().advance(iter(), n); + i.policies().advance(i.iter(), n); #else - i.policies().advance(iter(), n); + i.policies().advance(i.iter(), n); #endif } From 42710d0967da118bba0051c887490944ddb31c52 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 14 Jan 2001 19:23:19 +0000 Subject: [PATCH 033/265] also, advance_impl should take non-const Iter param [SVN r8595] --- include/boost/pending/iterator_adaptors.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index d313e3c..a2f394d 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -237,12 +237,12 @@ namespace detail { // Dummy version for iterators that don't support member access template - inline void advance_impl(const Iter&, Diff, Cat) { } + inline void advance_impl(Iter&, Diff, Cat) { } // Real version template inline typename Iter::pointer - advance_impl(const Iter& i, Diff n, std::random_access_iterator_tag) { + advance_impl(Iter& i, Diff n, std::random_access_iterator_tag) { #ifdef __MWERKS__ i.policies().advance(i.iter(), n); #else From 34a9d4e702be5b8abd2dc70f560040ee89f275a4 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 14 Jan 2001 21:10:44 +0000 Subject: [PATCH 034/265] another MIPSpro workaround [SVN r8597] --- include/boost/pending/iterator_adaptors.hpp | 23 +++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index a2f394d..f454d10 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -235,7 +235,7 @@ namespace detail { return &(*i); } - // Dummy version for iterators that don't support member access + // Dummy version for non-random access iterators template inline void advance_impl(Iter&, Diff, Cat) { } @@ -250,6 +250,21 @@ namespace detail { #endif } + // Dummy version for non-bidirectional iterators + template + inline void decrement_impl(Iter&, Cat) { } + + // Real version + template + inline typename Iter::pointer + decrement_impl(Iter& i, std::bidirectional_iterator_tag) { +#ifdef __MWERKS__ + i.policies().decrement(i.iter()); +#else + i.policies().decrement(i.iter()); +#endif + } + } // namespace detail //============================================================================ @@ -336,11 +351,7 @@ public: Self operator++(int) { Self tmp(*this); ++*this; return tmp; } Self& operator--() { -#ifdef __MWERKS__ - policies().decrement(iter()); -#else - policies().decrement(iter()); -#endif + detail::decrement_impl(*this, iterator_category()); return *this; } From 7fa5da6778fb0e9dbee29b51e8c174d557c927cb Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 15 Jan 2001 02:51:45 +0000 Subject: [PATCH 035/265] fixed dispatch for MIPSpro workaround [SVN r8599] --- include/boost/pending/iterator_adaptors.hpp | 29 ++++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index f454d10..cd1ee5e 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -221,13 +221,18 @@ inline bool operator<=(const iterator_comparisons& xb, namespace detail { - // Dummy version for iterators that don't support member access - template + // Dummy versions for iterators that don't support member access + template inline typename Iter::pointer - operator_arrow(const Iter&, Cat) { - typedef typename Iter::pointer Pointer; - return 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(); + } + // Real version template inline typename Iter::pointer @@ -236,8 +241,10 @@ namespace detail { } // Dummy version for non-random access iterators - template - inline void advance_impl(Iter&, Diff, Cat) { } + template + inline void advance_impl(Iter&, Diff, std::input_iterator_tag) { } + template + inline void advance_impl(Iter&, Diff, std::output_iterator_tag) { } // Real version template @@ -250,9 +257,11 @@ namespace detail { #endif } - // Dummy version for non-bidirectional iterators - template - inline void decrement_impl(Iter&, Cat) { } + // Dummy versions for non-bidirectional iterators + template + inline void decrement_impl(Iter&, std::input_iterator_tag) { } + template + inline void decrement_impl(Iter&, std::output_iterator_tag) { } // Real version template From cf1d6a30afa6b57286ae8492292227961ca20491 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 15 Jan 2001 03:10:11 +0000 Subject: [PATCH 036/265] fixed some warnings under g++ [SVN r8600] --- include/boost/pending/iterator_adaptors.hpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index cd1ee5e..379762b 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -55,35 +55,45 @@ struct TrivialIteratorPoliciesConcept 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; @@ -93,13 +103,16 @@ 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); @@ -248,7 +261,7 @@ namespace detail { // Real version template - inline typename Iter::pointer + inline void advance_impl(Iter& i, Diff n, std::random_access_iterator_tag) { #ifdef __MWERKS__ i.policies().advance(i.iter(), n); @@ -265,7 +278,7 @@ namespace detail { // Real version template - inline typename Iter::pointer + inline void decrement_impl(Iter& i, std::bidirectional_iterator_tag) { #ifdef __MWERKS__ i.policies().decrement(i.iter()); From b8ccd48fa3218e494da712114fcbd3c43acb3ed0 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 21 Jan 2001 06:20:20 +0000 Subject: [PATCH 037/265] Moved type<> to boost/type.hpp [SVN r8678] --- include/boost/pending/iterator_adaptors.hpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 379762b..121c47f 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -17,6 +17,7 @@ #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 @@ -28,11 +29,6 @@ namespace boost { -// Just a "type envelope"; works around some MSVC deficiencies. -template -struct type {}; - - //============================================================================ // Concept checking classes that express the requirements for iterator // policies and adapted types. These classes are mostly for From a31a89ae7d0fd0bef7c5e62703b88b2638d6b60c Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 21 Jan 2001 19:33:06 +0000 Subject: [PATCH 038/265] fixed some mwerks compiler errors [SVN r8683] --- include/boost/pending/detail/int_iterator.hpp | 2 +- include/boost/pending/iterator_adaptors.hpp | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/include/boost/pending/detail/int_iterator.hpp b/include/boost/pending/detail/int_iterator.hpp index 9fcfffe..2d96185 100644 --- a/include/boost/pending/detail/int_iterator.hpp +++ b/include/boost/pending/detail/int_iterator.hpp @@ -29,7 +29,7 @@ public: typedef IntT value_type; typedef IntT& reference; typedef IntT* pointer; - typedef ptrdiff_t difference_type; + typedef std::ptrdiff_t difference_type; inline int_iterator() : _i(0) { } inline int_iterator(IntT i) : _i(i) { } diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 121c47f..3501e6a 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -259,11 +259,7 @@ namespace detail { template inline void advance_impl(Iter& i, Diff n, std::random_access_iterator_tag) { -#ifdef __MWERKS__ - i.policies().advance(i.iter(), n); -#else i.policies().advance(i.iter(), n); -#endif } // Dummy versions for non-bidirectional iterators @@ -276,11 +272,7 @@ namespace detail { template inline void decrement_impl(Iter& i, std::bidirectional_iterator_tag) { -#ifdef __MWERKS__ - i.policies().decrement(i.iter()); -#else i.policies().decrement(i.iter()); -#endif } } // namespace detail From c948483ec10c9a8bd96bd4351ca543068a569646 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 21 Jan 2001 20:28:02 +0000 Subject: [PATCH 039/265] added some #ifdefs to prevent compilation of workaround code [SVN r8688] --- include/boost/pending/iterator_adaptors.hpp | 30 ++++++++++----------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 3501e6a..74f4534 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -230,7 +230,8 @@ inline bool operator<=(const iterator_comparisons& xb, namespace detail { - // Dummy versions for iterators that don't support member access +#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) { @@ -242,33 +243,30 @@ namespace detail { return typename Iter::pointer(); } - // Real version + 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); } - // Dummy version for non-random access iterators - template - inline void advance_impl(Iter&, Diff, std::input_iterator_tag) { } - template - inline void advance_impl(Iter&, Diff, std::output_iterator_tag) { } - - // Real version template inline void advance_impl(Iter& i, Diff n, std::random_access_iterator_tag) { i.policies().advance(i.iter(), n); } - // Dummy versions for non-bidirectional iterators - template - inline void decrement_impl(Iter&, std::input_iterator_tag) { } - template - inline void decrement_impl(Iter&, std::output_iterator_tag) { } - - // Real version template inline void decrement_impl(Iter& i, std::bidirectional_iterator_tag) { From 9a4b0b576dbc86c9f2dc2c0d6e16272e0f93dd76 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Tue, 23 Jan 2001 19:09:30 +0000 Subject: [PATCH 040/265] added filter iterator [SVN r8735] --- include/boost/pending/iterator_adaptors.hpp | 55 +++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 74f4534..8ceb505 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -130,6 +130,10 @@ struct default_iterator_policies // 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; } @@ -317,13 +321,16 @@ public: iterator_adaptor() { } - iterator_adaptor(const Iterator& iter, const Policies& p = Policies()) - : m_iter_p(iter, p) {} + 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()); } reference operator*() const { @@ -617,7 +624,7 @@ struct indirect_iterators //============================================================================= // Reverse Iterators Adaptor -struct reverse_iterator_policies +struct reverse_iterator_policies : public default_iterator_policies { template Reference dereference(type, const Iterator& x) const @@ -778,6 +785,48 @@ struct projection_iterators { 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 58b56fbabb4fc9ba761efe238cdd23df143b0378 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 24 Jan 2001 18:36:52 +0000 Subject: [PATCH 041/265] Initial checkin [SVN r8757] --- include/boost/counting_iterator.hpp | 178 ++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 include/boost/counting_iterator.hpp diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp new file mode 100644 index 0000000..2279c93 --- /dev/null +++ b/include/boost/counting_iterator.hpp @@ -0,0 +1,178 @@ +// (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. +// +// See http://www.boost.org for most recent version including documentation. +// +// Supplies: +// +// template class counting_iterator_traits; +// template class counting_iterator_policies; +// +// Iterator traits and policies for adapted iterators whose dereferenced +// value progresses through consecutive values of Incrementable when the +// iterator is derferenced. +// +// template +// iterator_adaptor, +// counting_iterator_traits > +// counting_iterator(Incrementable); +// +// A function which produces an adapted counting iterator over values of +// Incrementable. +// +// Revision History +// 24 Jan 2001 initial revision, based on Jeremy Siek's +// boost/pending/integer_range.hpp (David Abrahams) + +#ifndef BOOST_COUNTING_ITERATOR_HPP_DWA20000119 +# define BOOST_COUNTING_ITERATOR_HPP_DWA20000119 + +# include +# include +# include +# include +# include +# ifndef BOOST_NO_LIMITS +# include +# endif + +namespace boost { + +namespace detail { + + // Template class counting_iterator_traits_select -- choose an + // iterator_category and difference_type for a counting_iterator at + // compile-time based on whether or not it wraps an integer or an iterator, + // using "poor man's partial specialization". + template struct counting_iterator_traits_select; + + // Incrementable is an iterator type + template <> + struct counting_iterator_traits_select + { + template + struct traits + { + private: + typedef boost::detail::iterator_traits x; + public: + typedef typename x::iterator_category iterator_category; + typedef typename x::difference_type difference_type; + }; + }; + + // Incrementable is a numeric type + template <> + struct counting_iterator_traits_select + { + template + struct traits + { + typedef typename + boost::detail::numeric_traits::difference_type + difference_type; + typedef std::random_access_iterator_tag iterator_category; + }; + }; + + // Template class distance_policy_select -- choose a policy for computing the + // distance between counting_iterators at compile-time based on whether or not + // the iterator wraps an integer or an iterator, using "poor man's partial + // specialization". + + template struct distance_policy_select; + + // A policy for wrapped iterators + template <> + struct distance_policy_select + { + template + struct policy { + static Distance distance(Incrementable x, Incrementable y) + { return boost::detail::distance(x, y); } + }; + }; + + // A policy for wrapped numbers + template <> + struct distance_policy_select + { + template + struct policy { + static Distance distance(Incrementable x, Incrementable y) + { return numeric_distance(x, y); } + }; + }; + + // Compute the distance over arbitrary numeric and/or iterator types + template + Distance any_distance(Incrementable start, Incrementable finish, Distance* = 0) + { + return distance_policy_select< +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + std::numeric_limits::is_specialized +#else + // Causes warnings with GCC, but how else can I detect numeric types + // at compile-time? + (boost::is_convertible::value && + boost::is_convertible::value) +#endif + >::template policy::distance(start, finish); + } + +} // namespace detail + +template +struct counting_iterator_traits { + private: + typedef typename detail::counting_iterator_traits_select<( +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + std::numeric_limits::is_specialized +#else + // Causes warnings with GCC, but how else can I detect numeric types at + // compile-time? + (boost::is_convertible::value && + boost::is_convertible::value) +#endif + )>::template traits traits; + public: + typedef Incrementable value_type; + typedef const Incrementable& reference; + typedef const value_type* pointer; + typedef typename traits::difference_type difference_type; + typedef typename traits::iterator_category iterator_category; +}; + +template +struct counting_iterator_policies : public default_iterator_policies +{ + const Incrementable& dereference(type, const Incrementable& i) const + { return i; } + + template + Difference distance(type, const Iterator1& x, + const Iterator2& y) const + { + return boost::detail::any_distance(x, y);//,(Difference*)()); + } +}; + +// Manufacture a counting iterator for an arbitrary incrementable type +template +inline iterator_adaptor, + counting_iterator_traits > +counting_iterator(Incrementable x) +{ + return iterator_adaptor, + counting_iterator_traits >(x); +} + +} // namespace boost + +#endif // BOOST_COUNTING_ITERATOR_HPP_DWA20000119 From 8f41e88f85adcb4189dcbb07e4bd8ef8d7894593 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 25 Jan 2001 04:57:16 +0000 Subject: [PATCH 042/265] 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 043/265] 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 044/265] 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 045/265] 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 046/265] 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 047/265] 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 048/265] 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 049/265] 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 050/265] 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 051/265] 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 052/265] 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 053/265] 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 054/265] 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 055/265] 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 056/265] 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 057/265] 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 058/265] 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 059/265] 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, From ee9f140fae4ca7608e802ce55278eaa0a4ddfef2 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 8 Feb 2001 03:07:33 +0000 Subject: [PATCH 060/265] Removed all pair generator's except for projection and some const adaptor generators. Added make_xxx_iterator() helper functions for remaining iterator adaptors. Removed some traits template parameters where they where no longer needed thanks to detail::iterator_traits. Moved some of the compile-time logic into enums for EDG compatibility. [SVN r9024] --- include/boost/iterator_adaptors.hpp | 296 +++++++++++++++------------- 1 file changed, 162 insertions(+), 134 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 47d4001..3ab25fb 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,7 +12,20 @@ // // Revision History: -// 07 Feb 2001 +// 07 Feb 2001 Jeremy Siek +// Removed all pair generator's except for projection and +// some const adaptor generators. +// +// Added make_xxx_iterator() helper functions for remaining +// iterator adaptors. +// +// Removed some traits template parameters where they +// where no longer needed thanks to detail::iterator_traits. +// +// Moved some of the compile-time logic into enums for +// EDG compatibility. +// +// 07 Feb 2001 David Abrahams // Removed iterator_adaptor_pair_generator and // reverse_iterator_pair_generator (more such culling to come) // @@ -24,7 +37,7 @@ // // Fixed naming convention of non-template parameter names // -// 06 Feb 2001 +// 06 Feb 2001 David Abrahams // Produce operator-> proxy objects for InputIterators // // Added static assertions to do some basic concept checks @@ -321,10 +334,9 @@ namespace detail { 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 + enum { is_input_iter = boost::is_convertible::value + & !boost::is_convertible::value }; + typedef typename boost::detail::if_true<(is_input_iter)>::template then< proxy, // else @@ -382,14 +394,19 @@ public: typedef typename Traits::iterator_category iterator_category; typedef Iterator iterator_type; + enum { is_input_or_output_iter = + boost::is_convertible::value + || boost::is_convertible::value }; + // Iterators should satisfy one of the known categories - BOOST_STATIC_ASSERT((boost::is_convertible::value - || boost::is_convertible::value)); + BOOST_STATIC_ASSERT(is_input_or_output_iter); // Iterators >= ForwardIterator must produce real references. - BOOST_STATIC_ASSERT((!boost::is_convertible::value - || boost::is_same::value - || boost::is_same::value)); + enum { forward_iter_with_real_reference = + (!boost::is_convertible::value + || boost::is_same::value + || boost::is_same::value) }; + BOOST_STATIC_ASSERT(forward_iter_with_real_reference); iterator_adaptor() { } @@ -566,30 +583,22 @@ struct transform_iterator_policies : public default_iterator_policies 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 std::input_iterator_tag iterator_category; -}; - -template - > -struct transform_iterator_generator +template +class transform_iterator_generator { - typedef transform_iterator_traits - transform_traits; + typedef typename boost::detail::iterator_traits::difference_type + difference_type; + typedef typename AdaptableUnaryFunction::result_type value_type; +public: + typedef boost::iterator transform_traits; typedef iterator_adaptor, transform_traits> type; }; template -typename transform_iterator_generator::type +inline typename transform_iterator_generator::type make_transform_iterator( const Iterator& base, const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) @@ -620,52 +629,44 @@ struct indirect_iterator_policies : public default_iterator_policies { return **x; } }; -template ::value_type, - class InnerTraits = boost::detail::iterator_traits, - class OuterTraits = boost::detail::iterator_traits // never needed (?) - > -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 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 + class InnerTraits = boost::detail::iterator_traits + > +class indirect_iterator_generator { - typedef iterator_adaptor - > type; + typedef boost::detail::iterator_traits OuterTraits; + typedef typename OuterTraits::difference_type difference_type; + typedef typename OuterTraits::iterator_category iterator_category; + + typedef typename InnerTraits::value_type value_type; + typedef typename InnerTraits::pointer pointer; + typedef typename InnerTraits::reference reference; +public: + typedef boost::iterator indirect_traits; + typedef iterator_adaptor type; }; -template , - 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 +template +inline typename indirect_iterator_generator::type +make_indirect_iterator(OuterIterator outer, InnerIterator, InnerTraits) { - typedef iterator_adaptor, - indirect_iterator_policies> iterator; - - typedef iterator_adaptor, - indirect_iterator_policies> const_iterator; -}; + typedef typename indirect_iterator_generator + ::type result_t; + return result_t(outer); +} + +#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) +template +inline typename indirect_iterator_generator::type +make_indirect_iterator(OuterIterator outer) +{ + typedef typename indirect_iterator_generator + ::type result_t; + return result_t(outer); +} +#endif //============================================================================= @@ -712,14 +713,23 @@ struct reverse_iterator_generator Traits> type; }; -template - > -struct const_reverse_iterator_generator +template +inline typename reverse_iterator_generator::type +make_reverse_iterator(Iterator iter, Traits) { - typedef iterator_adaptor type; -}; + typedef typename reverse_iterator_generator::type result_t; + return result_t(iter); +} + +#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) +template +inline typename reverse_iterator_generator::type +make_reverse_iterator(Iterator iter) +{ + typedef typename reverse_iterator_generator::type result_t; + return result_t(iter); +} +#endif //============================================================================= // Projection Iterators Adaptor @@ -738,101 +748,119 @@ struct projection_iterator_policies : public default_iterator_policies AdaptableUnaryFunction m_f; }; -template -struct projection_iterator_traits { +template +class projection_iterator_generator { + typedef boost::detail::iterator_traits 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 - > -struct projection_iterator_generator { - typedef projection_iterator_traits + typedef boost::iterator projection_traits; +public: typedef iterator_adaptor, + projection_iterator_policies, projection_traits> type; }; -template - > -struct const_projection_iterator_generator { - typedef const_projection_iterator_traits projection_traits; +template +class const_projection_iterator_generator { + typedef boost::detail::iterator_traits Traits; + typedef typename AdaptableUnaryFunction::result_type value_type; + typedef boost::iterator + projection_traits; +public: typedef iterator_adaptor, + projection_iterator_policies, projection_traits> type; }; -template , - class ConstTraits = boost::detail::iterator_traits - > +template struct projection_iterator_pair_generator { - typedef projection_iterator_traits - projection_traits; - typedef const_projection_iterator_traits const_projection_traits; - typedef iterator_adaptor, - projection_traits> iterator; - typedef iterator_adaptor, - const_projection_traits > const_iterator; + typedef typename projection_iterator_generator::type iterator; + typedef typename const_projection_iterator_generator::type const_iterator; }; + +template +inline typename projection_iterator_generator::type +make_projection_iterator(Iterator iter, AdaptableUnaryFunction f) +{ + typedef typename projection_iterator_generator::type result_t; + return result_t(iter, f); +} + +template +inline typename const_projection_iterator_generator::type +make_const_projection_iterator(Iterator iter, AdaptableUnaryFunction f) +{ + typedef typename const_projection_iterator_generator::type result_t; + return result_t(iter, f); +} + //============================================================================= // Filter Iterator Adaptor - template - class filter_iterator_policies : public default_iterator_policies { - public: +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) { } + : m_predicate(p), m_end(end) { } void initialize(Iterator& x) { - advance(x); + advance(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); + ++x; + advance(x); } - private: +private: void advance(Iterator& iter) { - while (m_end != iter && !m_predicate(*iter)) - ++iter; + while (m_end != iter && !m_predicate(*iter)) + ++iter; } Predicate m_predicate; Iterator m_end; - }; - - template - > - class filter_iterator_generator { +}; + +template + > +class filter_iterator_generator { typedef filter_iterator_policies Policies; - public: +public: + typedef filter_iterator_policies policies_type; typedef iterator_adaptor type; - }; +}; + + +template +inline typename filter_iterator_generator::type +make_filter_iterator(Iterator first, Iterator last, Predicate p, Traits) +{ + typedef filter_iterator_generator Gen; + typedef typename Gen::policies_type policies_t; + typedef typename Gen::type result_t; + return result_t(first, policies_t(p, last)); +} + +#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) +template +inline typename filter_iterator_generator::type +make_filter_iterator(Iterator first, Iterator last, Predicate p) +{ + typedef filter_iterator_generator Gen; + typedef typename Gen::policies_type policies_t; + typedef typename Gen::type result_t; + return result_t(first, policies_t(p, last)); +} +#endif } // namespace boost From edf17ba001c4705fe53b21b411a19f3c95b96db2 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 8 Feb 2001 03:41:23 +0000 Subject: [PATCH 061/265] put indirect_iterator_pair_generator back in [SVN r9027] --- include/boost/iterator_adaptors.hpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 3ab25fb..71c5759 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -13,8 +13,7 @@ // Revision History: // 07 Feb 2001 Jeremy Siek -// Removed all pair generator's except for projection and -// some const adaptor generators. +// Removed some const iterator adaptor generators. // // Added make_xxx_iterator() helper functions for remaining // iterator adaptors. @@ -335,7 +334,7 @@ namespace detail { typedef operator_arrow_proxy proxy; typedef typename Traits::pointer pointer; enum { is_input_iter = boost::is_convertible::value - & !boost::is_convertible::value }; + & !boost::is_convertible::value }; typedef typename boost::detail::if_true<(is_input_iter)>::template then< proxy, @@ -648,6 +647,20 @@ public: typedef iterator_adaptor type; }; +template , + class InnerIterator = typename boost::detail::iterator_traits::value_type, + class InnerTraits = boost::detail::iterator_traits + > +struct indirect_iterator_pair_generator +{ + typedef typename indirect_iterator_generator::type iterator; + typedef typename indirect_iterator_generator::type const_iterator; +}; + template inline typename indirect_iterator_generator::type make_indirect_iterator(OuterIterator outer, InnerIterator, InnerTraits) @@ -830,8 +843,8 @@ private: }; template - > + class Traits = boost::detail::iterator_traits + > class filter_iterator_generator { typedef filter_iterator_policies Policies; public: From b05b38810ce77a1dc738be16d193fee430c0e916 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 8 Feb 2001 04:45:18 +0000 Subject: [PATCH 062/265] just whitespace [SVN r9030] --- include/boost/iterator_adaptors.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 71c5759..f8b3659 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -333,8 +333,10 @@ namespace detail { typedef typename Traits::iterator_category category; typedef operator_arrow_proxy proxy; typedef typename Traits::pointer pointer; + enum { is_input_iter = boost::is_convertible::value & !boost::is_convertible::value }; + typedef typename boost::detail::if_true<(is_input_iter)>::template then< proxy, From bafe0703a6691ecb52cede4bbf77ee7992b04f75 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 9 Feb 2001 03:27:40 +0000 Subject: [PATCH 063/265] Beginning of a failed attempt to appease Borland [SVN r9041] --- include/boost/counting_iterator.hpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index 1580756..f4795fd 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -28,6 +28,8 @@ // Incrementable. // // Revision History +// 08 Feb 2001 Beginning of a failed attempt to appease Borland +// (David Abrahams) // 07 Feb 2001 rename counting_iterator() -> make_counting_iterator() // (David Abrahams) // 04 Feb 2001 Added counting_iterator_generator; updated comments @@ -136,16 +138,19 @@ namespace detail { template struct counting_iterator_traits { private: - typedef typename detail::counting_iterator_traits_select<( + enum { + is_numeric = #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS std::numeric_limits::is_specialized #else - // Causes warnings with GCC, but how else can I detect numeric types at - // compile-time? - (boost::is_convertible::value && - boost::is_convertible::value) + // Try to detect numeric types at compile time + boost::is_convertible::value + && boost::is_convertible::value #endif - )>::template traits traits; + }; + + typedef typename detail::counting_iterator_traits_select< + is_numeric>::template traits traits; public: typedef Incrementable value_type; typedef const Incrementable& reference; From 8496571204333aacd0d6517418fefa78f216ce26 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 9 Feb 2001 03:29:11 +0000 Subject: [PATCH 064/265] Fold in Jeremy's improvement to make_reverse_iterator [SVN r9042] --- include/boost/iterator_adaptors.hpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index f8b3659..815e219 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -728,23 +728,24 @@ struct reverse_iterator_generator Traits> type; }; -template -inline typename reverse_iterator_generator::type -make_reverse_iterator(Iterator iter, Traits) -{ - typedef typename reverse_iterator_generator::type result_t; - return result_t(iter); -} - -#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) template inline typename reverse_iterator_generator::type -make_reverse_iterator(Iterator iter) +make_reverse_iterator(Iterator base) { typedef typename reverse_iterator_generator::type result_t; - return result_t(iter); + return result_t(base); +} + +// Specify Traits type with an explicit argument, +// i.e., make_reverse_iterator(base) + +template +inline typename reverse_iterator_generator::type +make_reverse_iterator(Iterator base, Traits* = 0) +{ + typedef typename reverse_iterator_generator::type result_t; + return result_t(base); } -#endif //============================================================================= // Projection Iterators Adaptor From 8a73dcd0526a6e8e797a47696eb3671ccfe96378 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 9 Feb 2001 04:29:11 +0000 Subject: [PATCH 065/265] Fixed bidirectional iterator test so that --i is no longer a precondition. [SVN r9048] --- include/boost/pending/iterator_tests.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp index 9bde614..3abdccc 100644 --- a/include/boost/pending/iterator_tests.hpp +++ b/include/boost/pending/iterator_tests.hpp @@ -5,6 +5,9 @@ // test suite for STL concepts such as iterators and containers. // // Revision History: +// 08 Feb 2001 Fixed bidirectional iterator test so that +// --i is no longer a precondition. +// (Jeremy Siek) // 04 Feb 2001 Added lvalue test, corrected preconditions // (David Abrahams) @@ -125,7 +128,7 @@ void forward_iterator_test(Iterator i, T v1, T v2) #endif } -// Preconditions: *i == v1, *++i == v2, --i +// Preconditions: *i == v1, *++i == v2 template void bidirectional_iterator_test(Iterator i, T v1, T v2) { @@ -143,8 +146,8 @@ void bidirectional_iterator_test(Iterator i, T v1, T v2) --i; assert(i == i1); assert(i == i2); - --i1; - --i2; + ++i1; + ++i2; trivial_iterator_test(i, i1, v1); trivial_iterator_test(i, i2, v1); @@ -152,7 +155,7 @@ void bidirectional_iterator_test(Iterator i, T v1, T v2) // mutable_bidirectional_iterator_test -// Preconditions: [i-1,i+N) is a valid range +// Preconditions: [i,i+N) is a valid range template void random_access_iterator_test(Iterator i, int N, TrueVals vals) { From a94c9d0db2d15b64eda66deeb5b74ccbb46ca77e Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 9 Feb 2001 05:26:01 +0000 Subject: [PATCH 066/265] Added iterator constructor to allow const adaptor from non-const adaptee. Changed make_xxx to pass iterators by-value to get arrays converted to pointers. Removed InnerIterator template parameter from indirect_iterator_generator. Rearranged parameters for make_filter_iterator [SVN r9050] --- include/boost/iterator_adaptors.hpp | 111 +++++++++++++++++++--------- 1 file changed, 76 insertions(+), 35 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 815e219..5a5cfc8 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,18 @@ // // Revision History: +// 09 Feb 2001 Jeremy Siek +// Added iterator constructor to allow const adaptor +// from non-const adaptee. +// +// Changed make_xxx to pass iterators by-value to +// get arrays converted to pointers. +// +// Removed InnerIterator template parameter from +// indirect_iterator_generator. +// +// Rearranged parameters for make_filter_iterator +// // 07 Feb 2001 Jeremy Siek // Removed some const iterator adaptor generators. // @@ -416,6 +428,13 @@ public: policies().initialize(iter()); } + // To allow construction of const adaptor from non-const adaptee. + template + iterator_adaptor(const OtherIterator& it, const Policies& p = Policies()) + : m_iter_p(it, p) { + policies().initialize(iter()); + } + template iterator_adaptor (const iterator_adaptor& src) @@ -601,7 +620,7 @@ public: template inline typename transform_iterator_generator::type make_transform_iterator( - const Iterator& base, + Iterator base, const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) { typedef typename transform_iterator_generator::type result_t; @@ -631,9 +650,9 @@ struct indirect_iterator_policies : public default_iterator_policies }; template mutable indirect iterator; Immutable -> immutable indirect iterator - class InnerIterator = typename boost::detail::iterator_traits::value_type, - class InnerTraits = boost::detail::iterator_traits + // Mutable reference and pointer type in traits class -> mutable indirect iterator; + // Immutable reference and pointer type in traits class -> immutable indirect iterator + class InnerTraits = boost::detail::iterator_traits::value_type> > class indirect_iterator_generator { @@ -652,36 +671,38 @@ public: template , - class InnerIterator = typename boost::detail::iterator_traits::value_type, - class InnerTraits = boost::detail::iterator_traits + class InnerTraits = boost::detail::iterator_traits::value_type> > struct indirect_iterator_pair_generator { typedef typename indirect_iterator_generator::type iterator; + InnerTraits>::type iterator; typedef typename indirect_iterator_generator::type const_iterator; + ConstInnerTraits>::type const_iterator; }; -template -inline typename indirect_iterator_generator::type -make_indirect_iterator(OuterIterator outer, InnerIterator, InnerTraits) -{ - typedef typename indirect_iterator_generator - ::type result_t; - return result_t(outer); -} - -#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) +// WARNING: Do not use the one argument version of +// make_indirect_iterator() if the iterator is a builtin pointer type +// and if your compiler does not support partial specialization. template inline typename indirect_iterator_generator::type -make_indirect_iterator(OuterIterator outer) +make_indirect_iterator(OuterIterator base) { typedef typename indirect_iterator_generator ::type result_t; - return result_t(outer); + return result_t(base); +} + +// Tried to allow InnerTraits to be provided by explicit template +// argument to the function, but could not get it to work. -Jeremy Siek +template +inline typename indirect_iterator_generator::type +make_indirect_iterator(OuterIterator base, InnerTraits) +{ + typedef typename indirect_iterator_generator + ::type result_t; + return result_t(base); } -#endif //============================================================================= @@ -728,6 +749,10 @@ struct reverse_iterator_generator Traits> type; }; +// WARNING: Do not use the one template parameter version of +// make_reverse_iterator() if the iterator is a builtin pointer type +// and if your compiler does not support partial specialization. + template inline typename reverse_iterator_generator::type make_reverse_iterator(Iterator base) @@ -747,6 +772,7 @@ make_reverse_iterator(Iterator base, Traits* = 0) return result_t(base); } + //============================================================================= // Projection Iterators Adaptor @@ -799,7 +825,9 @@ struct projection_iterator_pair_generator { template inline typename projection_iterator_generator::type -make_projection_iterator(Iterator iter, AdaptableUnaryFunction f) +make_projection_iterator( + Iterator iter, + const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) { typedef typename projection_iterator_generator::type result_t; return result_t(iter, f); @@ -807,7 +835,9 @@ make_projection_iterator(Iterator iter, AdaptableUnaryFunction f) template inline typename const_projection_iterator_generator::type -make_const_projection_iterator(Iterator iter, AdaptableUnaryFunction f) +make_const_projection_iterator( + Iterator iter, + const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) { typedef typename const_projection_iterator_generator::type result_t; return result_t(iter, f); @@ -856,27 +886,38 @@ public: }; -template -inline typename filter_iterator_generator::type -make_filter_iterator(Iterator first, Iterator last, Predicate p, Traits) -{ - typedef filter_iterator_generator Gen; - typedef typename Gen::policies_type policies_t; - typedef typename Gen::type result_t; - return result_t(first, policies_t(p, last)); -} +// WARNING: Do not use this three argument version of +// make_filter_iterator() if the iterator is a builtin pointer type +// and if your compiler does not support partial specialization. -#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) +// If the Predicate argument "p" is left out, an explicit template +// argument for the Predicate is required, i.e., +// make_filter_iterator(f, l). template inline typename filter_iterator_generator::type -make_filter_iterator(Iterator first, Iterator last, Predicate p) +make_filter_iterator(Iterator first, Iterator last, const Predicate& p = Predicate()) { typedef filter_iterator_generator Gen; typedef typename Gen::policies_type policies_t; typedef typename Gen::type result_t; return result_t(first, policies_t(p, last)); } -#endif + +// Supply the Traits type via an exaplicit template argument, i.e., +// make_filter_iterator(f, l). +// +// If the Predicate argument "p" is left out, an explicit template +// argument for the Predicate is also required, i.e., +// make_filter_iterator(f, l). +template +inline typename filter_iterator_generator::type +make_filter_iterator(Iterator first, Iterator last, const Predicate& p = Predicate(), Traits* = 0) +{ + typedef filter_iterator_generator Gen; + typedef typename Gen::policies_type policies_t; + typedef typename Gen::type result_t; + return result_t(first, policies_t(p, last)); +} } // namespace boost From 86e183c75e79a51cf2c02128f912ac4e089ea01d Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 9 Feb 2001 05:44:13 +0000 Subject: [PATCH 067/265] MSVC porting [SVN r9052] --- include/boost/iterator_adaptors.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 5a5cfc8..b99b425 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -428,12 +428,15 @@ public: policies().initialize(iter()); } +#ifndef BOOST_MSVC // To allow construction of const adaptor from non-const adaptee. + // However, when this is defined MSVC gives ambiguous error. template iterator_adaptor(const OtherIterator& it, const Policies& p = Policies()) : m_iter_p(it, p) { policies().initialize(iter()); } +#endif template iterator_adaptor (const iterator_adaptor::type const_iterator; }; -// WARNING: Do not use the one argument version of -// make_indirect_iterator() if the iterator is a builtin pointer type -// and if your compiler does not support partial specialization. +#ifndef BOOST_NO_STD_ITERATOR_TRAITS template inline typename indirect_iterator_generator::type make_indirect_iterator(OuterIterator base) @@ -692,6 +693,7 @@ make_indirect_iterator(OuterIterator base) ::type result_t; return result_t(base); } +#endif // Tried to allow InnerTraits to be provided by explicit template // argument to the function, but could not get it to work. -Jeremy Siek From 8174963a451e60f6ed566e893950c677c29fe8e9 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 9 Feb 2001 15:17:17 +0000 Subject: [PATCH 068/265] Rolled back Jeremy's new constructor for now; it was causing problems with counting_iterator_test Attempted fix for Borland [SVN r9055] --- include/boost/iterator_adaptors.hpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index b99b425..d9111c8 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,12 @@ // // Revision History: +// 09 Feb 2001 David Abrahams +// Rolled back Jeremy's new constructor for now; it was causing +// problems with counting_iterator_test +// +// Attempted fix for Borland +// // 09 Feb 2001 Jeremy Siek // Added iterator constructor to allow const adaptor // from non-const adaptee. @@ -408,8 +414,8 @@ public: typedef Iterator iterator_type; enum { is_input_or_output_iter = - boost::is_convertible::value - || boost::is_convertible::value }; + boost::is_convertible::value + || boost::is_convertible::value }; // Iterators should satisfy one of the known categories BOOST_STATIC_ASSERT(is_input_or_output_iter); @@ -428,7 +434,7 @@ public: policies().initialize(iter()); } -#ifndef BOOST_MSVC +#if 0 // ndef BOOST_MSVC // To allow construction of const adaptor from non-const adaptee. // However, when this is defined MSVC gives ambiguous error. template From 490bee3a0636677c137dcc2354c017eff23be21e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 9 Feb 2001 15:21:02 +0000 Subject: [PATCH 069/265] Factored out is_numeric computation. Borland still unhappy :( [SVN r9057] --- include/boost/counting_iterator.hpp | 48 +++++++++++++++-------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index f4795fd..3a8762e 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -28,6 +28,8 @@ // Incrementable. // // Revision History +// 09 Feb 2001 Factored out is_numeric computation. Borland still +// unhappy :( (David Abrahams) // 08 Feb 2001 Beginning of a failed attempt to appease Borland // (David Abrahams) // 07 Feb 2001 rename counting_iterator() -> make_counting_iterator() @@ -117,20 +119,29 @@ namespace detail { }; }; + // Try to detect numeric types at compile time in ways compatible with the + // limitations of the compiler and library. + template + struct is_numeric { + enum { value = +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + std::numeric_limits::is_specialized +#elif defined(__BORLANDC__) + ::boost::is_integral::value || ::boost::is_same::value +#else + boost::is_convertible::value && boost::is_convertible::value +#endif + }; + }; + // Compute the distance over arbitrary numeric and/or iterator types template Distance any_distance(Incrementable start, Incrementable finish, Distance* = 0) { - return distance_policy_select< -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - std::numeric_limits::is_specialized -#else - // Causes warnings with GCC, but how else can I detect numeric types - // at compile-time? - (boost::is_convertible::value && - boost::is_convertible::value) -#endif - >::template policy::distance(start, finish); + + return distance_policy_select<( + is_numeric::value)>::template + policy::distance(start, finish); } } // namespace detail @@ -138,19 +149,10 @@ namespace detail { template struct counting_iterator_traits { private: - enum { - is_numeric = -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - std::numeric_limits::is_specialized -#else - // Try to detect numeric types at compile time - boost::is_convertible::value - && boost::is_convertible::value -#endif - }; - - typedef typename detail::counting_iterator_traits_select< - is_numeric>::template traits traits; + enum {numeric = detail::is_numeric::value }; + typedef typename detail::counting_iterator_traits_select<( + numeric + )>::template traits traits; public: typedef Incrementable value_type; typedef const Incrementable& reference; From 5bfc03ed4ac23a8509870decddc67d3ca2bf89c7 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 9 Feb 2001 15:43:57 +0000 Subject: [PATCH 070/265] Cleaned up redundant test is_integral || is_same -> is_integral [SVN r9059] --- include/boost/counting_iterator.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index 3a8762e..7e67049 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -47,6 +47,7 @@ # include # include # include +# include # ifndef BOOST_NO_LIMITS # include # endif @@ -123,11 +124,13 @@ namespace detail { // limitations of the compiler and library. template struct is_numeric { + // For a while, this wasn't true, but we rely on it below. This is a regression assert. + BOOST_STATIC_ASSERT(::boost::is_integral::value); enum { value = #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS std::numeric_limits::is_specialized #elif defined(__BORLANDC__) - ::boost::is_integral::value || ::boost::is_same::value + ::boost::is_integral::value #else boost::is_convertible::value && boost::is_convertible::value #endif From bfda34e9e0ea23ea3916e1b3cf541b8016bf5e26 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 9 Feb 2001 19:26:19 +0000 Subject: [PATCH 071/265] try a better interface to indirect iterators [SVN r9060] --- include/boost/iterator_adaptors.hpp | 93 ++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 16 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index d9111c8..d5644b4 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -658,39 +658,100 @@ struct indirect_iterator_policies : public default_iterator_policies { return **x; } }; +// This macro definition is only temporary in this file +# if !defined(BOOST_MSVC) +# define BOOST_ARG_DEPENDENT_TYPENAME typename +# else +# define BOOST_ARG_DEPENDENT_TYPENAME +# endif + +namespace detail { +#if !defined(BOOST_MSVC) + template + struct value_type_of_value_type { + typedef typename boost::detail::iterator_traits::value_type outer_value; + typedef typename boost::detail::iterator_traits::value_type type; + }; +#else // Even this workaround doesn't fly :( + template + struct inner_traits_select { + template + struct rebind { + struct traits { + typedef typename boost::remove_const::type value_type; + typedef Pointer pointer; + typedef Reference reference; + }; + }; + }; + + struct no_value_type {}; + template <> + struct inner_traits_select { + template + struct rebind { + typedef typename boost::detail::iterator_traits::value_type outer_value; + typedef typename boost::detail::iterator_traits traits; + }; + }; +#endif +} + template mutable indirect iterator; - // Immutable reference and pointer type in traits class -> immutable indirect iterator - class InnerTraits = boost::detail::iterator_traits::value_type> + class Value = +#if !defined(BOOST_MSVC) + BOOST_ARG_DEPENDENT_TYPENAME detail::value_type_of_value_type::type, +#else + detail::no_value_type, +#endif + class Pointer = Value*, + class Reference = Value& > class indirect_iterator_generator { - typedef boost::detail::iterator_traits OuterTraits; - typedef typename OuterTraits::difference_type difference_type; - typedef typename OuterTraits::iterator_category iterator_category; + typedef boost::detail::iterator_traits outer_traits; + typedef typename outer_traits::difference_type difference_type; + typedef typename outer_traits::iterator_category iterator_category; - typedef typename InnerTraits::value_type value_type; - typedef typename InnerTraits::pointer pointer; - typedef typename InnerTraits::reference reference; +#if !defined(BOOST_MSVC) + typedef typename boost::remove_const::type value_type; + typedef Pointer pointer; + typedef Reference reference; +#else + typedef detail::inner_traits_select::template + rebind inner_traits; + typedef typename inner_traits::value_type value_type; + typedef typename inner_traits::pointer pointer; + typedef typename inner_traits::reference reference; +#endif public: typedef boost::iterator indirect_traits; typedef iterator_adaptor type; }; template , - class InnerTraits = boost::detail::iterator_traits::value_type> + class Value = +#if !defined(BOOST_MSVC) + BOOST_ARG_DEPENDENT_TYPENAME detail::value_type_of_value_type::type, +#else + detail::no_value_type, +#endif + class Pointer = Value*, + class Reference = Value&, + class ConstPointer = const Value*, + class ConstReference = const Value& > struct indirect_iterator_pair_generator { typedef typename indirect_iterator_generator::type iterator; + Value, Pointer, Reference>::type iterator; typedef typename indirect_iterator_generator::type const_iterator; + Value, ConstPointer, ConstReference>::type const_iterator; }; -#ifndef BOOST_NO_STD_ITERATOR_TRAITS +# undef BOOST_ARG_DEPENDENT_TYPENAME + +# ifndef BOOST_NO_STD_ITERATOR_TRAITS template inline typename indirect_iterator_generator::type make_indirect_iterator(OuterIterator base) @@ -699,7 +760,7 @@ make_indirect_iterator(OuterIterator base) ::type result_t; return result_t(base); } -#endif +# endif // Tried to allow InnerTraits to be provided by explicit template // argument to the function, but could not get it to work. -Jeremy Siek From 6f90982a45349fb60f134f0330f9b5316218aa8b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 9 Feb 2001 21:04:09 +0000 Subject: [PATCH 072/265] roll back mistaken changes [SVN r9062] --- include/boost/iterator_adaptors.hpp | 93 +++++------------------------ 1 file changed, 16 insertions(+), 77 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index d5644b4..d9111c8 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -658,100 +658,39 @@ struct indirect_iterator_policies : public default_iterator_policies { return **x; } }; -// This macro definition is only temporary in this file -# if !defined(BOOST_MSVC) -# define BOOST_ARG_DEPENDENT_TYPENAME typename -# else -# define BOOST_ARG_DEPENDENT_TYPENAME -# endif - -namespace detail { -#if !defined(BOOST_MSVC) - template - struct value_type_of_value_type { - typedef typename boost::detail::iterator_traits::value_type outer_value; - typedef typename boost::detail::iterator_traits::value_type type; - }; -#else // Even this workaround doesn't fly :( - template - struct inner_traits_select { - template - struct rebind { - struct traits { - typedef typename boost::remove_const::type value_type; - typedef Pointer pointer; - typedef Reference reference; - }; - }; - }; - - struct no_value_type {}; - template <> - struct inner_traits_select { - template - struct rebind { - typedef typename boost::detail::iterator_traits::value_type outer_value; - typedef typename boost::detail::iterator_traits traits; - }; - }; -#endif -} - template ::type, -#else - detail::no_value_type, -#endif - class Pointer = Value*, - class Reference = Value& + // Mutable reference and pointer type in traits class -> mutable indirect iterator; + // Immutable reference and pointer type in traits class -> immutable indirect iterator + class InnerTraits = boost::detail::iterator_traits::value_type> > class indirect_iterator_generator { - typedef boost::detail::iterator_traits outer_traits; - typedef typename outer_traits::difference_type difference_type; - typedef typename outer_traits::iterator_category iterator_category; + typedef boost::detail::iterator_traits OuterTraits; + typedef typename OuterTraits::difference_type difference_type; + typedef typename OuterTraits::iterator_category iterator_category; -#if !defined(BOOST_MSVC) - typedef typename boost::remove_const::type value_type; - typedef Pointer pointer; - typedef Reference reference; -#else - typedef detail::inner_traits_select::template - rebind inner_traits; - typedef typename inner_traits::value_type value_type; - typedef typename inner_traits::pointer pointer; - typedef typename inner_traits::reference reference; -#endif + typedef typename InnerTraits::value_type value_type; + typedef typename InnerTraits::pointer pointer; + typedef typename InnerTraits::reference reference; public: typedef boost::iterator indirect_traits; typedef iterator_adaptor type; }; template ::type, -#else - detail::no_value_type, -#endif - class Pointer = Value*, - class Reference = Value&, - class ConstPointer = const Value*, - class ConstReference = const Value& + class ConstInnerIterator, // Immutable + class ConstInnerTraits = boost::detail::iterator_traits, + class InnerTraits = boost::detail::iterator_traits::value_type> > struct indirect_iterator_pair_generator { typedef typename indirect_iterator_generator::type iterator; + InnerTraits>::type iterator; typedef typename indirect_iterator_generator::type const_iterator; + ConstInnerTraits>::type const_iterator; }; -# undef BOOST_ARG_DEPENDENT_TYPENAME - -# ifndef BOOST_NO_STD_ITERATOR_TRAITS +#ifndef BOOST_NO_STD_ITERATOR_TRAITS template inline typename indirect_iterator_generator::type make_indirect_iterator(OuterIterator base) @@ -760,7 +699,7 @@ make_indirect_iterator(OuterIterator base) ::type result_t; return result_t(base); } -# endif +#endif // Tried to allow InnerTraits to be provided by explicit template // argument to the function, but could not get it to work. -Jeremy Siek From 15b5b6677663b80912c387fdb2f0e7aac5ce343f Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 10 Feb 2001 00:26:55 +0000 Subject: [PATCH 073/265] Improved interface to indirect_ and reverse_ iterators [SVN r9065] --- include/boost/iterator_adaptors.hpp | 159 +++++++++++++++++++++------- 1 file changed, 121 insertions(+), 38 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index d9111c8..30e88a2 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -13,6 +13,8 @@ // Revision History: // 09 Feb 2001 David Abrahams +// Improved interface to indirect_ and reverse_ iterators +// // Rolled back Jeremy's new constructor for now; it was causing // problems with counting_iterator_test // @@ -658,39 +660,77 @@ struct indirect_iterator_policies : public default_iterator_policies { return **x; } }; +// This macro definition is only temporary in this file +# if !defined(BOOST_MSVC) +# define BOOST_ARG_DEPENDENT_TYPENAME typename +# else +# define BOOST_ARG_DEPENDENT_TYPENAME +# endif + +} template struct undefined; namespace boost { + +namespace detail { +# if !defined(BOOST_MSVC) // stragely instantiated even when unused! Maybe try a recursive template someday ;-) + template + struct value_type_of_value_type { + typedef typename boost::detail::iterator_traits::value_type outer_value; + typedef typename boost::detail::iterator_traits::value_type type; + }; +# endif +} + template mutable indirect iterator; - // Immutable reference and pointer type in traits class -> immutable indirect iterator - class InnerTraits = boost::detail::iterator_traits::value_type> + class Value +#if !defined(BOOST_MSVC) + = BOOST_ARG_DEPENDENT_TYPENAME detail::value_type_of_value_type::type +#endif + , class Pointer = Value* + , class Reference = Value& > class indirect_iterator_generator { - typedef boost::detail::iterator_traits OuterTraits; - typedef typename OuterTraits::difference_type difference_type; - typedef typename OuterTraits::iterator_category iterator_category; + typedef boost::detail::iterator_traits outer_traits; + typedef typename outer_traits::difference_type difference_type; + typedef typename outer_traits::iterator_category iterator_category; - typedef typename InnerTraits::value_type value_type; - typedef typename InnerTraits::pointer pointer; - typedef typename InnerTraits::reference reference; + typedef typename boost::remove_const::type value_type; + typedef Pointer pointer; + typedef Reference reference; public: typedef boost::iterator indirect_traits; typedef iterator_adaptor type; }; template , - class InnerTraits = boost::detail::iterator_traits::value_type> + class Value +#if !defined(BOOST_MSVC) + = BOOST_ARG_DEPENDENT_TYPENAME detail::value_type_of_value_type::type +#endif + , class Pointer = Value* + , class Reference = Value& + , class ConstPointer = const Value* + , class ConstReference = const Value& > struct indirect_iterator_pair_generator { typedef typename indirect_iterator_generator::type iterator; + Value, Pointer, Reference>::type iterator; typedef typename indirect_iterator_generator::type const_iterator; + Value, ConstPointer, ConstReference>::type const_iterator; }; -#ifndef BOOST_NO_STD_ITERATOR_TRAITS +// Tried to allow InnerTraits to be provided by explicit template +// argument to the function, but could not get it to work. -Jeremy Siek +template +inline typename indirect_iterator_generator::type +make_indirect_iterator(OuterIterator base, Value* = 0) +{ + typedef typename indirect_iterator_generator + ::type result_t; + return result_t(base); +} + +# if 0 // This just doesn't seem to work under any circumstances! template inline typename indirect_iterator_generator::type make_indirect_iterator(OuterIterator base) @@ -699,18 +739,7 @@ make_indirect_iterator(OuterIterator base) ::type result_t; return result_t(base); } -#endif - -// Tried to allow InnerTraits to be provided by explicit template -// argument to the function, but could not get it to work. -Jeremy Siek -template -inline typename indirect_iterator_generator::type -make_indirect_iterator(OuterIterator base, InnerTraits) -{ - typedef typename indirect_iterator_generator - ::type result_t; - return result_t(base); -} +# endif //============================================================================= @@ -757,10 +786,6 @@ struct reverse_iterator_generator Traits> type; }; -// WARNING: Do not use the one template parameter version of -// make_reverse_iterator() if the iterator is a builtin pointer type -// and if your compiler does not support partial specialization. - template inline typename reverse_iterator_generator::type make_reverse_iterator(Iterator base) @@ -769,17 +794,73 @@ make_reverse_iterator(Iterator base) return result_t(base); } -// Specify Traits type with an explicit argument, -// i.e., make_reverse_iterator(base) +template struct undefined; -template -inline typename reverse_iterator_generator::type -make_reverse_iterator(Iterator base, Traits* = 0) +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace detail { + template + struct iterator_defaults_select + { + template + struct traits + { + typedef typename boost::detail::iterator_traits::value_type value_type; + typedef typename boost::detail::iterator_traits::pointer pointer; + typedef typename boost::detail::iterator_traits::reference reference; + }; + }; + + template <> + struct iterator_defaults_select + { + template + struct traits + { + typedef Value value_type; + typedef Value* pointer; + typedef Value& reference; + }; + }; + + template + struct iterator_defaults + { + enum { is_ptr = boost::is_pointer::value }; + typedef iterator_defaults_select::template traits traits; + typedef typename traits::pointer pointer; + typedef typename traits::reference reference; + }; +} +#endif + +template ::value_type, +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::pointer, + class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::reference, +#else + class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, + class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, +#endif + class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category, + class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type + > +struct reverse_iterator_generator2 { - typedef typename reverse_iterator_generator::type result_t; + typedef typename boost::remove_const::type value_type; + typedef typename boost::iterator traits; + typedef iterator_adaptor type; +}; + +//#ifndef BOOST_MSVC +template +inline typename reverse_iterator_generator2::type +make_reverse_iterator2(Iterator base) +{ + typedef typename reverse_iterator_generator2::type result_t; return result_t(base); } - +//#endif //============================================================================= // Projection Iterators Adaptor @@ -929,6 +1010,8 @@ make_filter_iterator(Iterator first, Iterator last, const Predicate& p = Predica } // namespace boost +# undef BOOST_ARG_DEPENDENT_TYPENAME + #endif From d7884b56135a9840e06eece9110c125e06e87f7c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 10 Feb 2001 00:35:45 +0000 Subject: [PATCH 074/265] *** empty log message *** [SVN r9066] --- include/boost/iterator_adaptors.hpp | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 30e88a2..d2d902a 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -777,25 +777,6 @@ struct reverse_iterator_policies : public default_iterator_policies { return y < x; } }; -template - > -struct reverse_iterator_generator -{ - typedef iterator_adaptor type; -}; - -template -inline typename reverse_iterator_generator::type -make_reverse_iterator(Iterator base) -{ - typedef typename reverse_iterator_generator::type result_t; - return result_t(base); -} - -template struct undefined; - #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION namespace detail { template @@ -845,22 +826,20 @@ template ::iterator_category, class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type > -struct reverse_iterator_generator2 +struct reverse_iterator_generator { typedef typename boost::remove_const::type value_type; typedef typename boost::iterator traits; typedef iterator_adaptor type; }; -//#ifndef BOOST_MSVC template -inline typename reverse_iterator_generator2::type -make_reverse_iterator2(Iterator base) +inline typename reverse_iterator_generator::type +make_reverse_iterator(Iterator base) { - typedef typename reverse_iterator_generator2::type result_t; + typedef typename reverse_iterator_generator::type result_t; return result_t(base); } -//#endif //============================================================================= // Projection Iterators Adaptor From 51616fa84576ada821fb26291109f1a4f7dbaf5a Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 10 Feb 2001 09:34:19 +0000 Subject: [PATCH 075/265] removed superfluous "typename" [SVN r9068] --- 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 d2d902a..8d27135 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -829,7 +829,7 @@ template ::type value_type; - typedef typename boost::iterator traits; + typedef boost::iterator traits; typedef iterator_adaptor type; }; From e9f24023d40d2c513321bfac701d07f66548d40f Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sat, 10 Feb 2001 17:57:51 +0000 Subject: [PATCH 076/265] completely removed constructor that was #if 0'd [SVN r9076] --- include/boost/iterator_adaptors.hpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 8d27135..fcb5818 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -436,16 +436,6 @@ public: policies().initialize(iter()); } -#if 0 // ndef BOOST_MSVC - // To allow construction of const adaptor from non-const adaptee. - // However, when this is defined MSVC gives ambiguous error. - template - iterator_adaptor(const OtherIterator& it, const Policies& p = Policies()) - : m_iter_p(it, p) { - policies().initialize(iter()); - } -#endif - template iterator_adaptor (const iterator_adaptor& src) From be44a4714bfeb0971894f463c98d980ccb267f22 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 10 Feb 2001 20:22:05 +0000 Subject: [PATCH 077/265] Rolled in supposed Borland fixes from John Maddock, but not seeing any improvement yet Changed argument order to indirect_ generator, for convenience in the case of input iterators (where Reference must be a value type). Removed derivation of filter_iterator_policies from default_iterator_policies, since the iterator category is likely to be reduced (we don't want to allow illegal operations like decrement). Support for a simpler filter iterator interface. [SVN r9092] --- include/boost/iterator_adaptors.hpp | 137 +++++++++++++++++++--------- 1 file changed, 92 insertions(+), 45 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index fcb5818..9a40dd2 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,19 @@ // // Revision History: +// 10 Feb 2001 David Abrahams +// Rolled in supposed Borland fixes from John Maddock, but not seeing any +// improvement yet +// +// Changed argument order to indirect_ generator, for convenience in the +// case of input iterators (where Reference must be a value type). +// +// Removed derivation of filter_iterator_policies from +// default_iterator_policies, since the iterator category is likely to be +// reduced (we don't want to allow illegal operations like decrement). +// +// Support for a simpler filter iterator interface. +// // 09 Feb 2001 David Abrahams // Improved interface to indirect_ and reverse_ iterators // @@ -424,7 +437,7 @@ public: // Iterators >= ForwardIterator must produce real references. enum { forward_iter_with_real_reference = - (!boost::is_convertible::value + (!boost::is_convertible::value || boost::is_same::value || boost::is_same::value) }; BOOST_STATIC_ASSERT(forward_iter_with_real_reference); @@ -657,8 +670,6 @@ struct indirect_iterator_policies : public default_iterator_policies # define BOOST_ARG_DEPENDENT_TYPENAME # endif -} template struct undefined; namespace boost { - namespace detail { # if !defined(BOOST_MSVC) // stragely instantiated even when unused! Maybe try a recursive template someday ;-) template @@ -674,8 +685,8 @@ template ::type #endif - , class Pointer = Value* , class Reference = Value& + , class Pointer = Value* > class indirect_iterator_generator { @@ -704,9 +715,9 @@ template ::type iterator; + Value, Reference, Pointer>::type iterator; typedef typename indirect_iterator_generator::type const_iterator; + Value, ConstReference, ConstPointer>::type const_iterator; }; // Tried to allow InnerTraits to be provided by explicit template @@ -905,7 +916,8 @@ make_const_projection_iterator( // Filter Iterator Adaptor template -class filter_iterator_policies : public default_iterator_policies { +class filter_iterator_policies +{ public: filter_iterator_policies() { } @@ -913,71 +925,106 @@ public: : m_predicate(p), m_end(end) { } void initialize(Iterator& x) { - advance(x); + satisfy_predicate(x); } - // dwa 2/4/01 - The Iter template argument neccessary for compatibility with - // a MWCW bug workaround + // The Iter template argument is neccessary for compatibility with a MWCW + // bug workaround template void increment(Iter& x) { ++x; - advance(x); + satisfy_predicate(x); } -private: - void advance(Iterator& iter) + + template + Reference dereference(type, const Iter& x) const + { return *x; } + + template + bool equal(const Iterator1& x, const Iterator2& y) const + { return x == y; } + + private: + void satisfy_predicate(Iterator& iter) { while (m_end != iter && !m_predicate(*iter)) ++iter; - } + } Predicate m_predicate; Iterator m_end; }; +namespace detail { + // A type generator returning Base if T is derived from Base, and T otherwise. + template + struct reduce_to_base_class + { + typedef typename if_true<( + ::boost::is_convertible::value + )>::template then::type type; + }; + + // "Steps down" the category of iterators below bidirectional so the category + // can be used with filter iterators. + template + struct non_bidirectional_category + { + typedef typename reduce_to_base_class< + std::forward_iterator_tag, + typename iterator_traits::iterator_category + >::type type; + + // For some reason, putting this assertion in filter_iterator_generator fails inexplicably under MSVC + BOOST_STATIC_ASSERT((!boost::is_convertible::value)); + }; +} + template + class Value = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::value_type, +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::pointer, + class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::reference, +#else + class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, + class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, +#endif + class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::non_bidirectional_category::type, + class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type > class filter_iterator_generator { - typedef filter_iterator_policies Policies; -public: - typedef filter_iterator_policies policies_type; - typedef iterator_adaptor type; + typedef typename boost::remove_const::type value_type; + typedef boost::iterator traits; + enum { + is_bidirectional + = boost::is_convertible::value + }; +#ifndef BOOST_MSVC // I don't have any idea why this occurs, but it doesn't seem to hurt too badly. + BOOST_STATIC_ASSERT(!is_bidirectional); +#endif + public: + typedef filter_iterator_policies policies_type; + typedef iterator_adaptor type; }; +// This keeps MSVC happy; it doesn't like to deduce default template arguments +// for template function return types +namespace detail { + template + struct filter_generator { + typedef typename boost::filter_iterator_generator::type type; + }; +} -// WARNING: Do not use this three argument version of -// make_filter_iterator() if the iterator is a builtin pointer type -// and if your compiler does not support partial specialization. - -// If the Predicate argument "p" is left out, an explicit template -// argument for the Predicate is required, i.e., -// make_filter_iterator(f, l). template -inline typename filter_iterator_generator::type +inline typename detail::filter_generator::type make_filter_iterator(Iterator first, Iterator last, const Predicate& p = Predicate()) { typedef filter_iterator_generator Gen; - typedef typename Gen::policies_type policies_t; + typedef filter_iterator_policies policies_t; typedef typename Gen::type result_t; return result_t(first, policies_t(p, last)); } -// Supply the Traits type via an exaplicit template argument, i.e., -// make_filter_iterator(f, l). -// -// If the Predicate argument "p" is left out, an explicit template -// argument for the Predicate is also required, i.e., -// make_filter_iterator(f, l). -template -inline typename filter_iterator_generator::type -make_filter_iterator(Iterator first, Iterator last, const Predicate& p = Predicate(), Traits* = 0) -{ - typedef filter_iterator_generator Gen; - typedef typename Gen::policies_type policies_t; - typedef typename Gen::type result_t; - return result_t(first, policies_t(p, last)); -} - - } // namespace boost # undef BOOST_ARG_DEPENDENT_TYPENAME From dbb99b1cf355ddf5076c968c1c444451840d14a6 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 10 Feb 2001 20:23:35 +0000 Subject: [PATCH 078/265] Rolled in supposed Borland fixes from John Maddock, but not seeing any improvement yet [SVN r9093] --- include/boost/counting_iterator.hpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index 7e67049..08ddae2 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -28,6 +28,8 @@ // Incrementable. // // Revision History +// 10 Feb 2001 Rolled in supposed Borland fixes from John Maddock, but not +// seeing any improvement yet // 09 Feb 2001 Factored out is_numeric computation. Borland still // unhappy :( (David Abrahams) // 08 Feb 2001 Beginning of a failed attempt to appease Borland @@ -60,11 +62,14 @@ namespace detail { // iterator_category and difference_type for a counting_iterator at // compile-time based on whether or not it wraps an integer or an iterator, // using "poor man's partial specialization". - template struct counting_iterator_traits_select; + template struct counting_iterator_traits_select +#ifndef __BORLANDC__ + ; // Incrementable is an iterator type template <> struct counting_iterator_traits_select +#endif { template struct traits @@ -96,11 +101,13 @@ namespace detail { // the iterator wraps an integer or an iterator, using "poor man's partial // specialization". - template struct distance_policy_select; - + template struct distance_policy_select +#ifndef __BORLANDC__ + ; // A policy for wrapped iterators template <> struct distance_policy_select +#endif { template struct policy { @@ -130,7 +137,7 @@ namespace detail { #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS std::numeric_limits::is_specialized #elif defined(__BORLANDC__) - ::boost::is_integral::value + ::boost::is_arithmetic::value #else boost::is_convertible::value && boost::is_convertible::value #endif From c5f24d0d72f4abb037987cdd5b60fdc3d56a6343 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 10 Feb 2001 23:14:42 +0000 Subject: [PATCH 079/265] A baby step that worked. [SVN r9095] --- include/boost/iterator_adaptors.hpp | 106 +++++++++++++++------------- 1 file changed, 57 insertions(+), 49 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 9a40dd2..6f313a6 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -390,8 +390,51 @@ namespace detail { i.policies().decrement(i.iter()); } +# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct iterator_defaults_select + { + template + struct traits + { + typedef typename boost::detail::iterator_traits::value_type value_type; + typedef typename boost::detail::iterator_traits::pointer pointer; + typedef typename boost::detail::iterator_traits::reference reference; + }; + }; + + template <> + struct iterator_defaults_select + { + template + struct traits + { + typedef Value value_type; + typedef Value* pointer; + typedef Value& reference; + }; + }; + + template + struct iterator_defaults + { + enum { is_ptr = boost::is_pointer::value }; + typedef iterator_defaults_select::template traits traits; + typedef typename traits::pointer pointer; + typedef typename traits::reference reference; + }; +# else + template + struct iterator_defaults : iterator_traits + { + typedef typename iterator_traits::pointer pointer; + typedef typename iterator_traits::reference reference; + }; + +# endif } // namespace detail + //============================================================================ //iterator_adaptor - Adapts a generic piece of data as an iterator. Adaptation // is especially easy if the data being adapted is itself an iterator @@ -778,52 +821,10 @@ struct reverse_iterator_policies : public default_iterator_policies { return y < x; } }; -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -namespace detail { - template - struct iterator_defaults_select - { - template - struct traits - { - typedef typename boost::detail::iterator_traits::value_type value_type; - typedef typename boost::detail::iterator_traits::pointer pointer; - typedef typename boost::detail::iterator_traits::reference reference; - }; - }; - - template <> - struct iterator_defaults_select - { - template - struct traits - { - typedef Value value_type; - typedef Value* pointer; - typedef Value& reference; - }; - }; - - template - struct iterator_defaults - { - enum { is_ptr = boost::is_pointer::value }; - typedef iterator_defaults_select::template traits traits; - typedef typename traits::pointer pointer; - typedef typename traits::reference reference; - }; -} -#endif - template ::value_type, -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::pointer, - class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::reference, -#else class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, -#endif class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category, class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type > @@ -969,25 +970,32 @@ namespace detail { template struct non_bidirectional_category { +# if !defined(__MWERKS__) || __MWERKS__ > 0x4000 typedef typename reduce_to_base_class< std::forward_iterator_tag, typename iterator_traits::iterator_category >::type type; - + private: // For some reason, putting this assertion in filter_iterator_generator fails inexplicably under MSVC BOOST_STATIC_ASSERT((!boost::is_convertible::value)); +# else + // is_convertible doesn't work with MWERKS + typedef typename iterator_traits::iterator_category input_category; + typedef typename if_true<( + boost::is_same::value + || boost::is_same::value + )>::template then< + std::forward_iterator_tag, + input_category + >::type type; +# endif }; } template ::value_type, -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::pointer, - class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::reference, -#else - class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, -#endif + class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::non_bidirectional_category::type, class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type > From c585adde716fce46a92339d95899c904d3418f98 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 11 Feb 2001 03:05:50 +0000 Subject: [PATCH 080/265] Removed traits argument from iterator_adaptor<> and switched to explicit trait specification for maximum ease-of-use. Added comments to detail::iterator_defaults<> Began using detail::iterator_defaults<> unconditionally for code clarity Changed uses of `Iterator' to `Base' where non-iterators can be used. [SVN r9104] --- include/boost/iterator_adaptors.hpp | 379 ++++++++++++++++------------ 1 file changed, 212 insertions(+), 167 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 6f313a6..0e3d54d 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,13 @@ // // Revision History: +// 10 Feb 2001 David Abrahams +// Removed traits argument from iterator_adaptor<> and switched to +// explicit trait specification for maximum ease-of-use. +// Added comments to detail::iterator_defaults<> +// Began using detail::iterator_defaults<> unconditionally for code clarity +// Changed uses of `Iterator' to `Base' where non-iterators can be used. +// // 10 Feb 2001 David Abrahams // Rolled in supposed Borland fixes from John Maddock, but not seeing any // improvement yet @@ -210,24 +217,24 @@ struct default_iterator_policies // and thought they were non-const. Also, Sun C++ does not like static // function templates. - template - void initialize(Iterator&) + template + void initialize(Base&) { } - template - Reference dereference(type, const Iterator& x) const + template + Reference dereference(type, const Base& x) const { return *x; } - template - void increment(Iterator& x) + template + void increment(Base& x) { ++x; } - template - void decrement(Iterator& x) + template + void decrement(Base& x) { --x; } - template - void advance(Iterator& x, DifferenceType n) + template + void advance(Base& x, DifferenceType n) { x += n; } template @@ -360,21 +367,19 @@ namespace detail { return &(*i); } - template + template struct operator_arrow_result_generator { - typedef typename Traits::iterator_category category; - typedef operator_arrow_proxy proxy; - typedef typename Traits::pointer pointer; + typedef operator_arrow_proxy proxy; - enum { is_input_iter = boost::is_convertible::value - & !boost::is_convertible::value }; + enum { is_input_iter = boost::is_convertible::value + & !boost::is_convertible::value }; typedef typename boost::detail::if_true<(is_input_iter)>::template then< proxy, // else - pointer + Pointer >::type type; }; @@ -391,30 +396,37 @@ namespace detail { } # ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // Select default pointer and reference types for adapted non-pointer + // iterators based on the iterator and the value_type. Poor man's partial + // specialization is in use here. template struct iterator_defaults_select { template struct traits { - typedef typename boost::detail::iterator_traits::value_type value_type; + // The assumption is that iterator_traits can deduce these types + // properly as long as the iterator is not a pointer. typedef typename boost::detail::iterator_traits::pointer pointer; typedef typename boost::detail::iterator_traits::reference reference; }; }; + // Select default pointer and reference types for adapted pointer iterators + // given a (possibly-const) value_type. template <> struct iterator_defaults_select { template struct traits { - typedef Value value_type; typedef Value* pointer; typedef Value& reference; }; }; + // Consolidate selection of the default pointer and reference type template struct iterator_defaults { @@ -427,49 +439,91 @@ namespace detail { template struct iterator_defaults : iterator_traits { - typedef typename iterator_traits::pointer pointer; - typedef typename iterator_traits::reference reference; + enum { + is_iterator_value_type = + ::boost::is_same::value_type>::value + }; + + typedef typename if_true<( + is_iterator_value_type + )>::template then< + typename iterator_traits::pointer, + Value* + >::type pointer; + + typedef typename if_true<( + is_iterator_value_type + )>::template then< + typename iterator_traits::reference, + Value& + >::type reference; + }; - # endif } // namespace detail +// This macro definition is only temporary in this file +# if !defined(BOOST_MSVC) +# define BOOST_ARG_DEPENDENT_TYPENAME typename +# else +# define BOOST_ARG_DEPENDENT_TYPENAME +# endif + +template struct undefined; //============================================================================ //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. +// Base - the base (usually 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. +// Value - if supplied, the value_type of the resulting iterator, unless +// const. If const, a conforming compiler strips constness for the +// value_type. If not supplied, iterator_traits::value_type is used // -template +// Reference - the reference type of the resulting iterator, and in +// particular, the result type of operator*(). If not supplied but +// Value is supplied, Value& is used. Otherwise +// iterator_traits::reference is used. +// +// Pointer - the pointer type of the resulting iterator, and in +// particular, the result type of operator->(). If not +// supplied but Value is supplied, Value* is used. Otherwise +// iterator_traits::pointer is used. +// +// Category - the iterator_category of the resulting iterator. If not +// supplied, iterator_traits::iterator_category is used. +// +// Distance - the difference_type of the resulting iterator. If not +// supplied, iterator_traits::difference_type is used. +template ::value_type, + class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, + class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, + class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category, + class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type > struct iterator_adaptor : #ifdef BOOST_RELOPS_AMBIGUITY_BUG iterator_comparisons< - iterator_adaptor, + iterator_adaptor, #endif - boost::iterator + boost::iterator #ifdef BOOST_RELOPS_AMBIGUITY_BUG > #endif { - typedef iterator_adaptor Self; + 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; + typedef Distance difference_type; + typedef typename boost::remove_const::type value_type; + typedef Pointer pointer; + typedef Reference reference; + typedef Category iterator_category; + typedef Base base_type; enum { is_input_or_output_iter = boost::is_convertible::value @@ -487,16 +541,17 @@ public: iterator_adaptor() { } - iterator_adaptor(const Iterator& it, const Policies& p = Policies()) + iterator_adaptor(const Base& 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()); + template + iterator_adaptor ( + const iterator_adaptor& src) + : m_iter_p(src.iter(), src.policies()) + { + policies().initialize(iter()); } #ifdef BOOST_MSVC @@ -516,7 +571,7 @@ public: # pragma warning( disable : 4284 ) #endif - typename boost::detail::operator_arrow_result_generator::type + typename boost::detail::operator_arrow_result_generator::type operator->() const { return detail::operator_arrow(*this, iterator_category()); } @@ -527,116 +582,148 @@ public: value_type operator[](difference_type n) const { return *(*this + n); } - Self& operator++() { + 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()); + policies().increment(iter()); #else policies().increment(iter()); #endif return *this; } - Self operator++(int) { Self tmp(*this); ++*this; return tmp; } + self operator++(int) { self tmp(*this); ++*this; return tmp; } - Self& operator--() { + self& operator--() { detail::decrement_impl(*this, iterator_category()); return *this; } - Self operator--(int) { Self tmp(*this); --*this; return tmp; } + self operator--(int) { self tmp(*this); --*this; return tmp; } - Self& operator+=(difference_type n) { + self& operator+=(difference_type n) { detail::advance_impl(*this, n, iterator_category()); return *this; } - Self& operator-=(difference_type n) { + self& operator-=(difference_type n) { detail::advance_impl(*this, -n, iterator_category()); return *this; } - iterator_type base() const { return m_iter_p.first(); } + base_type base() const { return m_iter_p.first(); } + // Moved from global scope to avoid ambiguity with the operator-() which + // subtracts iterators from one another. + self operator-(Distance x) + { self result(*this); return result -= x; } private: typedef Policies policies_type; - compressed_pair m_iter_p; -public: // too many compilers have trouble when these are private. + compressed_pair m_iter_p; + +public: // implementation details (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(); } + + Base& iter() { return m_iter_p.first(); } + const Base& 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) +template +iterator_adaptor +operator+( + iterator_adaptor p, + Distance2 x) { return p += x; } -template -iterator_adaptor -operator+(typename Traits::difference_type x, iterator_adaptor p) +template +iterator_adaptor +operator+( + Distance2 x, + iterator_adaptor p) { return p += x; } -template -typename Traits1::difference_type operator-( - const iterator_adaptor& x, - const iterator_adaptor& y ) +template +Distance 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()); + return x.policies().distance(type(), y.iter(), x.iter()); } #ifndef BOOST_RELOPS_AMBIGUITY_BUG -template +template inline bool -operator==(const iterator_adaptor& x, const iterator_adaptor& y) { +operator==( + const iterator_adaptor& x, + const iterator_adaptor& y) +{ return x.policies().equal(x.iter(), y.iter()); } -template +template inline bool -operator<(const iterator_adaptor& x, const iterator_adaptor& y) { +operator<( + const iterator_adaptor& x, + const iterator_adaptor& y) +{ return x.policies().less(x.iter(), y.iter()); } -template +template inline bool -operator>(const iterator_adaptor& x, - const iterator_adaptor& y) { +operator>( + const iterator_adaptor& x, + const iterator_adaptor& y) +{ return x.policies().less(y.iter(), x.iter()); } -template +template inline bool -operator>=(const iterator_adaptor& x, const iterator_adaptor& y) { +operator>=( + const iterator_adaptor& x, + const iterator_adaptor& y) +{ return !x.policies().less(x.iter(), y.iter()); } -template +template inline bool -operator<=(const iterator_adaptor& x, - const iterator_adaptor& y) { +operator<=( + const iterator_adaptor& x, + const iterator_adaptor& y) +{ return !x.policies().less(y.iter(), x.iter()); } -template +template inline bool -operator!=(const iterator_adaptor& x, - const iterator_adaptor& y) { +operator!=( + const iterator_adaptor& x, + const iterator_adaptor& y) +{ return !x.policies().equal(x.iter(), y.iter()); } #endif @@ -663,14 +750,11 @@ struct transform_iterator_policies : public default_iterator_policies template class transform_iterator_generator { - typedef typename boost::detail::iterator_traits::difference_type - difference_type; typedef typename AdaptableUnaryFunction::result_type value_type; public: - typedef boost::iterator transform_traits; typedef iterator_adaptor, transform_traits> + transform_iterator_policies, + value_type, value_type, value_type*, std::input_iterator_tag> type; }; @@ -706,13 +790,6 @@ struct indirect_iterator_policies : public default_iterator_policies { return **x; } }; -// This macro definition is only temporary in this file -# if !defined(BOOST_MSVC) -# define BOOST_ARG_DEPENDENT_TYPENAME typename -# else -# define BOOST_ARG_DEPENDENT_TYPENAME -# endif - namespace detail { # if !defined(BOOST_MSVC) // stragely instantiated even when unused! Maybe try a recursive template someday ;-) template @@ -731,18 +808,10 @@ template -class indirect_iterator_generator +struct indirect_iterator_generator { - typedef boost::detail::iterator_traits outer_traits; - typedef typename outer_traits::difference_type difference_type; - typedef typename outer_traits::iterator_category iterator_category; - - typedef typename boost::remove_const::type value_type; - typedef Pointer pointer; - typedef Reference reference; -public: - typedef boost::iterator indirect_traits; - typedef iterator_adaptor type; + typedef iterator_adaptor type; }; template ::type const_iterator; }; -// Tried to allow InnerTraits to be provided by explicit template -// argument to the function, but could not get it to work. -Jeremy Siek -template -inline typename indirect_iterator_generator::type -make_indirect_iterator(OuterIterator base, Value* = 0) -{ - typedef typename indirect_iterator_generator - ::type result_t; - return result_t(base); -} - -# if 0 // This just doesn't seem to work under any circumstances! +#ifndef BOOST_MSVC template inline typename indirect_iterator_generator::type make_indirect_iterator(OuterIterator base) @@ -783,28 +841,27 @@ make_indirect_iterator(OuterIterator base) ::type result_t; return result_t(base); } -# endif - +#endif //============================================================================= // Reverse Iterators Adaptor struct reverse_iterator_policies : public default_iterator_policies { - template - Reference dereference(type, const Iterator& x) const + template + Reference dereference(type, const BidirectionalIterator& x) const { return *boost::prior(x); } - template - void increment(Iterator& x) const + template + void increment(BidirectionalIterator& x) const { --x; } - template - void decrement(Iterator& x) const + template + void decrement(BidirectionalIterator& x) const { ++x; } - template - void advance(Iterator& x, DifferenceType n) const + template + void advance(BidirectionalIterator& x, DifferenceType n) const { x -= n; } template @@ -821,25 +878,24 @@ struct reverse_iterator_policies : public default_iterator_policies { return y < x; } }; -template ::value_type, - class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, - class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, - class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category, - class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type +template ::value_type, + class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, + class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, + class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category, + class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type > struct reverse_iterator_generator { - typedef typename boost::remove_const::type value_type; - typedef boost::iterator traits; - typedef iterator_adaptor type; + typedef iterator_adaptor type; }; -template -inline typename reverse_iterator_generator::type -make_reverse_iterator(Iterator base) +template +inline typename reverse_iterator_generator::type +make_reverse_iterator(BidirectionalIterator base) { - typedef typename reverse_iterator_generator::type result_t; + typedef typename reverse_iterator_generator::type result_t; return result_t(base); } @@ -862,28 +918,18 @@ struct projection_iterator_policies : public default_iterator_policies template class projection_iterator_generator { - typedef boost::detail::iterator_traits Traits; typedef typename AdaptableUnaryFunction::result_type value_type; - typedef boost::iterator - projection_traits; + typedef projection_iterator_policies policies; public: - typedef iterator_adaptor, - projection_traits> type; + typedef iterator_adaptor type; }; template class const_projection_iterator_generator { - typedef boost::detail::iterator_traits Traits; typedef typename AdaptableUnaryFunction::result_type value_type; - typedef boost::iterator - projection_traits; + typedef projection_iterator_policies policies; public: - typedef iterator_adaptor, - projection_traits> type; + typedef iterator_adaptor type; }; template @@ -1000,8 +1046,6 @@ template ::difference_type > class filter_iterator_generator { - typedef typename boost::remove_const::type value_type; - typedef boost::iterator traits; enum { is_bidirectional = boost::is_convertible::value @@ -1011,7 +1055,8 @@ class filter_iterator_generator { #endif public: typedef filter_iterator_policies policies_type; - typedef iterator_adaptor type; + typedef iterator_adaptor type; }; // This keeps MSVC happy; it doesn't like to deduce default template arguments From ad4c5ab089096237bea2b5d95416b299b93df983 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 11 Feb 2001 03:10:01 +0000 Subject: [PATCH 081/265] Use new iterator_adaptor<> interface [SVN r9106] --- include/boost/counting_iterator.hpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index 08ddae2..86caadc 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -28,8 +28,9 @@ // Incrementable. // // Revision History +// 10 Feb 2001 Use new iterator_adaptor<> interface (David Abrahams) // 10 Feb 2001 Rolled in supposed Borland fixes from John Maddock, but not -// seeing any improvement yet +// seeing any improvement yet (David Abrahams) // 09 Feb 2001 Factored out is_numeric computation. Borland still // unhappy :( (David Abrahams) // 08 Feb 2001 Beginning of a failed attempt to appease Borland @@ -189,9 +190,16 @@ struct counting_iterator_policies : public default_iterator_policies template struct counting_iterator_generator { + typedef counting_iterator_traits traits; + typedef iterator_adaptor, - counting_iterator_traits > type; + typename traits::value_type, + typename traits::reference, + typename traits::pointer, + typename traits::iterator_category, + typename traits::difference_type + > type; }; // Manufacture a counting iterator for an arbitrary incrementable type @@ -199,9 +207,19 @@ template inline typename counting_iterator_generator::type make_counting_iterator(Incrementable x) { + typedef counting_iterator_traits traits; + + // These typedefs appease MSVC + typedef typename traits::value_type value_type; + typedef typename traits::reference reference; + typedef typename traits::pointer pointer; + typedef typename traits::iterator_category iterator_category; + typedef typename traits::difference_type difference_type; + return iterator_adaptor, - counting_iterator_traits >(x); + value_type, reference, pointer, iterator_category,difference_type + >(x); } From b2701f9f78109509feb6fc925fbd844c6284a244 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Sun, 11 Feb 2001 12:50:06 +0000 Subject: [PATCH 082/265] Borland compiler fixes [SVN r9110] --- include/boost/counting_iterator.hpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index 86caadc..1b806f1 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -130,28 +130,36 @@ namespace detail { // Try to detect numeric types at compile time in ways compatible with the // limitations of the compiler and library. +#ifndef __BORLANDC__ template struct is_numeric { // For a while, this wasn't true, but we rely on it below. This is a regression assert. BOOST_STATIC_ASSERT(::boost::is_integral::value); - enum { value = + enum { value = #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS std::numeric_limits::is_specialized -#elif defined(__BORLANDC__) - ::boost::is_arithmetic::value #else boost::is_convertible::value && boost::is_convertible::value #endif }; }; - +#else + // Borland seems to have a strange problem with is_numeric, just delegate + // to is_arithmetic instead: + template + struct is_numeric { + // For a while, this wasn't true, but we rely on it below. This is a regression assert. + BOOST_STATIC_ASSERT(::boost::is_integral::value); + static const bool value = ::boost::is_arithmetic::value; + }; +#endif // Compute the distance over arbitrary numeric and/or iterator types template Distance any_distance(Incrementable start, Incrementable finish, Distance* = 0) { return distance_policy_select<( - is_numeric::value)>::template + ::boost::detail::is_numeric::value)>::template policy::distance(start, finish); } @@ -160,10 +168,11 @@ namespace detail { template struct counting_iterator_traits { private: - enum {numeric = detail::is_numeric::value }; - typedef typename detail::counting_iterator_traits_select<( - numeric - )>::template traits traits; + BOOST_STATIC_ASSERT(::boost::detail::is_numeric::value == ::boost::is_arithmetic::value); + typedef ::boost::detail::counting_iterator_traits_select<( + ::boost::detail::is_numeric::value + )> binder; + typedef typename binder::template traits traits; public: typedef Incrementable value_type; typedef const Incrementable& reference; From 170b44763d8cc47d00290a6733b1922c0cc2d1bf Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 11 Feb 2001 14:07:11 +0000 Subject: [PATCH 083/265] Clean up after John Maddocks's (finally effective!) Borland fixes [SVN r9111] --- include/boost/counting_iterator.hpp | 40 +++++++++++------------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index 1b806f1..6dedaef 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -28,6 +28,8 @@ // Incrementable. // // Revision History +// 11 Feb 2001 Clean up after John Maddocks's (finally effective!) Borland +// fixes (David Abrahams). // 10 Feb 2001 Use new iterator_adaptor<> interface (David Abrahams) // 10 Feb 2001 Rolled in supposed Borland fixes from John Maddock, but not // seeing any improvement yet (David Abrahams) @@ -63,14 +65,11 @@ namespace detail { // iterator_category and difference_type for a counting_iterator at // compile-time based on whether or not it wraps an integer or an iterator, // using "poor man's partial specialization". - template struct counting_iterator_traits_select + template struct counting_iterator_traits_select; -#ifndef __BORLANDC__ - ; // Incrementable is an iterator type template <> struct counting_iterator_traits_select -#endif { template struct traits @@ -102,13 +101,11 @@ namespace detail { // the iterator wraps an integer or an iterator, using "poor man's partial // specialization". - template struct distance_policy_select -#ifndef __BORLANDC__ - ; + template struct distance_policy_select; + // A policy for wrapped iterators template <> struct distance_policy_select -#endif { template struct policy { @@ -130,36 +127,31 @@ namespace detail { // Try to detect numeric types at compile time in ways compatible with the // limitations of the compiler and library. -#ifndef __BORLANDC__ template struct is_numeric { // For a while, this wasn't true, but we rely on it below. This is a regression assert. BOOST_STATIC_ASSERT(::boost::is_integral::value); +#if !defined(__BORLANDC__) enum { value = -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS std::numeric_limits::is_specialized -#else +# else boost::is_convertible::value && boost::is_convertible::value -#endif +# endif }; - }; #else - // Borland seems to have a strange problem with is_numeric, just delegate - // to is_arithmetic instead: - template - struct is_numeric { - // For a while, this wasn't true, but we rely on it below. This is a regression assert. - BOOST_STATIC_ASSERT(::boost::is_integral::value); + // Borland seems to have a strange problem with using an enum in this case static const bool value = ::boost::is_arithmetic::value; - }; #endif + }; + // Compute the distance over arbitrary numeric and/or iterator types template Distance any_distance(Incrementable start, Incrementable finish, Distance* = 0) { return distance_policy_select<( - ::boost::detail::is_numeric::value)>::template + is_numeric::value)>::template policy::distance(start, finish); } @@ -168,11 +160,9 @@ namespace detail { template struct counting_iterator_traits { private: - BOOST_STATIC_ASSERT(::boost::detail::is_numeric::value == ::boost::is_arithmetic::value); typedef ::boost::detail::counting_iterator_traits_select<( - ::boost::detail::is_numeric::value - )> binder; - typedef typename binder::template traits traits; + detail::is_numeric::value + )>::template traits traits; public: typedef Incrementable value_type; typedef const Incrementable& reference; From 268e70faa185140301651df8bfe1a9b92907c7ba Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 11 Feb 2001 16:06:12 +0000 Subject: [PATCH 084/265] Reinstate one of John's fixes [SVN r9113] --- include/boost/counting_iterator.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index 6dedaef..aacd050 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -161,8 +161,9 @@ template struct counting_iterator_traits { private: typedef ::boost::detail::counting_iterator_traits_select<( - detail::is_numeric::value - )>::template traits traits; + ::boost::detail::is_numeric::value + )> binder; + typedef typename binder::template traits traits; public: typedef Incrementable value_type; typedef const Incrementable& reference; From fd6ba58d5eec71680e1ab9dfbd8af87a702ad09c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 11 Feb 2001 16:09:22 +0000 Subject: [PATCH 085/265] Borland fixes up the wazoo. It finally works! [SVN r9114] --- include/boost/iterator_adaptors.hpp | 77 +++++++++++++---------------- 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 0e3d54d..fc4d538 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,8 @@ // // Revision History: +// 11 Feb 2001 David Abrahams +// Borland fixes up the wazoo. It finally works! // 10 Feb 2001 David Abrahams // Removed traits argument from iterator_adaptor<> and switched to // explicit trait specification for maximum ease-of-use. @@ -21,74 +23,56 @@ // // 10 Feb 2001 David Abrahams // Rolled in supposed Borland fixes from John Maddock, but not seeing any -// improvement yet -// +// improvement yet // Changed argument order to indirect_ generator, for convenience in the -// case of input iterators (where Reference must be a value type). -// +// case of input iterators (where Reference must be a value type). // Removed derivation of filter_iterator_policies from -// default_iterator_policies, since the iterator category is likely to be -// reduced (we don't want to allow illegal operations like decrement). -// +// default_iterator_policies, since the iterator category is likely to be +// reduced (we don't want to allow illegal operations like decrement). // Support for a simpler filter iterator interface. // // 09 Feb 2001 David Abrahams // Improved interface to indirect_ and reverse_ iterators -// // Rolled back Jeremy's new constructor for now; it was causing -// problems with counting_iterator_test -// +// problems with counting_iterator_test // Attempted fix for Borland // // 09 Feb 2001 Jeremy Siek // Added iterator constructor to allow const adaptor -// from non-const adaptee. -// +// from non-const adaptee. // Changed make_xxx to pass iterators by-value to -// get arrays converted to pointers. -// +// get arrays converted to pointers. // Removed InnerIterator template parameter from -// indirect_iterator_generator. -// +// indirect_iterator_generator. // Rearranged parameters for make_filter_iterator // // 07 Feb 2001 Jeremy Siek // Removed some const iterator adaptor generators. -// // Added make_xxx_iterator() helper functions for remaining -// iterator adaptors. -// +// iterator adaptors. // Removed some traits template parameters where they -// where no longer needed thanks to detail::iterator_traits. -// +// where no longer needed thanks to detail::iterator_traits. // Moved some of the compile-time logic into enums for // EDG compatibility. // // 07 Feb 2001 David Abrahams // Removed iterator_adaptor_pair_generator and -// reverse_iterator_pair_generator (more such culling to come) -// +// 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 -// +// to boost::detail::iterator_traits for improved utility in +// non-generic contexts // Fixed naming convention of non-template parameter names // // 06 Feb 2001 David Abrahams // 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. +// 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) @@ -358,7 +342,11 @@ namespace detail { template inline operator_arrow_proxy operator_arrow(const Iter& i, std::input_iterator_tag) { - return operator_arrow_proxy(*i); + return operator_arrow_proxy< +#ifndef BOOST_MSVC + typename +#endif + Iter::value_type>(*i); } template @@ -431,6 +419,7 @@ namespace detail { struct iterator_defaults { enum { is_ptr = boost::is_pointer::value }; + typedef iterator_defaults_select::template traits traits; typedef typename traits::pointer pointer; typedef typename traits::reference reference; @@ -439,20 +428,17 @@ namespace detail { template struct iterator_defaults : iterator_traits { - enum { - is_iterator_value_type = - ::boost::is_same::value_type>::value - }; - + // Trying to factor the common is_same expression into an enum or a + // static bool constant confused Borland. typedef typename if_true<( - is_iterator_value_type + ::boost::is_same::value_type>::value )>::template then< typename iterator_traits::pointer, Value* >::type pointer; typedef typename if_true<( - is_iterator_value_type + ::boost::is_same::value_type>::value )>::template then< typename iterator_traits::reference, Value& @@ -1046,10 +1032,17 @@ template ::difference_type > class filter_iterator_generator { +#ifndef __BORLANDC__ enum { +#else + static const bool +#endif is_bidirectional = boost::is_convertible::value - }; +#ifndef __BORLANDC__ + } +#endif + ; #ifndef BOOST_MSVC // I don't have any idea why this occurs, but it doesn't seem to hurt too badly. BOOST_STATIC_ASSERT(!is_bidirectional); #endif From ea4c7c7dd96fa2cb685cbbfe795874ee94de2d12 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 11 Feb 2001 18:57:31 +0000 Subject: [PATCH 086/265] Removed workaround for older MIPSpro compiler. The workaround was preventing the proper functionality of the underlying iterator being carried forward into the iterator adaptor. Also added is_bidirectional enum to avoid EDG compiler error. [SVN r9123] --- include/boost/iterator_adaptors.hpp | 54 ++++++----------------------- 1 file changed, 11 insertions(+), 43 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index fc4d538..ee7c28b 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,11 @@ // // Revision History: +// 11 Feb 2001 Jeremy Siek +// Removed workaround for older MIPSpro compiler. The workaround +// was preventing the proper functionality of the underlying +// iterator being carried forward into the iterator adaptor. +// Also added is_bidirectional enum to avoid EDG compiler error. // 11 Feb 2001 David Abrahams // Borland fixes up the wazoo. It finally works! // 10 Feb 2001 David Abrahams @@ -297,35 +302,8 @@ inline bool operator<=(const iterator_comparisons& xb, } #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::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 - // 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 @@ -371,17 +349,6 @@ namespace detail { >::type type; }; - 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()); - } # ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION @@ -559,7 +526,7 @@ public: typename boost::detail::operator_arrow_result_generator::type operator->() const - { return detail::operator_arrow(*this, iterator_category()); } + { return detail::operator_arrow(*this, Category()); } #ifdef _MSC_VER # pragma warning(pop) @@ -582,19 +549,19 @@ public: self operator++(int) { self tmp(*this); ++*this; return tmp; } self& operator--() { - detail::decrement_impl(*this, iterator_category()); + policies().decrement(iter()); return *this; } self operator--(int) { self tmp(*this); --*this; return tmp; } self& operator+=(difference_type n) { - detail::advance_impl(*this, n, iterator_category()); + policies().advance(iter(), n); return *this; } self& operator-=(difference_type n) { - detail::advance_impl(*this, -n, iterator_category()); + policies().advance(iter(), -n); return *this; } @@ -1009,7 +976,8 @@ namespace detail { >::type type; private: // For some reason, putting this assertion in filter_iterator_generator fails inexplicably under MSVC - BOOST_STATIC_ASSERT((!boost::is_convertible::value)); + enum { is_bidirectional = (!boost::is_convertible::value) }; + BOOST_STATIC_ASSERT(is_bidirectional); # else // is_convertible doesn't work with MWERKS typedef typename iterator_traits::iterator_category input_category; From e3aaf2cc91ecb317fb64aceb8b1fec01a462e983 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 11 Feb 2001 19:29:28 +0000 Subject: [PATCH 087/265] Switch to use of BOOST_STATIC_CONSTANT where possible [SVN r9127] --- include/boost/iterator_adaptors.hpp | 45 +++++++++++++++-------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index ee7c28b..38eca67 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,8 @@ // // Revision History: +// 11 Feb 2001 David Abrahams +// Switch to use of BOOST_STATIC_CONSTANT where possible // 11 Feb 2001 Jeremy Siek // Removed workaround for older MIPSpro compiler. The workaround // was preventing the proper functionality of the underlying @@ -338,8 +340,11 @@ namespace detail { { typedef operator_arrow_proxy proxy; - enum { is_input_iter = boost::is_convertible::value - & !boost::is_convertible::value }; + // Borland chokes unless it's an actual enum (!) + enum { is_input_iter + = (boost::is_convertible::value + & !boost::is_convertible::value) + }; typedef typename boost::detail::if_true<(is_input_iter)>::template then< @@ -385,7 +390,7 @@ namespace detail { template struct iterator_defaults { - enum { is_ptr = boost::is_pointer::value }; + BOOST_STATIC_CONSTANT(bool, is_ptr = boost::is_pointer::value); typedef iterator_defaults_select::template traits traits; typedef typename traits::pointer pointer; @@ -470,7 +475,7 @@ struct iterator_adaptor : #endif { typedef iterator_adaptor self; -public: + public: typedef Distance difference_type; typedef typename boost::remove_const::type value_type; typedef Pointer pointer; @@ -478,20 +483,23 @@ public: typedef Category iterator_category; typedef Base base_type; - enum { is_input_or_output_iter = - boost::is_convertible::value - || boost::is_convertible::value }; + private: + BOOST_STATIC_CONSTANT(bool, is_input_or_output_iter + = (boost::is_convertible::value + || boost::is_convertible::value)); // Iterators should satisfy one of the known categories BOOST_STATIC_ASSERT(is_input_or_output_iter); // Iterators >= ForwardIterator must produce real references. - enum { forward_iter_with_real_reference = + BOOST_STATIC_CONSTANT(bool, forward_iter_with_real_reference = (!boost::is_convertible::value || boost::is_same::value - || boost::is_same::value) }; + || boost::is_same::value)); + BOOST_STATIC_ASSERT(forward_iter_with_real_reference); - + + public: iterator_adaptor() { } iterator_adaptor(const Base& it, const Policies& p = Policies()) @@ -976,7 +984,9 @@ namespace detail { >::type type; private: // For some reason, putting this assertion in filter_iterator_generator fails inexplicably under MSVC - enum { is_bidirectional = (!boost::is_convertible::value) }; + BOOST_STATIC_CONSTANT( + bool, is_bidirectional + = (!boost::is_convertible::value)); BOOST_STATIC_ASSERT(is_bidirectional); # else // is_convertible doesn't work with MWERKS @@ -1000,17 +1010,8 @@ template ::difference_type > class filter_iterator_generator { -#ifndef __BORLANDC__ - enum { -#else - static const bool -#endif - is_bidirectional - = boost::is_convertible::value -#ifndef __BORLANDC__ - } -#endif - ; + BOOST_STATIC_CONSTANT(bool, is_bidirectional + = (boost::is_convertible::value)); #ifndef BOOST_MSVC // I don't have any idea why this occurs, but it doesn't seem to hurt too badly. BOOST_STATIC_ASSERT(!is_bidirectional); #endif From dca20fae750bb19314ca8ce747e75199a777a749 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 11 Feb 2001 19:33:47 +0000 Subject: [PATCH 088/265] Use BOOST_STATIC_CONSTANT [SVN r9129] --- include/boost/counting_iterator.hpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index aacd050..0d122f5 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -28,6 +28,7 @@ // Incrementable. // // Revision History +// 11 Feb 2001 Use BOOST_STATIC_CONSTANT (Dave Abrahams) // 11 Feb 2001 Clean up after John Maddocks's (finally effective!) Borland // fixes (David Abrahams). // 10 Feb 2001 Use new iterator_adaptor<> interface (David Abrahams) @@ -131,18 +132,16 @@ namespace detail { struct is_numeric { // For a while, this wasn't true, but we rely on it below. This is a regression assert. BOOST_STATIC_ASSERT(::boost::is_integral::value); -#if !defined(__BORLANDC__) - enum { value = # ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - std::numeric_limits::is_specialized + BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_specialized); # else - boost::is_convertible::value && boost::is_convertible::value +# if !defined(__BORLANDC__) + BOOST_STATIC_CONSTANT(bool, value = ( + boost::is_convertible::value && boost::is_convertible::value)); +# else + BOOST_STATIC_CONSTANT(bool, value = ::boost::is_arithmetic::value); +# endif # endif - }; -#else - // Borland seems to have a strange problem with using an enum in this case - static const bool value = ::boost::is_arithmetic::value; -#endif }; // Compute the distance over arbitrary numeric and/or iterator types From 2c2a3eab2188e1b85e892678813d9866fdb6f9a3 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 11 Feb 2001 19:36:43 +0000 Subject: [PATCH 089/265] Use new iterator_adaptor interface, Fixes for Borland. [SVN r9131] --- include/boost/half_open_range.hpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/include/boost/half_open_range.hpp b/include/boost/half_open_range.hpp index ac8d057..1de1e9d 100644 --- a/include/boost/half_open_range.hpp +++ b/include/boost/half_open_range.hpp @@ -5,8 +5,10 @@ // for any purpose. // // Revision History: -// 04 Feb 2001 Support for user-defined iterator categories (David Abrahams) -// 30 Jan 2001 Initial Checkin (David Abrahams) +// 11 Feb 2001 Use new iterator_adaptor interface, Fixes for Borland. +// (Dave Abrahams) +// 04 Feb 2001 Support for user-defined iterator categories (Dave Abrahams) +// 30 Jan 2001 Initial Checkin (Dave Abrahams) #ifndef BOOST_HALF_OPEN_RANGE_HPP_ # define BOOST_HALF_OPEN_RANGE_HPP_ @@ -75,7 +77,7 @@ namespace detail { static const Incrementable choose(const Incrementable& start, const Incrementable& finish) { return finish_chooser<( - boost::is_convertible::value + ::boost::is_convertible::value )>::template rebind::choose(start, finish); } }; @@ -85,16 +87,18 @@ namespace detail { template struct half_open_range { - typedef iterator_adaptor, - counting_iterator_traits > iterator; + typedef typename counting_iterator_generator::type iterator; private: // utility type definitions + // Using iter_t prevents compiler confusion with boost::iterator + typedef typename counting_iterator_generator::type iter_t; + typedef std::less less_value; - typedef typename boost::detail::iterator_traits::iterator_category category; + typedef typename iter_t::iterator_category category; + typedef half_open_range self; public: - typedef iterator const_iterator; + typedef iter_t 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; @@ -130,7 +134,14 @@ struct half_open_range #endif ) {} - + + half_open_range& operator=(const self& x) + { + m_start = x.m_start; + m_finish = x.m_finish; + return *this; + } + half_open_range& operator=(const std::pair& x) { m_start = x.first; From 5482763a93a877adb6899d4323fdee1f90efbfa0 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 12 Feb 2001 04:45:02 +0000 Subject: [PATCH 090/265] added missing const qualifier [SVN r9148] --- 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 38eca67..22c7ade 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -577,7 +577,7 @@ struct iterator_adaptor : // Moved from global scope to avoid ambiguity with the operator-() which // subtracts iterators from one another. - self operator-(Distance x) + self operator-(Distance x) const { self result(*this); return result -= x; } private: typedef Policies policies_type; From 1988994bd3a7b68a7c014bba517ac53d8f7455b0 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Tue, 13 Feb 2001 02:03:59 +0000 Subject: [PATCH 091/265] added dummy_constructor to dummyT so it can be used in concept archetypes [SVN r9181] --- include/boost/pending/iterator_tests.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp index 3abdccc..c3c3601 100644 --- a/include/boost/pending/iterator_tests.hpp +++ b/include/boost/pending/iterator_tests.hpp @@ -15,12 +15,14 @@ # include # include # include +# include // for detail::dummy_constructor namespace boost { // use this for the value type struct dummyT { dummyT() { } + dummyT(detail::dummy_constructor) { } dummyT(int x) : m_x(x) { } int foo() const { return m_x; } bool operator==(const dummyT& d) const { return m_x == d.m_x; } From bf459774914952f1458e1b7815fec8d407613283 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 15 Feb 2001 05:51:40 +0000 Subject: [PATCH 092/265] removed unnecessary typedefs from counting_iterator_traits [SVN r9203] --- include/boost/counting_iterator.hpp | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index 0d122f5..90d808d 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -28,6 +28,8 @@ // Incrementable. // // Revision History +// 14 Feb 2001 Removed unnecessary typedefs from counting_iterator_traits +// (Jeremy Siek) // 11 Feb 2001 Use BOOST_STATIC_CONSTANT (Dave Abrahams) // 11 Feb 2001 Clean up after John Maddocks's (finally effective!) Borland // fixes (David Abrahams). @@ -164,9 +166,6 @@ struct counting_iterator_traits { )> binder; typedef typename binder::template traits traits; public: - typedef Incrementable value_type; - typedef const Incrementable& reference; - typedef const value_type* pointer; typedef typename traits::difference_type difference_type; typedef typename traits::iterator_category iterator_category; }; @@ -193,9 +192,9 @@ struct counting_iterator_generator typedef iterator_adaptor, - typename traits::value_type, - typename traits::reference, - typename traits::pointer, + Incrementable, + const Incrementable&, + const Incrementable*, typename traits::iterator_category, typename traits::difference_type > type; @@ -206,19 +205,8 @@ template inline typename counting_iterator_generator::type make_counting_iterator(Incrementable x) { - typedef counting_iterator_traits traits; - - // These typedefs appease MSVC - typedef typename traits::value_type value_type; - typedef typename traits::reference reference; - typedef typename traits::pointer pointer; - typedef typename traits::iterator_category iterator_category; - typedef typename traits::difference_type difference_type; - - return iterator_adaptor, - value_type, reference, pointer, iterator_category,difference_type - >(x); + typedef typename counting_iterator_generator::type result_t; + return result_t(x); } From c2472221ef7164695e8959e65b1faae872534f90 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 15 Feb 2001 06:07:00 +0000 Subject: [PATCH 093/265] made the typedef policies_type public in iterator_adaptor and private in filter_iterator_generator [SVN r9205] --- include/boost/iterator_adaptors.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 22c7ade..cd10caa 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -482,6 +482,7 @@ struct iterator_adaptor : typedef Reference reference; typedef Category iterator_category; typedef Base base_type; + typedef Policies policies_type; private: BOOST_STATIC_CONSTANT(bool, is_input_or_output_iter @@ -580,7 +581,6 @@ struct iterator_adaptor : self operator-(Distance x) const { self result(*this); return result -= x; } private: - typedef Policies policies_type; compressed_pair m_iter_p; public: // implementation details (too many compilers have trouble when these are private). @@ -1015,8 +1015,8 @@ class filter_iterator_generator { #ifndef BOOST_MSVC // I don't have any idea why this occurs, but it doesn't seem to hurt too badly. BOOST_STATIC_ASSERT(!is_bidirectional); #endif - public: typedef filter_iterator_policies policies_type; + public: typedef iterator_adaptor type; }; From ee20a630ddc39274b6d4c936d8a879897c68afc9 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 16 Feb 2001 05:24:45 +0000 Subject: [PATCH 094/265] Remove implication that a type generator may only generate a single type [SVN r9221] --- 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 cd10caa..f92b6da 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -896,7 +896,7 @@ public: template struct projection_iterator_pair_generator { typedef typename projection_iterator_generator::type iterator; - typedef typename const_projection_iterator_generator::type const_iterator; + typedef typename const_projection_iterator_generator::type const_iterator; }; From 1c73f1f2aefa082de5c45ebcc186df104f650730 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 16 Feb 2001 21:27:26 +0000 Subject: [PATCH 095/265] made filter_iterator_generator::policies_type public [SVN r9230] --- 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 f92b6da..a40c861 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -1015,8 +1015,8 @@ class filter_iterator_generator { #ifndef BOOST_MSVC // I don't have any idea why this occurs, but it doesn't seem to hurt too badly. BOOST_STATIC_ASSERT(!is_bidirectional); #endif - typedef filter_iterator_policies policies_type; public: + typedef filter_iterator_policies policies_type; typedef iterator_adaptor type; }; From 0c8d74863f7ff37ccbe0da85491edc5907543320 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 16 Feb 2001 23:06:57 +0000 Subject: [PATCH 096/265] Add an implicit conversion operator to operator_arrow_proxy as CW and BCC workarounds. [SVN r9233] --- include/boost/iterator_adaptors.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index a40c861..cbcf3cc 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,9 @@ // // Revision History: +// 16 Feb 2001 David Abrahams +// Add an implicit conversion operator to operator_arrow_proxy +// as CW and BCC workarounds. // 11 Feb 2001 David Abrahams // Switch to use of BOOST_STATIC_CONSTANT where possible // 11 Feb 2001 Jeremy Siek @@ -316,6 +319,9 @@ namespace detail { { operator_arrow_proxy(const T& x) : m_value(x) {} const T* operator->() const { return &m_value; } + // This function is needed for MWCW and BCC, which won't call operator-> + // again automatically per 13.3.1.2 para 8 + operator const T*() const { return &m_value; } T m_value; }; From ef66d28b19d5bde23b29385177bc1d0a9c89895d Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sat, 17 Feb 2001 01:44:41 +0000 Subject: [PATCH 097/265] added "explicit" to iterator_adaptor constructor [SVN r9234] --- include/boost/iterator_adaptors.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index cbcf3cc..f0f18fe 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -509,6 +509,7 @@ struct iterator_adaptor : public: iterator_adaptor() { } + explicit iterator_adaptor(const Base& it, const Policies& p = Policies()) : m_iter_p(it, p) { policies().initialize(iter()); From fc15f5f710e273f9c54fc93924d2a2a444a951b6 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sat, 17 Feb 2001 19:59:54 +0000 Subject: [PATCH 098/265] added Category parameter to the indirect iterator [SVN r9240] --- include/boost/iterator_adaptors.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index f0f18fe..f82fe2a 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -775,11 +775,12 @@ template ::iterator_category > struct indirect_iterator_generator { typedef iterator_adaptor type; + indirect_iterator_policies,Value,Reference,Pointer,Category> type; }; template ::iterator_category > struct indirect_iterator_pair_generator { typedef typename indirect_iterator_generator::type iterator; + Value, Reference, Pointer,Category>::type iterator; typedef typename indirect_iterator_generator::type const_iterator; + Value, ConstReference, ConstPointer,Category>::type const_iterator; }; #ifndef BOOST_MSVC From 8d8f828da5f8ab5932de75fc57575529b7536579 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sat, 17 Feb 2001 22:03:06 +0000 Subject: [PATCH 099/265] changes to order of indirect_iterator_generator param list [SVN r9246] --- include/boost/iterator_adaptors.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index f82fe2a..5d37871 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -774,8 +774,8 @@ template ::type #endif , class Reference = Value& - , class Pointer = Value* , class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category + , class Pointer = Value* > struct indirect_iterator_generator { @@ -788,18 +788,18 @@ template ::type #endif - , class Pointer = Value* , class Reference = Value& - , class ConstPointer = const Value* , class ConstReference = const Value& , class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category + , class Pointer = Value* + , class ConstPointer = const Value* > struct indirect_iterator_pair_generator { typedef typename indirect_iterator_generator::type iterator; + Value, Reference,Category,Pointer>::type iterator; typedef typename indirect_iterator_generator::type const_iterator; + Value, ConstReference,Category,ConstPointer>::type const_iterator; }; #ifndef BOOST_MSVC From e9d9bdbb10dec54f49ea68345453073c99dd9ac4 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 18 Feb 2001 22:21:14 +0000 Subject: [PATCH 100/265] Reinstated reverse_iterator_pair_generator [SVN r9264] --- include/boost/iterator_adaptors.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 5d37871..2bcc601 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,8 @@ // // Revision History: +// 18 Feb 2001 David Abrahams +// Reinstated reverse_iterator_pair_generator // 16 Feb 2001 David Abrahams // Add an implicit conversion operator to operator_arrow_proxy // as CW and BCC workarounds. @@ -861,6 +863,21 @@ struct reverse_iterator_generator Value,Reference,Pointer,Category,Distance> type; }; +template ::value_type> +struct reverse_iterator_pair_generator +{ + typedef boost::detail::iterator_traits::iterator_category category; + typedef iterator_adaptor::iterator_category, + typename boost::detail::iterator_traits::difference_type> iterator; + typedef iterator_adaptor::iterator_category, + typename boost::detail::iterator_traits::difference_type> const_iterator; +}; + template inline typename reverse_iterator_generator::type make_reverse_iterator(BidirectionalIterator base) From 149d07cda06ae1fa62b6e525470e0498406d2ac1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 19 Feb 2001 16:22:03 +0000 Subject: [PATCH 101/265] Fix missing comma bug [SVN r9274] --- include/boost/iterator_adaptors.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 2bcc601..127b08c 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -869,11 +869,11 @@ struct reverse_iterator_pair_generator { typedef boost::detail::iterator_traits::iterator_category category; typedef iterator_adaptor::iterator_category, typename boost::detail::iterator_traits::difference_type> iterator; typedef iterator_adaptor::iterator_category, typename boost::detail::iterator_traits::difference_type> const_iterator; }; From af8dd117d51c33420f36019e0d07451299009f7f Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 19 Feb 2001 20:41:22 +0000 Subject: [PATCH 102/265] Rolled back reverse_iterator_pair_generator again, as it doesn't save typing on a conforming compiler [SVN r9279] --- include/boost/iterator_adaptors.hpp | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 127b08c..0e9ddb2 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,9 @@ // // Revision History: +// 19 Feb 2001 David Abrahams +// Rolled back reverse_iterator_pair_generator again, as it doesn't +// save typing on a conforming compiler. // 18 Feb 2001 David Abrahams // Reinstated reverse_iterator_pair_generator // 16 Feb 2001 David Abrahams @@ -863,21 +866,6 @@ struct reverse_iterator_generator Value,Reference,Pointer,Category,Distance> type; }; -template ::value_type> -struct reverse_iterator_pair_generator -{ - typedef boost::detail::iterator_traits::iterator_category category; - typedef iterator_adaptor::iterator_category, - typename boost::detail::iterator_traits::difference_type> iterator; - typedef iterator_adaptor::iterator_category, - typename boost::detail::iterator_traits::difference_type> const_iterator; -}; - template inline typename reverse_iterator_generator::type make_reverse_iterator(BidirectionalIterator base) From d22edf735aebd1b6e812393f2307460a8887b2eb Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Tue, 20 Feb 2001 16:00:21 +0000 Subject: [PATCH 103/265] put policies type in private [SVN r9290] --- 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 0e9ddb2..e0af582 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -1029,8 +1029,8 @@ class filter_iterator_generator { #ifndef BOOST_MSVC // I don't have any idea why this occurs, but it doesn't seem to hurt too badly. BOOST_STATIC_ASSERT(!is_bidirectional); #endif - public: typedef filter_iterator_policies policies_type; + public: typedef iterator_adaptor type; }; From f27fd095f70783969025d508c41140cc54d5ff3f Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Tue, 27 Feb 2001 05:49:55 +0000 Subject: [PATCH 104/265] new file, part of the iterator adaptors library [SVN r9350] --- include/boost/function_output_iterator.hpp | 55 ++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 include/boost/function_output_iterator.hpp diff --git a/include/boost/function_output_iterator.hpp b/include/boost/function_output_iterator.hpp new file mode 100644 index 0000000..764c118 --- /dev/null +++ b/include/boost/function_output_iterator.hpp @@ -0,0 +1,55 @@ +// (C) Copyright Jeremy Siek 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: + +// 27 Feb 2001 Jeremy Siek +// Initial checkin. + +#ifndef BOOST_FUNCTION_OUTPUT_ITERATOR_HPP +#define BOOST_FUNCTION_OUTPUT_ITERATOR_HPP + +#include + +namespace boost { + + template + class function_output_iterator { + typedef function_output_iterator self; + public: + typedef std::output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + explicit function_output_iterator(const UnaryFunction& f = UnaryFunction()) + : m_f(f) {} + + struct output_proxy { + output_proxy(UnaryFunction& f) : m_f(f) { } + template output_proxy& operator=(const T& value) { + m_f(value); + return *this; + } + UnaryFunction& m_f; + }; + output_proxy operator*() { return output_proxy(m_f); } + self& operator++() { return *this; } + self& operator++(int) { return *this; } + private: + UnaryFunction m_f; + }; + + template + inline function_output_iterator + make_function_output_iterator(const UnaryFunction& f = UnaryFunction()) { + return function_output_iterator(f); + } + +} // namespace boost + +#endif // BOOST_FUNCTION_OUTPUT_ITERATOR_HPP From d924f56ad85299f48e99a311f76bffb36283f94d Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 8 Mar 2001 16:33:14 +0000 Subject: [PATCH 105/265] added support for optional named template parameters [SVN r9487] --- include/boost/iterator_adaptors.hpp | 171 ++++++++++++++++++++++++---- 1 file changed, 151 insertions(+), 20 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index e0af582..a93c842 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,8 @@ // // Revision History: +// 08 Mar 2001 Jeremy Siek +// Added support for optional named template parameters. // 19 Feb 2001 David Abrahams // Rolled back reverse_iterator_pair_generator again, as it doesn't // save typing on a conforming compiler. @@ -104,6 +106,7 @@ # 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 @@ -220,6 +223,9 @@ struct default_iterator_policies void initialize(Base&) { } + // The "type" parameter is a portable mechanism for + // the iterator_adaptor class to tell this member function what + // the Reference type is, which is needed for the return type. template Reference dereference(type, const Base& x) const { return *x; } @@ -429,8 +435,111 @@ namespace detail { }; # endif + + //=========================================================================== + // Specify the defaults for iterator_adaptor's template parameters + + struct default_value_type { + template + struct bind { + typedef typename boost::detail::iterator_traits::value_type type; + }; + }; + struct default_difference_type { + template + struct bind { + typedef typename boost::detail::iterator_traits::difference_type type; + }; + }; + struct default_iterator_category { + template + struct bind { + typedef typename boost::detail::iterator_traits::iterator_category type; + }; + }; + struct default_pointer { + template + struct bind { + typedef typename Traits::value_type Value; + typedef typename boost::detail::iterator_defaults::pointer + type; + }; + }; + struct default_reference { + template + struct bind { + typedef typename Traits::value_type Value; + typedef typename boost::detail::iterator_defaults::reference + type; + }; + }; + + //=========================================================================== + // Support for named template parameters + +#if !defined(__BORLANDC__) + // Borland C++ thinks the nested recursive inheritance here is illegal. + + template + struct iter_traits_gen : public named_template_param_base { + template + struct value_type : public iter_traits_gen { }; + template + struct reference : public iter_traits_gen { }; + template + struct pointer : public iter_traits_gen { }; + template + struct iterator_category : public iter_traits_gen{}; + template + struct difference_type : public iter_traits_gen { }; + + typedef boost::iterator traits; + }; +#endif + + BOOST_NAMED_TEMPLATE_PARAM(value_type); + BOOST_NAMED_TEMPLATE_PARAM(reference); + BOOST_NAMED_TEMPLATE_PARAM(pointer); + BOOST_NAMED_TEMPLATE_PARAM(iterator_category); + BOOST_NAMED_TEMPLATE_PARAM(difference_type); + + template + class iterator_adaptor_traits_gen + { + typedef boost::iterator + Traits0; + + typedef typename get_value_type::type, Traits0 + >::type value_type; + typedef typename get_difference_type::type + difference_type; + typedef typename get_iterator_category::type + iterator_category; + + typedef boost::iterator Traits1; + + typedef typename get_pointer::type pointer; + typedef typename get_reference::type reference; + public: + typedef boost::iterator type; + }; + } // namespace detail + +#if !defined(__BORLANDC__) +struct iterator_traits_generator + : public detail::iter_traits_gen<> { }; +#endif + // This macro definition is only temporary in this file # if !defined(BOOST_MSVC) # define BOOST_ARG_DEPENDENT_TYPENAME typename @@ -469,29 +578,40 @@ template struct undefined; // Distance - the difference_type of the resulting iterator. If not // supplied, iterator_traits::difference_type is used. template ::value_type, class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category, class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type +#else + class Value = detail::default_argument, + class Reference = detail::default_argument, + class Pointer = detail::default_argument, + class Category = detail::default_argument, + class Distance = detail::default_argument +#endif > struct iterator_adaptor : #ifdef BOOST_RELOPS_AMBIGUITY_BUG iterator_comparisons< iterator_adaptor, -#endif - boost::iterator -#ifdef BOOST_RELOPS_AMBIGUITY_BUG -> + typename detail::iterator_adaptor_traits_gen::type + > +#else + detail::iterator_adaptor_traits_gen::type #endif { typedef iterator_adaptor self; public: - typedef Distance difference_type; - typedef typename boost::remove_const::type value_type; - typedef Pointer pointer; - typedef Reference reference; - typedef Category iterator_category; + typedef typename detail::iterator_adaptor_traits_gen::type Traits; + + 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 Base base_type; typedef Policies policies_type; @@ -501,16 +621,19 @@ struct iterator_adaptor : || boost::is_convertible::value)); // Iterators should satisfy one of the known categories +#if 0 BOOST_STATIC_ASSERT(is_input_or_output_iter); +#endif // Iterators >= ForwardIterator must produce real references. +#if 0 BOOST_STATIC_CONSTANT(bool, forward_iter_with_real_reference = (!boost::is_convertible::value || boost::is_same::value || boost::is_same::value)); BOOST_STATIC_ASSERT(forward_iter_with_real_reference); - +#endif public: iterator_adaptor() { } @@ -545,9 +668,9 @@ struct iterator_adaptor : # pragma warning( disable : 4284 ) #endif - typename boost::detail::operator_arrow_result_generator::type + typename boost::detail::operator_arrow_result_generator::type operator->() const - { return detail::operator_arrow(*this, Category()); } + { return detail::operator_arrow(*this, iterator_category()); } #ifdef _MSC_VER # pragma warning(pop) @@ -590,7 +713,7 @@ struct iterator_adaptor : // Moved from global scope to avoid ambiguity with the operator-() which // subtracts iterators from one another. - self operator-(Distance x) const + self operator-(difference_type x) const { self result(*this); return result -= x; } private: compressed_pair m_iter_p; @@ -626,11 +749,14 @@ operator+( template -Distance operator-( +typename iterator_adaptor::difference_type +operator-( const iterator_adaptor& x, const iterator_adaptor& y) { - return x.policies().distance(type(), y.iter(), x.iter()); + typedef typename iterator_adaptor::difference_type difference_type; + return x.policies().distance(type(), y.iter(), x.iter()); } #ifndef BOOST_RELOPS_AMBIGUITY_BUG @@ -967,14 +1093,19 @@ public: { return x == y; } private: - void satisfy_predicate(Iterator& iter) - { - while (m_end != iter && !m_predicate(*iter)) - ++iter; - } + void satisfy_predicate(Iterator& iter); Predicate m_predicate; Iterator m_end; }; +template +void filter_iterator_policies +::satisfy_predicate(Iterator& iter) +{ + while (m_end != iter && !m_predicate(*iter)) + ++iter; +} + + namespace detail { // A type generator returning Base if T is derived from Base, and T otherwise. From 4e29b5aa29acad159f4215076815beac9bf0d6a2 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 8 Mar 2001 17:01:25 +0000 Subject: [PATCH 106/265] removed some #if 0's [SVN r9491] --- include/boost/iterator_adaptors.hpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index a93c842..3c0475e 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -578,19 +578,11 @@ template struct undefined; // Distance - the difference_type of the resulting iterator. If not // supplied, iterator_traits::difference_type is used. template ::value_type, - class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, - class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, - class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category, - class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type -#else class Value = detail::default_argument, class Reference = detail::default_argument, class Pointer = detail::default_argument, class Category = detail::default_argument, class Distance = detail::default_argument -#endif > struct iterator_adaptor : #ifdef BOOST_RELOPS_AMBIGUITY_BUG @@ -621,19 +613,15 @@ struct iterator_adaptor : || boost::is_convertible::value)); // Iterators should satisfy one of the known categories -#if 0 BOOST_STATIC_ASSERT(is_input_or_output_iter); -#endif // Iterators >= ForwardIterator must produce real references. -#if 0 BOOST_STATIC_CONSTANT(bool, forward_iter_with_real_reference = (!boost::is_convertible::value || boost::is_same::value || boost::is_same::value)); BOOST_STATIC_ASSERT(forward_iter_with_real_reference); -#endif public: iterator_adaptor() { } From f6cc2e520f06f718265bab7c1aa6d830f501b7ed Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 8 Mar 2001 19:03:44 +0000 Subject: [PATCH 107/265] parameters following a named parameter list must get their types from the named parameter list and not use the default [SVN r9496] --- include/boost/iterator_adaptors.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 3c0475e..0bd6adf 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -579,10 +579,10 @@ template struct undefined; // supplied, iterator_traits::difference_type is used. template ::type, + class Pointer = typename detail::choose_default_argument::type, + class Category = typename detail::choose_default_argument::type, + class Distance = typename detail::choose_default_argument::type > struct iterator_adaptor : #ifdef BOOST_RELOPS_AMBIGUITY_BUG From cbbe851adbdbc833a34daae83820e1473e0b927d Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 8 Mar 2001 20:01:35 +0000 Subject: [PATCH 108/265] VC++ workaround: the forward_iterator real ref check is not working [SVN r9499] --- include/boost/iterator_adaptors.hpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 0bd6adf..31bc4c3 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -579,10 +579,10 @@ template struct undefined; // supplied, iterator_traits::difference_type is used. template ::type, - class Pointer = typename detail::choose_default_argument::type, - class Category = typename detail::choose_default_argument::type, - class Distance = typename detail::choose_default_argument::type + class Reference = BOOST_ARG_DEPENDENT_TYPENAME detail::choose_default_argument::type, + class Pointer = BOOST_ARG_DEPENDENT_TYPENAME detail::choose_default_argument::type, + class Category = BOOST_ARG_DEPENDENT_TYPENAME detail::choose_default_argument::type, + class Distance = BOOST_ARG_DEPENDENT_TYPENAME detail::choose_default_argument::type > struct iterator_adaptor : #ifdef BOOST_RELOPS_AMBIGUITY_BUG @@ -615,13 +615,18 @@ struct iterator_adaptor : // Iterators should satisfy one of the known categories BOOST_STATIC_ASSERT(is_input_or_output_iter); - // Iterators >= ForwardIterator must produce real references. + // Iterators >= ForwardIterator must produce real references + // as required by the C++ standard requirements in Table 74. BOOST_STATIC_CONSTANT(bool, forward_iter_with_real_reference = (!boost::is_convertible::value || boost::is_same::value || boost::is_same::value)); +#if !defined(BOOST_MSVC) + // This check gives incorrect results in iter_traits_gen_test.cpp BOOST_STATIC_ASSERT(forward_iter_with_real_reference); +#endif + public: iterator_adaptor() { } From eb06c122d1ea9d2e63fd9a7ae44b44b6f6f0bfd4 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 18 Mar 2001 18:37:49 +0000 Subject: [PATCH 109/265] rigged new iterator_traits for backward compatibility [SVN r9577] --- development/boost/iterator_concepts.hpp | 169 +++++--------------- development/boost/iterator_traits.hpp | 123 +++++++++++--- development/libs/iterator/concept_tests.cpp | 66 +++++++- 3 files changed, 205 insertions(+), 153 deletions(-) diff --git a/development/boost/iterator_concepts.hpp b/development/boost/iterator_concepts.hpp index acea6e3..a3ddc8b 100644 --- a/development/boost/iterator_concepts.hpp +++ b/development/boost/iterator_concepts.hpp @@ -3,6 +3,8 @@ #include #include +#include +#include namespace boost_concepts { // Used a different namespace here (instead of "boost") so that the @@ -11,6 +13,7 @@ namespace boost_concepts { //=========================================================================== + // Iterator Access Concepts template class ReadableIteratorConcept { @@ -23,11 +26,12 @@ namespace boost_concepts { void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); boost::function_requires< boost::EqualityComparableConcept >(); - boost::function_requires< boost::DefaultConstructibleConcept >(); - boost::function_requires< - boost::ConvertibleConcept >(); - + boost::DefaultConstructibleConcept >(); + + BOOST_STATIC_ASSERT((boost::is_convertible::value)); + reference r = *i; // or perhaps read(x) value_type v(r); boost::ignore_unused_variable_warning(v); @@ -44,10 +48,11 @@ namespace boost_concepts { void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); boost::function_requires< boost::EqualityComparableConcept >(); - boost::function_requires< boost::DefaultConstructibleConcept >(); - boost::function_requires< - boost::ConvertibleConcept >(); + boost::DefaultConstructibleConcept >(); + + BOOST_STATIC_ASSERT((boost::is_convertible::value)); *i = v; // an alternative could be something like write(x, v) } @@ -65,12 +70,12 @@ namespace boost_concepts { void constraints() { boost::function_requires< ReadableIteratorConcept >(); - - boost::function_requires< - boost::ConvertibleConcept >(); - typedef typename boost::require_same::type req; + BOOST_STATIC_ASSERT((boost::is_convertible::value)); + + BOOST_STATIC_ASSERT((boost::is_same::value)); reference v = *i; boost::ignore_unused_variable_warning(v); @@ -88,13 +93,13 @@ namespace boost_concepts { void constraints() { boost::function_requires< ReadableIteratorConcept >(); - boost::function_requires< WritableIteratorConcept >(); - boost::function_requires< - boost::ConvertibleConcept >(); + WritableIteratorConcept >(); + + BOOST_STATIC_ASSERT((boost::is_convertible::value)); - typedef typename boost::require_same::type req; + BOOST_STATIC_ASSERT((boost::is_same::value)); reference v = *i; boost::ignore_unused_variable_warning(v); @@ -103,24 +108,25 @@ namespace boost_concepts { }; //=========================================================================== + // Iterator Traversal Concepts template class SinglePassIteratorConcept { public: - typedef typename boost::iterator_traits::motion_category - motion_category; + typedef typename boost::iterator_traits::traversal_category + traversal_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 >(); - + boost::DefaultConstructibleConcept >(); + + BOOST_STATIC_ASSERT((boost::is_convertible::value)); + // difference_type must be a signed integral type ++i; @@ -133,30 +139,28 @@ namespace boost_concepts { template class ForwardIteratorConcept { public: - typedef typename boost::iterator_traits::motion_category - motion_category; + typedef typename boost::iterator_traits::traversal_category + traversal_category; void constraints() { boost::function_requires< SinglePassIteratorConcept >(); - boost::function_requires< - boost::ConvertibleConcept >(); + BOOST_STATIC_ASSERT((boost::is_convertible::value)); } }; template class BidirectionalIteratorConcept { public: - typedef typename boost::iterator_traits::motion_category - motion_category; + typedef typename boost::iterator_traits::traversal_category + traversal_category; void constraints() { boost::function_requires< ForwardIteratorConcept >(); - boost::function_requires< - boost::ConvertibleConcept >(); + BOOST_STATIC_ASSERT((boost::is_convertible::value)); --i; (void)i--; @@ -167,18 +171,17 @@ namespace boost_concepts { template class RandomAccessIteratorConcept { public: - typedef typename boost::iterator_traits::motion_category - motion_category; + typedef typename boost::iterator_traits::traversal_category + traversal_category; typedef typename boost::iterator_traits::difference_type difference_type; void constraints() { boost::function_requires< BidirectionalIteratorConcept >(); - boost::function_requires< - boost::ConvertibleConcept >(); - + BOOST_STATIC_ASSERT((boost::is_convertible::value)); + i += n; i = i + n; i = n + i; @@ -190,92 +193,6 @@ namespace boost_concepts { 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 diff --git a/development/boost/iterator_traits.hpp b/development/boost/iterator_traits.hpp index 585f194..6f5d9b2 100644 --- a/development/boost/iterator_traits.hpp +++ b/development/boost/iterator_traits.hpp @@ -2,21 +2,14 @@ #define BOOST_ITERATOR_TRAITS_HPP #include -#include +#include +#include +#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 + // Traversal Categories struct single_pass_iterator_tag { }; struct forward_iterator_tag : public single_pass_iterator_tag { }; struct bidirectional_iterator_tag : public forward_iterator_tag { }; @@ -28,29 +21,113 @@ namespace boost { 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) + + struct error_iterator_tag { }; + + // Inherit from iterator_base if your iterator defines its own + // return_category and traversal_category. Otherwise, the "old style" + // iterator category will be mapped to the return_category and + // traversal_category. + struct new_iterator_base { }; namespace detail { - template - struct pointer_return_category { - typedef constant_lvalue_iterator_tag type; + + struct iter_traits_from_nested_types { + template struct bind { + 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::traversal_category traversal_category; + }; }; - template <> - struct pointer_return_category { - typedef mutable_lvalue_iterator_tag type; + + template + struct choose_lvalue_return { + typedef typename ct_if::value, + boost::constant_lvalue_iterator_tag, + boost::mutable_lvalue_iterator_tag>::type type; }; + + + template + struct iter_category_to_return { + typedef typename ct_if< + is_convertible::value, + typename choose_lvalue_return::type, + typename ct_if< + is_convertible::value, + boost::readable_iterator_tag, + typename ct_if< + is_convertible::value, + boost::writable_iterator_tag, + boost::error_iterator_tag + >::type + >::type + >::type type; + }; + + template + struct iter_category_to_traversal { + typedef typename ct_if< + is_convertible::value, + boost::random_access_iterator_tag, + typename ct_if< + is_convertible::value, + boost::bidirectional_iterator_tag, + typename ct_if< + is_convertible::value, + boost::forward_iterator_tag, + boost::single_pass_iterator_tag>::type + >::type + >::type type; + }; + + struct iter_traits_from_old_traits { + template class bind { + typedef boost::detail::iterator_traits OldTraits; + typedef typename OldTraits::iterator_category Cat; + public: + typedef typename OldTraits::value_type value_type; + typedef typename OldTraits::reference reference; + typedef typename OldTraits::pointer pointer; + typedef typename OldTraits::difference_type difference_type; + typedef iter_category_to_return::type return_category; + typedef iter_category_to_traversal::type traversal_category; + }; + }; + + template + class choose_iter_traits { + typedef typename ct_if::value, + iter_traits_from_nested_types, + iter_traits_from_old_traits>::type Choice; + public: + typedef typename Choice:: template bind type; + }; + } // namespace detail + + template + class iterator_traits + : public detail::choose_iter_traits::type { }; + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) template - struct iterator_traits { + 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 + typedef typename ct_if::value, + boost::constant_lvalue_iterator_tag, + boost::mutable_lvalue_iterator_tag>::type return_category; - typedef random_access_iterator_tag motion_category; + typedef boost::random_access_iterator_tag traversal_category; }; #endif diff --git a/development/libs/iterator/concept_tests.cpp b/development/libs/iterator/concept_tests.cpp index 9ef2ed9..032e889 100644 --- a/development/libs/iterator/concept_tests.cpp +++ b/development/libs/iterator/concept_tests.cpp @@ -1,13 +1,71 @@ #include +#include + +struct new_iterator + : public boost::iterator, + public boost::new_iterator_base +{ + typedef boost::random_access_iterator_tag traversal_category; + typedef boost::mutable_lvalue_iterator_tag return_category; + + int& operator*() const { return *m_x; } + new_iterator& operator++() { return *this; } + new_iterator operator++(int) { return *this; } + new_iterator& operator--() { return *this; } + new_iterator operator--(int) { return *this; } + new_iterator& operator+=(std::ptrdiff_t) { return *this; } + new_iterator operator+(std::ptrdiff_t) { return *this; } + new_iterator& operator-=(std::ptrdiff_t) { return *this; } + std::ptrdiff_t operator-(const new_iterator&) const { return 0; } + new_iterator operator-(std::ptrdiff_t) const { return *this; } + bool operator==(const new_iterator&) const { return false; } + bool operator!=(const new_iterator&) const { return false; } + bool operator<(const new_iterator&) const { return false; } + int* m_x; +}; +new_iterator operator+(std::ptrdiff_t, new_iterator x) { return x; } + +struct old_iterator + : public boost::iterator +{ + int& operator*() const { return *m_x; } + old_iterator& operator++() { return *this; } + old_iterator operator++(int) { return *this; } + old_iterator& operator--() { return *this; } + old_iterator operator--(int) { return *this; } + old_iterator& operator+=(std::ptrdiff_t) { return *this; } + old_iterator operator+(std::ptrdiff_t) { return *this; } + old_iterator& operator-=(std::ptrdiff_t) { return *this; } + old_iterator operator-(std::ptrdiff_t) const { return *this; } + std::ptrdiff_t operator-(const old_iterator&) const { return 0; } + bool operator==(const old_iterator&) const { return false; } + bool operator!=(const old_iterator&) const { return false; } + bool operator<(const old_iterator&) const { return false; } + int* m_x; +}; +old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; } int main() { - boost::function_requires< - boost_concepts::MutableLvalueRandomAccessIteratorConcept >(); + boost::function_requires< + boost_concepts::MutableLvalueIteratorConcept >(); + boost::function_requires< + boost_concepts::RandomAccessIteratorConcept >(); - boost::function_requires< - boost_concepts::ConstantLvalueRandomAccessIteratorConcept >(); + boost::function_requires< + boost_concepts::ConstantLvalueIteratorConcept >(); + boost::function_requires< + boost_concepts::RandomAccessIteratorConcept >(); + boost::function_requires< + boost_concepts::MutableLvalueIteratorConcept >(); + boost::function_requires< + boost_concepts::RandomAccessIteratorConcept >(); + + boost::function_requires< + boost_concepts::MutableLvalueIteratorConcept >(); + boost::function_requires< + boost_concepts::RandomAccessIteratorConcept >(); return 0; } From a110b9fd277cdec7b9bbb020262072b65ea94077 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 18 Mar 2001 19:06:33 +0000 Subject: [PATCH 110/265] new files [SVN r9578] --- .../libs/iterator/iterator_concepts.gif | Bin 0 -> 2994 bytes .../libs/iterator/iterator_concepts.htm | 606 ++++++++++++++++++ 2 files changed, 606 insertions(+) create mode 100644 development/libs/iterator/iterator_concepts.gif create mode 100644 development/libs/iterator/iterator_concepts.htm diff --git a/development/libs/iterator/iterator_concepts.gif b/development/libs/iterator/iterator_concepts.gif new file mode 100644 index 0000000000000000000000000000000000000000..762c0553370a4314dcaeb85aa99811b438dc9d3d GIT binary patch literal 2994 zcmZ?wbh9u|lx4cc(7*r!|NsBj0ns242Bv>K{VPwu1URG=Ir%aer46yuCrO&@2vaI&DVYW z$)=w@eygv)+4h@vJ=3!ihNg1|?O&BnzGufIVeawb$aV1r%NM>VIKi>##|_2Eh|HJG z9X}jrE?CKFSuUVuRFzq^>hKTqF7=zIqE3~EXKnaZVewkBYxa+yQLCkWes@RZyg7K2 z`-R2|oz*;lc;>#I^HSpPpDgV?)w;F4zSTBHo5ess7t#baWM>*PCX`wp+1yj-{C?WD6dQ7cqkI}8nrs;mMJ zs^?gA#%;ODzr<@vjQ-D8%eCe@Z3x`jwWl*I=jtMj<9$niozJ+wGk3<`qpz-|-fQOe z`o((uyZ)YH_4-S;J{<*Nd#av(e7pKbw!v|^zm;EJR($X~GH2qcw>(x~rXLqK>$dBi z)p6H#W%TYa+pCA3U*D3gJu}yOd!E9M^56e*7n^^0cqDv@PM?is_v2Hut<^<;@BH#| z&C2NgeFsgxy}k3k;9{o>+^5h{`tA~>E-?Mx9tA?ZU6W6 z^Z)mf4NP6n?l-Wpg*<5FlA8RWiLdHwLW_*4Mq+DTfJLI`f*s2zrt^-JaOTLYv0qB)RcZTBY`L0 z7yfSGx7RqueziZyuF`GN@jH)#UC%6SU6L|0^$TAoPiouZnNjZwmj!!&oOH>uCv#hn zh2+gh$$2?}8`BJ9-c3!LS;cF0)5{{PSaMd|Gm(txwRJa^ExsTS6%jd6F>A#l*4o3~ zbAxTFxF$I~G=1fmy6Ne)s5c_JuC6-7d-6pP!%C^ED<``xnY21}t5je~KttB4EW2w? z%Ti0atp16tDxayvH#hn&SB~=CJFgxlA751|zUB0_TW=z7I(55lnR-Mb+dryxr^F7! zXS-$vo&2`x$?6SEkM1Ql3^N z$7LAt^VQ$nc}}mBkLX#)ZezbxDYEiMc)L7s?^l;&nqk|7ZwGJPl>4r8<^3nGjS~g$rwi`;amzLB(=6;M`CbrSRb8v+KsMX0GLLO-k@_d$cy!(?I=L)R_w@Ne4VrHn2&z_};qE zzBW^kyX9Pv)VW`&6F2SbNij%j`qFm6QG)5Dx36Sp%BJ+K8@GBZ%eRDY%=pB@qNdnp zbf@RI#WlOlbG_RWRww>n({!j;pitN;=z20%?__n=1&VPP|y?inK_?v=r zHt(aA73Qz7{4Bbx`>W7`Crf7Rv6j;>KkE5}(`2RDn~F^p2^9SvzIY@YEjI&H%)cKP&U z4bxdT`#*kD_LWpIZhd_6SY7SswO0TkMqK`0C3&l^d7+c)Hegeca+= z`?!1w%iZD_zFX-9X3x)`-?+Kt73T^E(Ubt00HuYUFPB^Xd)O%7*7a`o?VNsROUYH; zNhNbR?q+N-d3CW_&SQ~c?nMW0tsv%!B1*vV zrY4>8p8c+?OFQ(5=hq5nEzPSYn;Yi^tpBoSk<`}3P7QNZl9w*`3H?xzbGm!`HmO5j z1GPKD_6q+kxz)Uh>1=M2u=47NYuCE|`bRfhn&KyObp_KR(f(^4%2%eiZs}RNy2;9U zR)Xq{W3dknvP7>w4P2;lsH&k*);>gH<(WefrzUOK5bC@p^{DbO_hmlo`|oP*O*!hi zuw&Y~Kgp{&{%*ZddN!xs`sKqDZq?T=E!$dC6nls3zDu;nSC&4rC-Qe?{{7gon$c&~ zf~Bv#|8DPEA2+SrK2>OST6E;pk2$Ls#x7DUejRfn$e?ef>pJ zFYYZh+`d!U^;PBR>j(bTPMGlLX+(`?>cJgseiLr9=GV@zc4C{AQs2umXG7Z22ZpNC z3-cDMJYid|GA%0bu*|bVHP&Y?@i*^Sq9nJ`-8(0#XOYFxozWkwFwm-}{o&^7ySiZ?o>cKCI7sVfW8RC&NFN>)M81 zN?Dxv$z-?K_U#Y12gZGUd-Ft31jB7n@vx~O6Zf3)IeJulLs5&-+8aA=?2jwhmC^iR z_QN;-n%JLLPI$Td^JLNA&QI&MO|6eDna;?&d7b37&8(~QJhY@Oob}JdGRD1ot00^C z)@tIVC$k<_&-K~d{`dNh^l2O8<#}J-vb?#ztZ$>%4(|KG*Uy}rrni2{QO->fr#H0- z&5`3?R(#^^{RPYJ^A-L^A`GV+>vy}F^@SdsmsvH5U*qGYnme9>xrHC| zq<5ZObuGAe&L^k(x!M0V#J#C`lWn}av+?Zo>tV%f|0y>dY+F8CefMqe`8~53E5eO_ zYriNrKE=u|`{1MBx3mKf-fZMwo%y+F``x-_R*lEPQ{yDLFLxbPikh*vL}-##lI0&W zZsk|TZkHzPm8zbVyZK$zkF$IBGTP*c{D1e7u`}klag)UTrSER9X8P&&e4h2O0PSso zyQ|+D9;?1;IloxcQu=kzVw={|8L=d_ZZP3E)Grzp*HJHF^`+!sK?(2ff(Tc`@e*N`GzOki+T=;de#*UVpkj99B<%XAuXuU_%X2YrF*0Jibm-Zjj}Hq84ow-wGS30_jrt8m#9H>$tR>a+wx+L4b-Iw!#-^U0qh5KhG}3NL!Y;MqC#s&WuU5w`s>&>H zFH}>n|6ck_xTA8Lk*!knd*Q0d5zz(BSt`>zo*B%^zHXk?cRl)-QfJ=u+>{drj)5gM z!mhJ53_I1sqi@8nyymP~lD$qn-!mfH + + + +Iterator Concepts + +C++ Boost + +
+ +

Iterator Concepts

+ +

The standard iterator concepts (the iterator requirements defined +in the C++ Standard) have a flaw. They glom together two separate +issues into a single set of concepts. The two issues are iterator +traversal and dereference return type semantics. These two issues are +inherently orthogonal and therefore ought to be represented by two +separate sets of concepts. The concepts described here do just +that.

+ +One set of concepts handles the return type semantics: + + +The other set of concepts handles iterator traversal: + + + +

+
+ + + +
Figure 1: +The iterator concepts and refinement relationships. +
+
+

+ +

Relationship with the standard iterator concepts

+ +

+std::Input Iterator refines boost::Single-Pass Iterator and +boost::ReadableIterator. + +

+std::Output Iterator refines boost::Single-Pass Iterator and +boost::Writable Iterator. + +

+std::Forward Iterator refines boost::Forward Iterator and +boost::Constant Lvalue Iterator or boost::Mutable Lvalue Iterator. + +

+std::Bidirectional Iterator refines boost::Bidirectional Iterator and +boost::Constant Lvalue Iterator or boost::Mutable Lvalue Iterator. + +

+std::Random Access Iterator refines boost::Random Access Iterator and +boost::Constant Lvalue Iterator or boost::Mutable Lvalue Iterator. + + +

Notation

+ + + + + + + + + + + + + + + + + +
XThe iterator type.
TThe value type of X.
x, yAn object of type X.
tAn object of type T.
+ +

+ +


+ +

+Readable Iterator +

+ +A Readable Iterator is an iterator that dereferences to produce an +rvalue that is convertible to the value_type of the +iterator. For example, derefencing may return a temporary object and +therefore it would be a mistake to bind the result to a reference. +Also, an attempt to assign a value to the result will most likely +cause an error. + +
+  template <class Readable Iterator>
+  void foo(Readable Iterator x)
+  {
+    typedef std::iterator_traits<Readable Iterator>::value_type T;
+    T t = *x;  // Read a value. This is OK.
+    T& s = *x; // Bind to a reference. This is a bad idea.
+    *x = t;    // Try to assign. This is a really bad idea.
+  }
+
+ + +

Associated Types

+ + + + + + + + + + + + + + + +
Value typeboost::iterator_traits<X>::value_type + The type of the value obtained by dereferencing a LvalueIterator +
Return Categoryboost::iterator_traits<X>::return_category + A type convertible to boost::readable_iterator_tag +
+ +

Refinement of

+ +Assignable, +Equality Comparable, +Default Constructible + +

Valid expressions

+ + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Dereference*x Convertible to T.
Member accessx->mT is a type with a member named m. +   +
+ +

+ +


+ +

+Writable Iterator +

+ +A Writable Iterator is an iterator that can be used to store a value +using the dereference-assignment expression. + +

Definitions

+ +If x is an Writable Iterator of type X, then the +expression *x = a; stores the value a into +x. Note that operator=, like other C++ functions, +may be overloaded; it may, in fact, even be a template function. In +general, then, a may be any of several different types. A +type A belongs to the set of value types of X +if, for an object a of type A, *x = a; is +well-defined and does not require performing any non-trivial +conversions on a. + +

Associated Types

+ + + + + + + + + +
Return Categoryboost::iterator_traits<X>::return_category + A type convertible to boost::writable_iterator_tag +
+ + + +

Refinement of

+ +Assignable, +Equality Comparable, +Default Constructible + +

Valid expressions

+ + + + + + + + + + +
NameExpressionReturn type
Dereference assignment*x = aunspecified
+ +

+ +


+ +

+Constant Lvalue Iterator +

+ +A Constant Lvalue Iterator is an iterator that dereferences to produce a +const reference to the pointed-to object, i.e., the associated +reference type is const T&. Changing the value +of or destroying an iterator that models Constant Lvalue Iterator does +not invalidate pointers and references previously obtained from that +iterator. + + +

Refinement of

+ +Readable Iterator + +

Associated Types

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Value typeboost::iterator_traits<X>::value_type + The type of the value obtained by dereferencing a Constant Lvalue Iterator. +
Reference typeboost::iterator_traits<X>::reference + The return type of operator*(), which must be + const T&. +
POinter typeboost::iterator_traits<X>::pointer + The pointer to the value type, which must be const T*. +
Return Categoryboost::iterator_traits<X>::return_category + A type convertible to boost::constant_lvalue_iterator_tag +
+ + +

Valid expressions

+ + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Dereference*x const T&
Member accessx->mT is a type with a member named m. +   +
+ + +

+Mutable Lvalue Iterator +

+ +A Mutable Lvalue Iterator is an iterator that dereferences to produce a +reference to the pointed-to object. The associated reference +type is T&. Changing the value of or destroying an +iterator that models Mutable Lvalue Iterator does not invalidate +pointers and references previously obtained from that iterator. + +

Refinement of

+ +Readable Iterator and +Writable Iterator. + + + +

Associated Types

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Value typeboost::iterator_traits<X>::value_type + The type of the value obtained by dereferencing a Mutable Lvalue Iterator. +
Reference typeboost::iterator_traits<X>::reference + The return type of operator*(), which is + T&. +
Pointer typeboost::iterator_traits<X>::pointer + The pointer to the value type, which is T*. +
Return Categoryboost::iterator_traits<X>::return_category + A type convertible to boost::mutable_lvalue_iterator_tag +
+ + +

Valid expressions

+ + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Dereference*x  T&
Member accessx->mT is a type with a member named m. +   +
+ +

+


+ +

+Single-Pass Iterator +

+ +A Single-Pass Iterator is an iterator that can be incremented to +traverse through a sequence of objects, but the sequence can only be +traversed a single time. + +

Associated types

+ + + + + + + + + + + + + + +
Difference typeboost::iterator_traits<X>::difference_type + A signed integral type used to represent the distance from one + iterator to another, or the number of elements in a range. +
Traversal Categoryboost::iterator_traits<X>::traversal_category + A type convertible to boost::single_pass_iterator_tag +
+ +

Valid expressions

+ + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Preincrement++i X&
Postincrement(void)i++  
+ +

+


+ +

+Forward Iterator +

+ +The Forward Iterator is an iterator that can be incremented. Also, it +is permissible to make multiple passes through the sequence. + +

Refinement of

+ +Single-Pass Iterator + +

Associated types

+ + + + + + + +
Traversal Categoryboost::iterator_traits<X>::traversal_category + A type convertible to boost::forward_iterator_tag +
+ +

+


+ +

+Bidirectional Iterator +

+ +An iterator that can be incremented and decremented. + +

Refinement of

+ +Forward Iterator + +

Associated types

+ + + + + + + +
Traversal Categoryboost::iterator_traits<X>::traversal_category + A type convertible to boost::bidirectional_iterator_tag +
+ +

Valid expressions

+ + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Predecrement--i X&
Postdecrementi-- X
+ +

+


+ +

+Random Access Iterator +

+ +An iterator that provides constant-time methods for moving forward and +backward in arbitrary-sized steps + +

Refinement of

+ +Bidirectional Iterator + +

Associated types

+ + + + + + + +
Traversal Categoryboost::iterator_traits<X>::traversal_category + A type convertible to boost::random_access_iterator_tag +
+ +

Valid expressions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Iterator additioni += n X&
Iterator additioni + n or n + i X
Iterator subtractioni -= n X&
Iterator subtractioni - n X
Differencei - j boost::iterator_traits<X>::difference_type
Element operatori[n]X must be a model of + Readable Iterator. The same return type as *i.
Element assignmenti[n] = tX must be a model of + Writable Iterator.unspecified
+ + +
+ +
+ + +
Copyright © 2000 +Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu) +
+ + + From 6de193442007f8367a4bcd3bd6e449f0ba2c3110 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 19 Mar 2001 17:41:49 +0000 Subject: [PATCH 111/265] new file [SVN r9585] --- development/libs/iterator/iterator_traits.htm | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 development/libs/iterator/iterator_traits.htm diff --git a/development/libs/iterator/iterator_traits.htm b/development/libs/iterator/iterator_traits.htm new file mode 100644 index 0000000..5ebc332 --- /dev/null +++ b/development/libs/iterator/iterator_traits.htm @@ -0,0 +1,92 @@ + + + + Boost Iterator Traits + + + +

Boost Iterator Traits

+Header boost/iterator_traits.hpp + +
+namespace boost {
+
+  template <typename Iterator>
+  struct iterator_traits
+  {
+    if (Iterator inherits from new_iterator_base) {
+      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::traversal_category traversal_category;
+    } else {
+      typedef std::iterator_traits<Iterator> OldTraits;
+      typedef typename OldTraits::value_type value_type;
+      typedef typename OldTraits::reference reference;
+      typedef typename OldTraits::pointer pointer;
+      typedef typename OldTraits::difference_type difference_type;
+
+      typedef typename OldTraits::iterator_category Cat;
+
+      // Determine the traversal_category based on the old iterator_category
+      if (Cat inherits from std::random_access_iterator_tag)
+        typedef boost::random_access_iterator_tag traversal_category;
+      else if (Cat inherits from std::bidirectional_iterator_tag)
+        typedef boost::bidirectional_iterator_tag traversal_category;
+      else if (Cat inherits from std::forward_iterator_tag)
+        typedef boost::forward_iterator_tag traversal_category;
+      else 
+        typedef boost::single_pass_iterator_tag traversal_category;
+
+      // Determine the return_category based on the old iterator_category and value_type
+      if (Cat inherits from std::forward_iterator_tag)
+        if (is-const(T))
+          typedef boost::constant_lvalue_iterator_tag return_category;
+        else
+          typedef boost::mutable_lvalue_iterator_tag return_category;
+      else if (Cat inherits from std::input_iterator_tag)
+        typedef boost::readable_iterator_tag return_category;
+      else if (Cat inherits from std::output_iterator_tag)
+        typedef boost::writable_iterator_tag return_category;
+      else
+        typedef boost::error_iterator_tag return_category;
+    }
+  };
+
+  template <typename T>
+  struct iterator_traits<T*>
+  {
+    typedef T value_type;
+    typedef T& reference;
+    typedef T* pointer;
+    typedef std::ptrdiff_t difference_type;
+    if (is-const(T))
+      typedef boost::constant_lvalue_iterator_tag return_category;
+    else
+      typedef boost::mutable_lvalue_iterator_tag return_category;
+    typedef boost::random_access_iterator_tag traversal_category;
+  };
+
+}
+
+ +
+
jeremy siek
+ + +Last modified: Sun Mar 18 17:10:26 EST 2001 + + + From 84663ff2e2ccd47de4e18a05c887ab7bfd96732e Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 19 Mar 2001 18:01:41 +0000 Subject: [PATCH 112/265] added more doc [SVN r9586] --- development/libs/iterator/iterator_traits.htm | 49 ++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/development/libs/iterator/iterator_traits.htm b/development/libs/iterator/iterator_traits.htm index 5ebc332..1574f0a 100644 --- a/development/libs/iterator/iterator_traits.htm +++ b/development/libs/iterator/iterator_traits.htm @@ -14,13 +14,58 @@ Boost Iterator Traits - + +C++ Boost +
+

Boost Iterator Traits

Header boost/iterator_traits.hpp +

+The boost::iterator_traits class provides access to the +associated types of iterators that model the Boost Iterator Concepts, which are a +replacement for the iterator requirements in the C++ standard. +The main difference between std::iterator_traits and +boost::iterator_traits is that the iterator_category +type has been removed, and replaced with two new types: + +

    +
  • traversal_category:   Can the iterator go forward, backward, etc.? +
  • return_category:   Is the iterator read or write only? + Is the dereferenced type an lvalue? +
+ + +

+An important feature of the boost::iterator_traits is that it +is backwards compatible, i.e., it will automatically work for +iterators for which there are valid definitions of +std::iterator_traits. The old iterator_category is +mapped to the appropriate traversal and return categories. + +

+When creating a new iterator type that is meant to work with +boost::iterator_traits, you can either create a +specialization of boost::iterator_traits for your iterator +type, or you can provide all the necessary associated types as nested +typedefs. In this case, your iterator class will need to inherit from +new_iterator_base to let boost::iterator_traits know +that it will be able to find typedefs for traversal_category +and return_category in you iterator class. + +

 namespace boost {
 
+  // Inherit from iterator_base if your iterator defines its own
+  // return_category and traversal_category. Otherwise, the "old style"
+  // iterator category will be mapped to the return_category and
+  // traversal_category.
+  struct new_iterator_base { };
+
   template <typename Iterator>
   struct iterator_traits
   {
@@ -86,7 +131,7 @@ namespace boost {
     
jeremy siek
-Last modified: Sun Mar 18 17:10:26 EST 2001 +Last modified: Mon Mar 19 12:59:30 EST 2001 From 0846ad5fd070fc241b2b258b682248ee1c999d7e Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 19 Mar 2001 18:05:17 +0000 Subject: [PATCH 113/265] added links to iterator_traits.htm [SVN r9587] --- .../libs/iterator/iterator_concepts.htm | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/development/libs/iterator/iterator_concepts.htm b/development/libs/iterator/iterator_concepts.htm index 05c2258..b81b054 100644 --- a/development/libs/iterator/iterator_concepts.htm +++ b/development/libs/iterator/iterator_concepts.htm @@ -157,7 +157,7 @@ cause an error. Value type - boost::iterator_traits<X>::value_type + boost::iterator_traits<X>::value_type The type of the value obtained by dereferencing a LvalueIterator @@ -165,7 +165,7 @@ cause an error. Return Category - boost::iterator_traits<X>::return_category + boost::iterator_traits<X>::return_category A type convertible to boost::readable_iterator_tag @@ -228,7 +228,7 @@ conversions on a. Return Category - boost::iterator_traits<X>::return_category + boost::iterator_traits<X>::return_category A type convertible to boost::writable_iterator_tag @@ -283,7 +283,7 @@ iterator. Value type - boost::iterator_traits<X>::value_type + boost::iterator_traits<X>::value_type The type of the value obtained by dereferencing a Constant Lvalue Iterator. @@ -291,7 +291,7 @@ iterator. Reference type - boost::iterator_traits<X>::reference + boost::iterator_traits<X>::reference The return type of operator*(), which must be const T&. @@ -300,7 +300,7 @@ iterator. POinter type - boost::iterator_traits<X>::pointer + boost::iterator_traits<X>::pointer The pointer to the value type, which must be const T*. @@ -308,7 +308,7 @@ iterator. Return Category - boost::iterator_traits<X>::return_category + boost::iterator_traits<X>::return_category A type convertible to boost::constant_lvalue_iterator_tag @@ -361,7 +361,7 @@ pointers and references previously obtained from that iterator. Value type - boost::iterator_traits<X>::value_type + boost::iterator_traits<X>::value_type The type of the value obtained by dereferencing a Mutable Lvalue Iterator. @@ -369,7 +369,7 @@ pointers and references previously obtained from that iterator. Reference type - boost::iterator_traits<X>::reference + boost::iterator_traits<X>::reference The return type of operator*(), which is T&. @@ -378,7 +378,7 @@ pointers and references previously obtained from that iterator. Pointer type - boost::iterator_traits<X>::pointer + boost::iterator_traits<X>::pointer The pointer to the value type, which is T*. @@ -386,7 +386,7 @@ pointers and references previously obtained from that iterator. Return Category - boost::iterator_traits<X>::return_category + boost::iterator_traits<X>::return_category A type convertible to boost::mutable_lvalue_iterator_tag @@ -431,7 +431,7 @@ traversed a single time. - + - + @@ -484,7 +484,7 @@ is permissible to make multiple passes through the sequence.
Difference typeboost::iterator_traits<X>::difference_typeboost::iterator_traits<X>::difference_type A signed integral type used to represent the distance from one iterator to another, or the number of elements in a range. @@ -440,7 +440,7 @@ traversed a single time.
Traversal Categoryboost::iterator_traits<X>::traversal_categoryboost::iterator_traits<X>::traversal_category A type convertible to boost::single_pass_iterator_tag
- + @@ -509,7 +509,7 @@ An iterator that can be incremented and decremented.
Traversal Categoryboost::iterator_traits<X>::traversal_categoryboost::iterator_traits<X>::traversal_category A type convertible to boost::forward_iterator_tag
- + @@ -550,7 +550,7 @@ backward in arbitrary-sized steps
Traversal Categoryboost::iterator_traits<X>::traversal_categoryboost::iterator_traits<X>::traversal_category A type convertible to boost::bidirectional_iterator_tag
- + @@ -576,7 +576,7 @@ backward in arbitrary-sized steps - + From e48cdcb94fc6d4f0faafb51de4cb92de1776a242 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 19 Mar 2001 19:35:51 +0000 Subject: [PATCH 114/265] blah [SVN r9588] --- development/libs/iterator/concept_tests.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/development/libs/iterator/concept_tests.cpp b/development/libs/iterator/concept_tests.cpp index 032e889..df0fd02 100644 --- a/development/libs/iterator/concept_tests.cpp +++ b/development/libs/iterator/concept_tests.cpp @@ -45,9 +45,13 @@ struct old_iterator }; old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; } +struct bar { }; +void foo(bar) { } + int main() { +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) boost::function_requires< boost_concepts::MutableLvalueIteratorConcept >(); boost::function_requires< @@ -57,6 +61,7 @@ main() boost_concepts::ConstantLvalueIteratorConcept >(); boost::function_requires< boost_concepts::RandomAccessIteratorConcept >(); +#endif boost::function_requires< boost_concepts::MutableLvalueIteratorConcept >(); From d7908fb81f82f7a84d00a3b2cf4caf1dbef706bd Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 5 Apr 2001 02:32:00 +0000 Subject: [PATCH 115/265] added public before the typedef for "type" in non_bidirectional_category [SVN r9711] --- include/boost/iterator_adaptors.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 31bc4c3..b05bef2 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -1129,6 +1129,7 @@ namespace detail { # else // is_convertible doesn't work with MWERKS typedef typename iterator_traits::iterator_category input_category; + public: typedef typename if_true<( boost::is_same::value || boost::is_same::value From 9582b2223c661c292599320682cb1674ef70ae10 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Wed, 25 Apr 2001 00:24:50 +0000 Subject: [PATCH 116/265] Change all eGroups references to YahooGroups [SVN r9979] --- development/libs/iterator/iterator_concepts.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/development/libs/iterator/iterator_concepts.htm b/development/libs/iterator/iterator_concepts.htm index b81b054..bca0841 100644 --- a/development/libs/iterator/iterator_concepts.htm +++ b/development/libs/iterator/iterator_concepts.htm @@ -76,7 +76,7 @@ The other set of concepts handles iterator traversal: - +
Traversal Categoryboost::iterator_traits<X>::traversal_categoryboost::iterator_traits<X>::traversal_category A type convertible to boost::random_access_iterator_tag i - n X
Differencei - j boost::iterator_traits<X>::difference_typei - j boost::iterator_traits<X>::difference_type
Element operator i[n]
Figure 1: The iterator concepts and refinement relationships.

From d7023154a3d0f239703b54bb5901c605f6a14ccb Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Wed, 25 Apr 2001 13:22:53 +0000 Subject: [PATCH 117/265] Fix broken hyperlinks [SVN r9980] --- development/libs/iterator/iterator_concepts.htm | 4 ++-- development/libs/iterator/iterator_traits.htm | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/development/libs/iterator/iterator_concepts.htm b/development/libs/iterator/iterator_concepts.htm index bca0841..0848ab5 100644 --- a/development/libs/iterator/iterator_concepts.htm +++ b/development/libs/iterator/iterator_concepts.htm @@ -38,7 +38,7 @@ Iterator Concepts -C++ Boost
@@ -599,7 +599,7 @@ backward in arbitrary-sized steps
Copyright © 2000 -Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu) +Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu)
diff --git a/development/libs/iterator/iterator_traits.htm b/development/libs/iterator/iterator_traits.htm index 1574f0a..40f3026 100644 --- a/development/libs/iterator/iterator_traits.htm +++ b/development/libs/iterator/iterator_traits.htm @@ -16,7 +16,7 @@ -C++ Boost
From 42e4db1539fc92bb50b15ab439633fe2d67e1983 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 3 Jun 2001 21:06:49 +0000 Subject: [PATCH 118/265] updated to match my paper to the committee [SVN r10259] --- development/boost/iterator_categories.hpp | 159 ++++++++++++++++++++++ development/boost/iterator_concepts.hpp | 67 +++------ development/boost/iterator_traits.hpp | 137 ------------------- 3 files changed, 179 insertions(+), 184 deletions(-) create mode 100644 development/boost/iterator_categories.hpp delete mode 100644 development/boost/iterator_traits.hpp diff --git a/development/boost/iterator_categories.hpp b/development/boost/iterator_categories.hpp new file mode 100644 index 0000000..138a5be --- /dev/null +++ b/development/boost/iterator_categories.hpp @@ -0,0 +1,159 @@ +#ifndef BOOST_ITERATOR_CATEGORIES_HPP +#define BOOST_ITERATOR_CATEGORIES_HPP + +#include +#include +#include +#include +#include + +namespace boost { + + // Return Type Categories + struct readable_iterator_tag { }; + struct writable_iterator_tag { }; + struct swappable_iterator_tag { }; + struct mutable_lvalue_iterator_tag : + virtual public writable_iterator_tag, + virtual public readable_iterator_tag { }; + struct constant_lvalue_iterator_tag : + virtual public readable_iterator_tag { }; + + // Traversal Categories + struct forward_traversal_tag { }; + struct bidirectional_traversal_tag : public forward_traversal_tag { }; + struct random_access_traversal_tag : public bidirectional_traversal_tag { }; + + struct error_iterator_tag { }; + + // Inherit from iterator_base if your iterator defines its own + // return_category and traversal_category. Otherwise, the "old style" + // iterator category will be mapped to the return_category and + // traversal_category. + struct new_iterator_base { }; + + namespace detail { + + struct return_category_from_nested_type { + template struct bind { + typedef typename Iterator::return_category type; + }; + }; + + struct traversal_category_from_nested_type { + template struct bind { + typedef typename Iterator::traversal_category type; + }; + }; + + template + struct choose_lvalue_return { + typedef typename ct_if::value, + boost::constant_lvalue_iterator_tag, + boost::mutable_lvalue_iterator_tag>::type type; + }; + + + template + struct iter_category_to_return { + typedef typename ct_if< + is_convertible::value, + typename choose_lvalue_return::type, + typename ct_if< + is_convertible::value, + boost::readable_iterator_tag, + typename ct_if< + is_convertible::value, + boost::writable_iterator_tag, + boost::error_iterator_tag + >::type + >::type + >::type type; + }; + + template + struct iter_category_to_traversal { + typedef typename ct_if< + is_convertible::value, + random_access_traversal_tag, + typename ct_if< + is_convertible::value, + bidirectional_traversal_tag, + forward_traversal_tag + >::type + >::type type; + }; + + struct return_category_from_old_traits { + template class bind { + typedef boost::detail::iterator_traits OldTraits; + typedef typename OldTraits::iterator_category Cat; + typedef typename OldTraits::value_type value_type; + public: + typedef iter_category_to_return::type type; + }; + }; + + struct traversal_category_from_old_traits { + template class bind { + typedef boost::detail::iterator_traits OldTraits; + typedef typename OldTraits::iterator_category Cat; + public: + typedef iter_category_to_traversal::type type; + }; + }; + + template + class choose_return_category { + typedef typename ct_if::value, + return_category_from_nested_type, + return_category_from_old_traits>::type Choice; + public: + typedef typename Choice:: template bind::type type; + }; + + template + class choose_traversal_category { + typedef typename ct_if::value, + traversal_category_from_nested_type, + traversal_category_from_old_traits>::type Choice; + public: + typedef typename Choice:: template bind::type type; + }; + + } // namespace detail + + template + struct return_category { + typedef typename detail::choose_return_category::type type; + }; + + + template + struct traversal_category { + typedef typename detail::choose_traversal_category::type type; + }; + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + template + struct return_category + { + typedef typename ct_if::value, + constant_lvalue_iterator_tag, + mutable_lvalue_iterator_tag>::type type; + }; + + template + struct traversal_category + { + typedef random_access_traversal_tag type; + }; + +#endif + +} // namespace boost + +#endif // BOOST_ITERATOR_CATEGORIES_HPP diff --git a/development/boost/iterator_concepts.hpp b/development/boost/iterator_concepts.hpp index a3ddc8b..a30ff17 100644 --- a/development/boost/iterator_concepts.hpp +++ b/development/boost/iterator_concepts.hpp @@ -2,7 +2,7 @@ #define BOOST_ITERATOR_CONCEPTS_HPP #include -#include +#include #include #include @@ -18,10 +18,9 @@ namespace boost_concepts { 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; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::reference reference; + typedef typename boost::return_category::type return_category; void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); @@ -42,8 +41,7 @@ namespace boost_concepts { template class WritableIteratorConcept { public: - typedef typename boost::iterator_traits::return_category - return_category; + typedef typename boost::return_category::type return_category; void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); @@ -54,7 +52,7 @@ namespace boost_concepts { BOOST_STATIC_ASSERT((boost::is_convertible::value)); - *i = v; // an alternative could be something like write(x, v) + *i = v; // a good alternative could be something like write(x, v) } ValueType v; Iterator i; @@ -63,10 +61,9 @@ namespace boost_concepts { 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; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::reference reference; + typedef typename boost::return_category::type return_category; void constraints() { boost::function_requires< ReadableIteratorConcept >(); @@ -86,10 +83,9 @@ namespace boost_concepts { 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; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::reference reference; + typedef typename boost::return_category::type return_category; void constraints() { boost::function_requires< ReadableIteratorConcept >(); @@ -111,12 +107,9 @@ namespace boost_concepts { // Iterator Traversal Concepts template - class SinglePassIteratorConcept { + class ForwardIteratorConcept { public: - typedef typename boost::iterator_traits::traversal_category - traversal_category; - typedef typename boost::iterator_traits::difference_type - difference_type; + typedef typename boost::traversal_category::type traversal_category; void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); @@ -125,42 +118,23 @@ namespace boost_concepts { boost::DefaultConstructibleConcept >(); BOOST_STATIC_ASSERT((boost::is_convertible::value)); - - // difference_type must be a signed integral type - + boost::forward_traversal_tag*>::value)); ++i; (void)i++; } - Iterator i; }; - template - class ForwardIteratorConcept { - public: - typedef typename boost::iterator_traits::traversal_category - traversal_category; - - void constraints() { - boost::function_requires< SinglePassIteratorConcept >(); - - BOOST_STATIC_ASSERT((boost::is_convertible::value)); - } - }; - template class BidirectionalIteratorConcept { public: - typedef typename boost::iterator_traits::traversal_category - traversal_category; + typedef typename boost::traversal_category::type traversal_category; void constraints() { boost::function_requires< ForwardIteratorConcept >(); BOOST_STATIC_ASSERT((boost::is_convertible::value)); + boost::bidirectional_traversal_tag*>::value)); --i; (void)i--; @@ -171,16 +145,15 @@ namespace boost_concepts { template class RandomAccessIteratorConcept { public: - typedef typename boost::iterator_traits::traversal_category - traversal_category; - typedef typename boost::iterator_traits::difference_type + typedef typename boost::traversal_category::type traversal_category; + typedef typename std::iterator_traits::difference_type difference_type; void constraints() { boost::function_requires< BidirectionalIteratorConcept >(); BOOST_STATIC_ASSERT((boost::is_convertible::value)); + boost::random_access_traversal_tag*>::value)); i += n; i = i + n; diff --git a/development/boost/iterator_traits.hpp b/development/boost/iterator_traits.hpp deleted file mode 100644 index 6f5d9b2..0000000 --- a/development/boost/iterator_traits.hpp +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef BOOST_ITERATOR_TRAITS_HPP -#define BOOST_ITERATOR_TRAITS_HPP - -#include -#include -#include -#include -#include - -namespace boost { - - // Traversal 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 { }; - - struct error_iterator_tag { }; - - // Inherit from iterator_base if your iterator defines its own - // return_category and traversal_category. Otherwise, the "old style" - // iterator category will be mapped to the return_category and - // traversal_category. - struct new_iterator_base { }; - - namespace detail { - - struct iter_traits_from_nested_types { - template struct bind { - 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::traversal_category traversal_category; - }; - }; - - template - struct choose_lvalue_return { - typedef typename ct_if::value, - boost::constant_lvalue_iterator_tag, - boost::mutable_lvalue_iterator_tag>::type type; - }; - - - template - struct iter_category_to_return { - typedef typename ct_if< - is_convertible::value, - typename choose_lvalue_return::type, - typename ct_if< - is_convertible::value, - boost::readable_iterator_tag, - typename ct_if< - is_convertible::value, - boost::writable_iterator_tag, - boost::error_iterator_tag - >::type - >::type - >::type type; - }; - - template - struct iter_category_to_traversal { - typedef typename ct_if< - is_convertible::value, - boost::random_access_iterator_tag, - typename ct_if< - is_convertible::value, - boost::bidirectional_iterator_tag, - typename ct_if< - is_convertible::value, - boost::forward_iterator_tag, - boost::single_pass_iterator_tag>::type - >::type - >::type type; - }; - - struct iter_traits_from_old_traits { - template class bind { - typedef boost::detail::iterator_traits OldTraits; - typedef typename OldTraits::iterator_category Cat; - public: - typedef typename OldTraits::value_type value_type; - typedef typename OldTraits::reference reference; - typedef typename OldTraits::pointer pointer; - typedef typename OldTraits::difference_type difference_type; - typedef iter_category_to_return::type return_category; - typedef iter_category_to_traversal::type traversal_category; - }; - }; - - template - class choose_iter_traits { - typedef typename ct_if::value, - iter_traits_from_nested_types, - iter_traits_from_old_traits>::type Choice; - public: - typedef typename Choice:: template bind type; - }; - - } // namespace detail - - template - class iterator_traits - : public detail::choose_iter_traits::type { }; - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - - template - struct iterator_traits - { - typedef T value_type; - typedef T& reference; - typedef T* pointer; - typedef std::ptrdiff_t difference_type; - typedef typename ct_if::value, - boost::constant_lvalue_iterator_tag, - boost::mutable_lvalue_iterator_tag>::type - return_category; - typedef boost::random_access_iterator_tag traversal_category; - }; - -#endif - -} // namespace boost - -#endif // BOOST_ITERATOR_TRAITS_HPP From 582ebfd054f474c6e9ab2387202fb55e2b2d1c1f Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 3 Jun 2001 21:07:46 +0000 Subject: [PATCH 119/265] updated to match changes in the headers [SVN r10260] --- development/libs/iterator/concept_tests.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/development/libs/iterator/concept_tests.cpp b/development/libs/iterator/concept_tests.cpp index df0fd02..f75f311 100644 --- a/development/libs/iterator/concept_tests.cpp +++ b/development/libs/iterator/concept_tests.cpp @@ -5,7 +5,7 @@ struct new_iterator : public boost::iterator, public boost::new_iterator_base { - typedef boost::random_access_iterator_tag traversal_category; + typedef boost::random_access_traversal_tag traversal_category; typedef boost::mutable_lvalue_iterator_tag return_category; int& operator*() const { return *m_x; } @@ -45,9 +45,6 @@ struct old_iterator }; old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; } -struct bar { }; -void foo(bar) { } - int main() { From 799158841e5fcc5d53166d88974e3524e0c476fa Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 8 Jun 2001 15:17:14 +0000 Subject: [PATCH 120/265] this is the original [SVN r10293] --- .../libs/iterator/iterator_concepts.fig | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 development/libs/iterator/iterator_concepts.fig diff --git a/development/libs/iterator/iterator_concepts.fig b/development/libs/iterator/iterator_concepts.fig new file mode 100644 index 0000000..3c51b23 --- /dev/null +++ b/development/libs/iterator/iterator_concepts.fig @@ -0,0 +1,37 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 825 1575 3825 4500 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 1725 2400 1725 1800 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 1725 4200 1725 3600 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 1725 3300 1725 2700 +4 0 0 100 0 19 18 0.0000 4 255 2370 825 1800 SinglePassIterator\001 +4 0 0 100 0 19 18 0.0000 4 195 1995 825 2700 ForwardIterator\001 +4 0 0 100 0 19 18 0.0000 4 195 2565 825 3600 BidirectionalIterator\001 +4 0 0 100 0 19 18 0.0000 4 195 2955 825 4500 RandomAccessIterator\001 +-6 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 4800 3600 4800 2400 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 6900 3000 5400 2400 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 6900 3000 7500 2400 +4 0 0 100 0 19 18 0.0000 4 195 1995 6600 2400 WritableIterator\001 +4 0 0 100 0 19 18 0.0000 4 195 2130 3900 2400 ReadableIterator\001 +4 0 0 50 0 19 18 0.0000 4 195 2805 5700 3300 MutableLvalueIterator\001 +4 0 0 50 0 19 18 0.0000 4 195 2955 3900 3900 ConstantLvalueIterator\001 From efecfd17b996c8b92caa0f0046ca60ab812f6cb7 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 8 Jun 2001 15:36:30 +0000 Subject: [PATCH 121/265] updated to match working group paper [SVN r10294] --- .../libs/iterator/iterator_concepts.fig | 28 +- .../libs/iterator/iterator_concepts.gif | Bin 2994 -> 2910 bytes .../libs/iterator/iterator_concepts.htm | 653 ++++++++++-------- 3 files changed, 369 insertions(+), 312 deletions(-) diff --git a/development/libs/iterator/iterator_concepts.fig b/development/libs/iterator/iterator_concepts.fig index 3c51b23..0723053 100644 --- a/development/libs/iterator/iterator_concepts.fig +++ b/development/libs/iterator/iterator_concepts.fig @@ -7,20 +7,16 @@ Letter Single -2 1200 2 -6 825 1575 3825 4500 +6 750 2100 3750 4125 2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2 1 1 1.00 60.00 120.00 - 1725 2400 1725 1800 + 1650 3825 1650 3225 2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2 1 1 1.00 60.00 120.00 - 1725 4200 1725 3600 -2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2 - 1 1 1.00 60.00 120.00 - 1725 3300 1725 2700 -4 0 0 100 0 19 18 0.0000 4 255 2370 825 1800 SinglePassIterator\001 -4 0 0 100 0 19 18 0.0000 4 195 1995 825 2700 ForwardIterator\001 -4 0 0 100 0 19 18 0.0000 4 195 2565 825 3600 BidirectionalIterator\001 -4 0 0 100 0 19 18 0.0000 4 195 2955 825 4500 RandomAccessIterator\001 + 1650 2925 1650 2325 +4 0 0 100 0 19 18 0.0000 4 210 1995 750 2325 ForwardIterator\001 +4 0 0 100 0 19 18 0.0000 4 210 2580 750 3225 BidirectionalIterator\001 +4 0 0 100 0 19 18 0.0000 4 210 2940 750 4125 RandomAccessIterator\001 -6 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 1 1 1.00 60.00 120.00 @@ -31,7 +27,11 @@ Single 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 1 1 1.00 60.00 120.00 6900 3000 7500 2400 -4 0 0 100 0 19 18 0.0000 4 195 1995 6600 2400 WritableIterator\001 -4 0 0 100 0 19 18 0.0000 4 195 2130 3900 2400 ReadableIterator\001 -4 0 0 50 0 19 18 0.0000 4 195 2805 5700 3300 MutableLvalueIterator\001 -4 0 0 50 0 19 18 0.0000 4 195 2955 3900 3900 ConstantLvalueIterator\001 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 6900 3000 9075 2475 +4 0 0 100 0 19 18 0.0000 4 210 2040 6600 2400 WritableIterator\001 +4 0 0 100 0 19 18 0.0000 4 210 2145 3900 2400 ReadableIterator\001 +4 0 0 50 0 19 18 0.0000 4 210 2835 5700 3300 MutableLvalueIterator\001 +4 0 0 50 0 19 18 0.0000 4 210 2970 3900 3900 ConstantLvalueIterator\001 +4 0 0 50 0 19 18 0.0000 4 270 2355 9075 2400 SwappableIterator\001 diff --git a/development/libs/iterator/iterator_concepts.gif b/development/libs/iterator/iterator_concepts.gif index 762c0553370a4314dcaeb85aa99811b438dc9d3d..29c38c9f26df88d38a3dfc3c34f29f3a80c38767 100644 GIT binary patch literal 2910 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 literal 2994 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 +

Iterator Concepts

-

The standard iterator concepts (the iterator requirements defined -in the C++ Standard) have a flaw. They glom together two separate -issues into a single set of concepts. The two issues are iterator -traversal and dereference return type semantics. These two issues are -inherently orthogonal and therefore ought to be represented by two -separate sets of concepts. The concepts described here do just -that.

+

The standard iterator categories and requirements are flawed because +they use a single hierarchy of requirements to address two orthogonal +issues: iterator traversal and dereference return +type. The current iterator requirement hierarchy is mainly +geared towards iterator traversal (hence the category names), while +requirements that address dereference return type sneak in at various +places. +

+The iterator requirements should be separated into two hierarchies. One set of concepts handles the return type semantics:

The other set of concepts handles iterator traversal: +The current Input Iterator and Output Iterator requirements will +continue to be used as is. Note that Input Iterator implies Readable +Iterator and Output Iterator implies Writable Iterator. + +

+Note: we considered defining a Single-Pass Iterator, which could be +combined with Readable or Writable Iterator to replace the Input and +Output Iterator requirements. We rejected this idea because there are +some differences between Input and Output Iterators that make it hard +to merge them: for example Input Iterator requires Equality Comparable +while Output Iterator does not. + +

- +
Figure 1: The iterator concepts and refinement relationships.

+

Relationship with the standard iterator concepts

-std::Input Iterator refines boost::Single-Pass Iterator and -boost::ReadableIterator. +std::Input Iterator implies boost::ReadableIterator.

-std::Output Iterator refines boost::Single-Pass Iterator and -boost::Writable Iterator. +std::Output Iterator implies boost::Writable Iterator.

std::Forward Iterator refines boost::Forward Iterator and @@ -106,106 +121,99 @@ boost::Constant Lvalue Iterator or boost::Mutable Lvalue Iterator.

Notation

- - - - - - - - - - - - - - - + + + + + + + + + + + + + + +
XThe iterator type.
TThe value type of X.
x, yAn object of type X.
tAn object of type T.
XThe iterator type.
TThe value type of X, i.e., std::iterator_traits<X>::value_type.
x, yAn object of type X.
tAn object of type T.


+ -

+

Readable Iterator -

+ A Readable Iterator is an iterator that dereferences to produce an rvalue that is convertible to the value_type of the -iterator. For example, derefencing may return a temporary object and -therefore it would be a mistake to bind the result to a reference. -Also, an attempt to assign a value to the result will most likely -cause an error. - -
-  template <class Readable Iterator>
-  void foo(Readable Iterator x)
-  {
-    typedef std::iterator_traits<Readable Iterator>::value_type T;
-    T t = *x;  // Read a value. This is OK.
-    T& s = *x; // Bind to a reference. This is a bad idea.
-    *x = t;    // Try to assign. This is a really bad idea.
-  }
-
- +iterator.

Associated Types

- - - - + + + + - - - - + + + + + + + + + +
Value typeboost::iterator_traits<X>::value_type - The type of the value obtained by dereferencing a LvalueIterator -
Value typestd::iterator_traits<X>::value_typeThe type of the objects pointed to by the iterator.
Return Categoryboost::iterator_traits<X>::return_category - A type convertible to boost::readable_iterator_tag -
Reference typestd::iterator_traits<X>::reference + The return type of dereferencing the iterator. This + type must be convertible to T. +
Return Categorystd::return_category<X>::type + A type convertible to std::readable_iterator_tag +

Refinement of

-Assignable, -Equality Comparable, -Default Constructible +Copy Constructible

Valid expressions

- - - - - - - - - - - - + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Dereference*x Convertible to T.
Member accessx->mT is a type with a member named m. -   -
NameExpressionType requirementsReturn type
Dereference*x std::iterator_traits<X>::reference
Member accessx->mT is a type with a member named m. +If m is a data member, the type of m. +If m is a member function, the return type of m. +


+ -

+

Writable Iterator -

+ A Writable Iterator is an iterator that can be used to store a value using the dereference-assignment expression. @@ -226,12 +234,12 @@ conversions on a. - - - - + + + +
Return Categoryboost::iterator_traits<X>::return_category - A type convertible to boost::writable_iterator_tag -
Return Categorystd::return_category<X>::type + A type convertible to std::writable_iterator_tag +
@@ -240,30 +248,100 @@ conversions on a.

Refinement of

-Assignable, -Equality Comparable, -Default Constructible +Copy Constructible

Valid expressions

- + - - - - - - + + + + + +
NameExpressionReturn type
Dereference assignment*x = aunspecified
Dereference assignment*x = aunspecified

-


-

+
+ + +

+Swappable Iterator +

+ +A Swappable Iterator is an iterator whose dereferenced values can be +swapped. + +

+Note: the requirements for Swappable Iterator are dependent on the +issues surrounding std::swap() being resolved. Here we assume +that the issue will be resolved by allowing the overload of +std::swap() for user-defined types. + +

+Note: Readable Iterator and Writable Iterator combined implies +Swappable Iterator because of the fully templated +std::swap(). However, Swappable Iterator does not imply +Readable Iterator nor Writable Iterator. + +

Associated Types

+ + + + + + + + + +
Return Categorystd::return_category<X>::type + A type convertible to std::swappable_iterator_tag +
+ + +

Valid expressions

+ +Of the two valid expressions listed below, only one OR the +other is required. If std::iter_swap() is overloaded for +X then std::swap() is not required. If +std::iter_swap() is not overloaded for X then the +default (fully templated) version is used, which will call +std::swap() (this means changing the current requirements for +std::iter_swap()). + +

+ + + + + + + + + + + + + + + + + +
NameExpressionReturn type
Iterator Swapstd::iter_swap(x, y)void
Dereference and Swapstd::swap(*x, *y)void
+ +

+ + +


+ + +

Constant Lvalue Iterator -

+ A Constant Lvalue Iterator is an iterator that dereferences to produce a const reference to the pointed-to object, i.e., the associated @@ -275,72 +353,72 @@ iterator.

Refinement of

-Readable Iterator +Readable Iterator

Associated Types

- - - - - - - - - - + + + + - - - - - - - + + + +
Value typeboost::iterator_traits<X>::value_type - The type of the value obtained by dereferencing a Constant Lvalue Iterator. -
Reference typeboost::iterator_traits<X>::reference - The return type of operator*(), which must be +
Reference typestd::iterator_traits<X>::reference + The return type of dereferencing the iterator, which must be const T&. -
POinter typeboost::iterator_traits<X>::pointer + -
Return Categoryboost::iterator_traits<X>::return_category - A type convertible to boost::constant_lvalue_iterator_tag -
Return Categorystd::return_category<X>::type + A type convertible to std::constant_lvalue_iterator_tag +
- + -

+

+ +


+ + +

Mutable Lvalue Iterator -

+ A Mutable Lvalue Iterator is an iterator that dereferences to produce a reference to the pointed-to object. The associated reference @@ -350,8 +428,9 @@ pointers and references previously obtained from that iterator.

Refinement of

-Readable Iterator and -Writable Iterator. +Readable Iterator, +Writable Iterator, +and Swappable Iterator. @@ -359,241 +438,219 @@ pointers and references previously obtained from that iterator. - - - - + + + + - - - - - - - - - - - - - + + + +
Value typeboost::iterator_traits<X>::value_type - The type of the value obtained by dereferencing a Mutable Lvalue Iterator. -
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator, which must be + T&.
Reference typeboost::iterator_traits<X>::reference - The return type of operator*(), which is - T&. -
Pointer typeboost::iterator_traits<X>::pointer + -
Return Categoryboost::iterator_traits<X>::return_category - A type convertible to boost::mutable_lvalue_iterator_tag -
Return Categorystd::return_category<X>::type + A type convertible to std::mutable_lvalue_iterator_tag +
- + +


+ -

-Single-Pass Iterator -

+

+Forward Traversal Iterator +

+ +The Forward Iterator is an iterator that can be incremented. Also, it +is permissible to make multiple passes through the iterator's range. + +

Refinement of

+ +Copy Constructible, +Assignable, +Default Constructible, and +Equality Comparable -A Single-Pass Iterator is an iterator that can be incremented to -traverse through a sequence of objects, but the sequence can only be -traversed a single time.

Associated types

- - - - - - - - - + + + + -
Difference typeboost::iterator_traits<X>::difference_type - A signed integral type used to represent the distance from one - iterator to another, or the number of elements in a range. -
Traversal Categoryboost::iterator_traits<X>::traversal_category - A type convertible to boost::single_pass_iterator_tag -
Difference Typestd::iterator_traits<X>::difference_type + A signed integral type used for representing distances + between iterators that point into the same range. +
+ + Traversal Category + std::traversal_category<X>::type + + A type convertible to std::forward_traversal_tag + + +

Valid expressions

- + - - - - - - - - - -
NameExpressionType requirements Return type
Preincrement++i X&
Postincrement(void)i++  
- -

-


- -

-Forward Iterator -

- -The Forward Iterator is an iterator that can be incremented. Also, it -is permissible to make multiple passes through the sequence. - -

Refinement of

- -Single-Pass Iterator - -

Associated types

- - - - - - + + + + + + + +
Traversal Categoryboost::iterator_traits<X>::traversal_category - A type convertible to boost::forward_iterator_tag -
Preincrement++i X&
Postincrementi++ convertible to const X&


+ -

-Bidirectional Iterator -

+

+Bidirectional Traversal Iterator +

An iterator that can be incremented and decremented.

Refinement of

-Forward Iterator +Forward Traversal Iterator

Associated types

- - - - + + + +
Traversal Categoryboost::iterator_traits<X>::traversal_category - A type convertible to boost::bidirectional_iterator_tag -
Traversal Categorystd::traversal_category<X>::type + A type convertible to std::bidirectional_traversal_tag +

Valid expressions

- + - - - - - - + + + + + +
NameExpressionType requirements Return type
Predecrement--i X&
Postdecrementi-- X
Predecrement--i X&
Postdecrementi-- convertible to const X&


+ -

-Random Access Iterator -

+

+Random Access Traversal Iterator +

An iterator that provides constant-time methods for moving forward and -backward in arbitrary-sized steps +backward in arbitrary-sized steps.

Refinement of

-Bidirectional Iterator +Bidirectional Traversal Iterator and +Less Than Comparable where < is a total ordering

Associated types

- - - - + + + +
Traversal Categoryboost::iterator_traits<X>::traversal_category - A type convertible to boost::random_access_iterator_tag -
Traversal Categorystd::traversal_category<X>::type + A type convertible to std::random_access_traversal_tag +

Valid expressions

- + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + +
NameExpressionType requirements
NameExpressionType requirements Return type
Iterator additioni += n X&
Iterator additioni + n or n + i X
Iterator subtractioni -= n X&
Iterator subtractioni - n X
Differencei - j boost::iterator_traits<X>::difference_type
Element operatori[n]X must be a model of - Readable Iterator. The same return type as *i.
Element assignmenti[n] = tX must be a model of - Writable Iterator.unspecified
Iterator additioni += n X&
Iterator additioni + n or n + i X
Iterator subtractioni -= n X&
Iterator subtractioni - n X
Differencei - j std::iterator_traits<X>::difference_type
Element operatori[n]X must also be a model of + Readable Iterator. std::iterator_traits<X>::reference
Element assignmenti[n] = tX must also be a model of + Writable Iterator.unspecified
- -
+


From 134b8b51aae8d3d1c5adc51d656d977a9e862f81 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 8 Jun 2001 15:37:16 +0000 Subject: [PATCH 122/265] updated [SVN r10295] --- .../libs/iterator/iterator_categories.htm | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 development/libs/iterator/iterator_categories.htm diff --git a/development/libs/iterator/iterator_categories.htm b/development/libs/iterator/iterator_categories.htm new file mode 100644 index 0000000..83c29e5 --- /dev/null +++ b/development/libs/iterator/iterator_categories.htm @@ -0,0 +1,160 @@ + + + + Boost Iterator Traits + + + +C++ Boost +
+ +

Boost Iterator Category Traits

+Header boost/iterator_categories.hpp + +

+The boost::traversal_category and +boost::return_category traits classes provides access to the +category tags for iterators that model the Boost Iterator Concepts, which are a +replacement for the iterator requirements in the C++ standard. The +other associated types of the Boost iterator concepts are accessed +through the std::iterator_traits class. + +

    +
  • traversal_category<Iter>::type   Can the iterator go forward, backward, etc.? +
  • return_category<Iter>::type   Is the iterator read or write only? + Is the dereferenced type an lvalue? +
+ +

+An important feature of the boost::traversal_category and +boost::return_category classes is that they are backwards +compatible, i.e., they automatically work for iterators for which +there are valid definitions of std::iterator_traits. The old +iterator_category is mapped to the appropriate traversal and +return categories. + +

+When creating a new iterator type that is meant to work with +boost::traversal_category and +boost::return_category, you can either create a +specialization of these classes for your iterator type, or you can +provide all the necessary associated types as nested typedefs. In +this case, your iterator class will need to inherit from +new_iterator_base to let the category traits know +that it will be able to find typedefs for traversal_category +and return_category in you iterator class. + + +Each of the new iterator requirements will need a category tag. + +

+namespace boost {
+
+  // Return Type Categories
+  struct readable_iterator_tag { };
+  struct writable_iterator_tag { };
+  struct swappable_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 { };
+
+  // Traversal Categories
+  struct forward_traversal_tag { };
+  struct bidirectional_traversal_tag : public forward_traversal_tag { };
+  struct random_access_traversal_tag : public bidirectional_traversal_tag { };
+
+}
+
+ +

+The following is pseudo-code for the iterator category traits classes. + +

+namespace boost {
+
+  // Inherit from iterator_base if your iterator defines its own
+  // return_category and traversal_category. Otherwise, the "old style"
+  // iterator category will be mapped to the return_category and
+  // traversal_category.
+  struct new_iterator_base { };
+
+  template <typename Iterator>
+  struct return_category
+  {
+    // Pseudo-code
+    if (Iterator inherits from new_iterator_base) {
+      typedef typename Iterator::return_category type;
+    } else {
+      typedef std::iterator_traits<Iterator> OldTraits;
+      typedef typename OldTraits::iterator_category Cat;
+      if (Cat inherits from std::forward_iterator_tag)
+	if (is-const(T))
+	  typedef boost::constant_lvalue_iterator_tag type;
+	else
+	  typedef boost::mutable_lvalue_iterator_tag type;
+      else if (Cat inherits from std::input_iterator_tag)
+	typedef boost::readable_iterator_tag type;
+      else if (Cat inherits from std::output_iterator_tag)
+	typedef boost::writable_iterator_tag type;
+    }
+  };
+
+  template <typename T>
+  struct return_category<T*>
+  {
+    // Pseudo-code
+    if (is-const(T))
+      typedef boost::constant_lvalue_iterator_tag type;
+    else
+      typedef boost::mutable_lvalue_iterator_tag type;
+  };
+
+  template <typename Iterator>
+  struct traversal_category
+  {
+    // Pseudo-code
+    if (Iterator inherits from new_iterator_base) {
+      typedef typename Iterator::traversal_category type;
+    } else {
+      typedef std::iterator_traits<Iterator> OldTraits;
+      typedef typename OldTraits::iterator_category Cat;
+
+      if (Cat inherits from std::random_access_iterator_tag)
+	typedef boost::random_access_traversal_tag type;
+      else if (Cat inherits from std::bidirectional_iterator_tag)
+	typedef boost::bidirectional_traversal_tag type;
+      else if (Cat inherits from std::forward_iterator_tag)
+	typedef boost::forward_traversal_tag type;
+    }
+  };
+
+  template <typename T>
+  struct traversal_category<T*>
+  {
+    typedef boost::random_access_traversal_tag type;
+  };
+
+}
+
+ +
+
jeremy siek
+ + +Last modified: Mon Mar 19 12:59:30 EST 2001 + + + From 552a1e6785eb04a17a2241c966f880ab5038d232 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 8 Jun 2001 16:58:44 +0000 Subject: [PATCH 123/265] replaced by iterator_categories.htm [SVN r10296] --- development/libs/iterator/iterator_traits.htm | 137 ------------------ 1 file changed, 137 deletions(-) delete mode 100644 development/libs/iterator/iterator_traits.htm diff --git a/development/libs/iterator/iterator_traits.htm b/development/libs/iterator/iterator_traits.htm deleted file mode 100644 index 40f3026..0000000 --- a/development/libs/iterator/iterator_traits.htm +++ /dev/null @@ -1,137 +0,0 @@ - - - - Boost Iterator Traits - - - -C++ Boost -
- -

Boost Iterator Traits

-Header boost/iterator_traits.hpp - -

-The boost::iterator_traits class provides access to the -associated types of iterators that model the Boost Iterator Concepts, which are a -replacement for the iterator requirements in the C++ standard. -The main difference between std::iterator_traits and -boost::iterator_traits is that the iterator_category -type has been removed, and replaced with two new types: - -

    -
  • traversal_category:   Can the iterator go forward, backward, etc.? -
  • return_category:   Is the iterator read or write only? - Is the dereferenced type an lvalue? -
- - -

-An important feature of the boost::iterator_traits is that it -is backwards compatible, i.e., it will automatically work for -iterators for which there are valid definitions of -std::iterator_traits. The old iterator_category is -mapped to the appropriate traversal and return categories. - -

-When creating a new iterator type that is meant to work with -boost::iterator_traits, you can either create a -specialization of boost::iterator_traits for your iterator -type, or you can provide all the necessary associated types as nested -typedefs. In this case, your iterator class will need to inherit from -new_iterator_base to let boost::iterator_traits know -that it will be able to find typedefs for traversal_category -and return_category in you iterator class. - - -

-namespace boost {
-
-  // Inherit from iterator_base if your iterator defines its own
-  // return_category and traversal_category. Otherwise, the "old style"
-  // iterator category will be mapped to the return_category and
-  // traversal_category.
-  struct new_iterator_base { };
-
-  template <typename Iterator>
-  struct iterator_traits
-  {
-    if (Iterator inherits from new_iterator_base) {
-      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::traversal_category traversal_category;
-    } else {
-      typedef std::iterator_traits<Iterator> OldTraits;
-      typedef typename OldTraits::value_type value_type;
-      typedef typename OldTraits::reference reference;
-      typedef typename OldTraits::pointer pointer;
-      typedef typename OldTraits::difference_type difference_type;
-
-      typedef typename OldTraits::iterator_category Cat;
-
-      // Determine the traversal_category based on the old iterator_category
-      if (Cat inherits from std::random_access_iterator_tag)
-        typedef boost::random_access_iterator_tag traversal_category;
-      else if (Cat inherits from std::bidirectional_iterator_tag)
-        typedef boost::bidirectional_iterator_tag traversal_category;
-      else if (Cat inherits from std::forward_iterator_tag)
-        typedef boost::forward_iterator_tag traversal_category;
-      else 
-        typedef boost::single_pass_iterator_tag traversal_category;
-
-      // Determine the return_category based on the old iterator_category and value_type
-      if (Cat inherits from std::forward_iterator_tag)
-        if (is-const(T))
-          typedef boost::constant_lvalue_iterator_tag return_category;
-        else
-          typedef boost::mutable_lvalue_iterator_tag return_category;
-      else if (Cat inherits from std::input_iterator_tag)
-        typedef boost::readable_iterator_tag return_category;
-      else if (Cat inherits from std::output_iterator_tag)
-        typedef boost::writable_iterator_tag return_category;
-      else
-        typedef boost::error_iterator_tag return_category;
-    }
-  };
-
-  template <typename T>
-  struct iterator_traits<T*>
-  {
-    typedef T value_type;
-    typedef T& reference;
-    typedef T* pointer;
-    typedef std::ptrdiff_t difference_type;
-    if (is-const(T))
-      typedef boost::constant_lvalue_iterator_tag return_category;
-    else
-      typedef boost::mutable_lvalue_iterator_tag return_category;
-    typedef boost::random_access_iterator_tag traversal_category;
-  };
-
-}
-
- -
-
jeremy siek
- - -Last modified: Mon Mar 19 12:59:30 EST 2001 - - - From ac053075156534bf11da0f008ec838aff88d2eec Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Fri, 8 Jun 2001 17:05:37 +0000 Subject: [PATCH 124/265] added "Traversal" to the names [SVN r10297] --- .../libs/iterator/iterator_concepts.fig | 14 +++++++------- .../libs/iterator/iterator_concepts.gif | Bin 2910 -> 3287 bytes 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/development/libs/iterator/iterator_concepts.fig b/development/libs/iterator/iterator_concepts.fig index 0723053..198205e 100644 --- a/development/libs/iterator/iterator_concepts.fig +++ b/development/libs/iterator/iterator_concepts.fig @@ -7,16 +7,16 @@ Letter Single -2 1200 2 -6 750 2100 3750 4125 +6 150 2325 4275 4350 2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2 1 1 1.00 60.00 120.00 - 1650 3825 1650 3225 + 1725 4050 1725 3450 2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2 1 1 1.00 60.00 120.00 - 1650 2925 1650 2325 -4 0 0 100 0 19 18 0.0000 4 210 1995 750 2325 ForwardIterator\001 -4 0 0 100 0 19 18 0.0000 4 210 2580 750 3225 BidirectionalIterator\001 -4 0 0 100 0 19 18 0.0000 4 210 2940 750 4125 RandomAccessIterator\001 + 1725 3150 1725 2550 +4 0 0 100 0 19 18 0.0000 4 210 3180 375 2550 ForwardTraversalIterator\001 +4 0 0 100 0 19 18 0.0000 4 210 3765 225 3450 BidirectionalTraversalIterator\001 +4 0 0 100 0 19 18 0.0000 4 210 4125 150 4350 RandomAccessTraversalIterator\001 -6 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 1 1 1.00 60.00 120.00 @@ -33,5 +33,5 @@ Single 4 0 0 100 0 19 18 0.0000 4 210 2040 6600 2400 WritableIterator\001 4 0 0 100 0 19 18 0.0000 4 210 2145 3900 2400 ReadableIterator\001 4 0 0 50 0 19 18 0.0000 4 210 2835 5700 3300 MutableLvalueIterator\001 -4 0 0 50 0 19 18 0.0000 4 210 2970 3900 3900 ConstantLvalueIterator\001 4 0 0 50 0 19 18 0.0000 4 270 2355 9075 2400 SwappableIterator\001 +4 0 0 50 0 19 18 0.0000 4 210 2970 3825 3900 ConstantLvalueIterator\001 diff --git a/development/libs/iterator/iterator_concepts.gif b/development/libs/iterator/iterator_concepts.gif index 29c38c9f26df88d38a3dfc3c34f29f3a80c38767..bac35c7d13e402c6bc2fd5ff770bf444da6f4426 100644 GIT binary patch literal 3287 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 avv|wt|F#w{F3RO$?#R71Ygz~cgEatv^I|Fh literal 2910 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 From 81e3df2b365388fa39410d76190b56cdedf128bb Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Wed, 25 Jul 2001 19:38:41 +0000 Subject: [PATCH 125/265] changed _MSC_VER to BOOST_MSVC [SVN r10705] --- include/boost/iterator_adaptors.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index b05bef2..ae2fdb6 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -656,7 +656,7 @@ struct iterator_adaptor : return policies().dereference(type(), iter()); } -#ifdef _MSC_VER +#ifdef BOOST_MSVC # pragma warning(push) # pragma warning( disable : 4284 ) #endif @@ -665,7 +665,7 @@ struct iterator_adaptor : operator->() const { return detail::operator_arrow(*this, iterator_category()); } -#ifdef _MSC_VER +#ifdef BOOST_MSVC # pragma warning(pop) #endif From 4e18b1126363d1ceaba007a548d007a8a8d454b7 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 3 Sep 2001 15:38:05 +0000 Subject: [PATCH 126/265] metrowerks fix for decrement() [SVN r10997] --- include/boost/iterator_adaptors.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index ae2fdb6..0d2a5f7 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -686,7 +686,11 @@ struct iterator_adaptor : self operator++(int) { self tmp(*this); ++*this; return tmp; } self& operator--() { +#ifdef __MWERKS__ + policies().decrement(iter()); +#else policies().decrement(iter()); +#endif return *this; } From ac327f51e9f94885632038295a09d45425163dcf Mon Sep 17 00:00:00 2001 From: John Maddock Date: Tue, 18 Sep 2001 11:13:39 +0000 Subject: [PATCH 127/265] commit of split-config, including any changes required to existing libraries (mainly regex). [SVN r11138] --- include/boost/iterator.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/iterator.hpp b/include/boost/iterator.hpp index 34e4e4b..0e2ef72 100644 --- a/include/boost/iterator.hpp +++ b/include/boost/iterator.hpp @@ -21,7 +21,7 @@ namespace boost { -# ifdef BOOST_NO_STD_ITERATOR +# if defined(BOOST_NO_STD_ITERATOR) && !defined(BOOST_MSVC_STD_ITERATOR) template From d1c7594344d880f0ae51ea6b405cc745e70c9c83 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 27 Sep 2001 00:26:01 +0000 Subject: [PATCH 128/265] Added borland bug fix [SVN r11290] --- include/boost/iterator_adaptors.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 0d2a5f7..596e0e3 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,8 @@ // // Revision History: +// 26 Sep 2001 David Abrahams +// Added borland bug fix // 08 Mar 2001 Jeremy Siek // Added support for optional named template parameters. // 19 Feb 2001 David Abrahams @@ -644,9 +646,9 @@ struct iterator_adaptor : policies().initialize(iter()); } -#ifdef BOOST_MSVC +#if defined(BOOST_MSVC) || defined(__BORLANDC__) // This is required to prevent a bug in how VC++ generates - // the assignment operator for compressed_pair. + // the assignment operator for compressed_pairv iterator_adaptor& operator= (const iterator_adaptor& x) { m_iter_p = x.m_iter_p; return *this; From 2d6f48d5abfd8c736dcf41dd70a17a7492ae15ea Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 4 Oct 2001 19:36:28 +0000 Subject: [PATCH 129/265] Applied indirect_iterator patch from George A. Heintzelman Changed name of "bind" to "select" to avoid problems with MSVC. [SVN r11337] --- include/boost/iterator_adaptors.hpp | 63 ++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 596e0e3..52fc730 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,9 @@ // // Revision History: +// 04 Oct 2001 David Abrahams +// Applied indirect_iterator patch from George A. Heintzelman +// Changed name of "bind" to "select" to avoid problems with MSVC. // 26 Sep 2001 David Abrahams // Added borland bug fix // 08 Mar 2001 Jeremy Siek @@ -443,25 +446,25 @@ namespace detail { struct default_value_type { template - struct bind { + struct select { typedef typename boost::detail::iterator_traits::value_type type; }; }; struct default_difference_type { template - struct bind { + struct select { typedef typename boost::detail::iterator_traits::difference_type type; }; }; struct default_iterator_category { template - struct bind { + struct select { typedef typename boost::detail::iterator_traits::iterator_category type; }; }; struct default_pointer { template - struct bind { + struct select { typedef typename Traits::value_type Value; typedef typename boost::detail::iterator_defaults::pointer type; @@ -469,7 +472,7 @@ namespace detail { }; struct default_reference { template - struct bind { + struct select { typedef typename Traits::value_type Value; typedef typename boost::detail::iterator_defaults::reference type; @@ -891,9 +894,11 @@ struct indirect_iterator_policies : public default_iterator_policies namespace detail { # if !defined(BOOST_MSVC) // stragely instantiated even when unused! Maybe try a recursive template someday ;-) template - struct value_type_of_value_type { + struct traits_of_value_type { typedef typename boost::detail::iterator_traits::value_type outer_value; - typedef typename boost::detail::iterator_traits::value_type type; + typedef typename boost::detail::iterator_traits::value_type value_type; + typedef typename boost::detail::iterator_traits::reference reference; + typedef typename boost::detail::iterator_traits::pointer pointer; }; # endif } @@ -901,11 +906,25 @@ namespace detail { template ::type + = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< + OuterIterator>::value_type +#endif + , class Reference +#if !defined(BOOST_MSVC) + = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< + OuterIterator>::reference +#else + = Value & +#endif + , class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits< + OuterIterator>::iterator_category + , class Pointer +#if !defined(BOOST_MSVC) + = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< + OuterIterator>::pointer +#else + = Value* #endif - , class Reference = Value& - , class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category - , class Pointer = Value* > struct indirect_iterator_generator { @@ -916,12 +935,26 @@ struct indirect_iterator_generator template ::type + = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< + OuterIterator>::value_type +#endif + , class Reference +#if !defined(BOOST_MSVC) + = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< + OuterIterator>::reference +#else + = Value & #endif - , class Reference = Value& , class ConstReference = const Value& - , class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category - , class Pointer = Value* + , class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits< + OuterIterator>::iterator_category + , class Pointer +#if !defined(BOOST_MSVC) + = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< + OuterIterator>::pointer +#else + = Value* +#endif , class ConstPointer = const Value* > struct indirect_iterator_pair_generator From 3fd1c4bc5d0eb522296383b05bd245def53dc9b6 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 4 Oct 2001 21:02:12 +0000 Subject: [PATCH 130/265] Changed projection_iterator to not rely on the default reference, working around a limitation of detail::iterator_traits [SVN r11340] --- include/boost/iterator_adaptors.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 52fc730..96c60b8 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,9 @@ // // Revision History: +// 04 Oct 2001 Jeremy Siek +// Changed projection_iterator to not rely on the default reference, +// working around a limitation of detail::iterator_traits. // 04 Oct 2001 David Abrahams // Applied indirect_iterator patch from George A. Heintzelman // Changed name of "bind" to "select" to avoid problems with MSVC. @@ -1054,7 +1057,7 @@ class projection_iterator_generator { typedef typename AdaptableUnaryFunction::result_type value_type; typedef projection_iterator_policies policies; public: - typedef iterator_adaptor type; + typedef iterator_adaptor type; }; template From 4566798afc16359b5526af82b89c1d6af87530eb Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 4 Nov 2001 02:50:10 +0000 Subject: [PATCH 131/265] iterator adaptor update and related changes [SVN r11554] --- include/boost/counting_iterator.hpp | 27 +- include/boost/iterator_adaptors.hpp | 438 +++++++++++++++++++--------- 2 files changed, 318 insertions(+), 147 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index 90d808d..84dce41 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -135,7 +135,15 @@ namespace detail { // For a while, this wasn't true, but we rely on it below. This is a regression assert. BOOST_STATIC_ASSERT(::boost::is_integral::value); # ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_specialized); +# if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) + BOOST_STATIC_CONSTANT(bool, + value = ( + std::numeric_limits::is_specialized + | boost::is_same::value + | boost::is_same::value)); +# else + BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_specialized); +# endif # else # if !defined(__BORLANDC__) BOOST_STATIC_CONSTANT(bool, value = ( @@ -173,14 +181,17 @@ struct counting_iterator_traits { template struct counting_iterator_policies : public default_iterator_policies { - const Incrementable& dereference(type, const Incrementable& i) const - { return i; } - - template - Difference distance(type, const Iterator1& x, - const Iterator2& y) const + template + typename IteratorAdaptor::reference dereference(const IteratorAdaptor& i) const + { return i.base(); } + + template + typename Iterator1::difference_type distance( + const Iterator1& x, const Iterator2& y) const { - return boost::detail::any_distance(x, y);//,(Difference*)()); + typedef typename Iterator1::difference_type difference_type; + return boost::detail::any_distance( + x.base(), y.base()); } }; diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 96c60b8..f81cf63 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,8 @@ // // Revision History: +// 03 Nov 2001 Jeremy Siek +// Changed the named template parameter interface and internal. // 04 Oct 2001 Jeremy Siek // Changed projection_iterator to not rely on the default reference, // working around a limitation of detail::iterator_traits. @@ -114,7 +116,7 @@ # 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 @@ -146,7 +148,7 @@ struct TrivialIteratorPoliciesConcept const_constraints(); } void const_constraints() const { - Reference r = p.dereference(type(), x); + Reference r = p.dereference(x); b = p.equal(x, x); ignore_unused_variable_warning(r); } @@ -208,8 +210,7 @@ struct RandomAccessIteratorPoliciesConcept ignore_unused_variable_warning(t); } void const_constraints() const { - n = p.distance(type(), x, x); - b = p.less(x, x); + n = p.distance(x, x); } Policies p; Adapted x; @@ -231,37 +232,30 @@ struct default_iterator_policies void initialize(Base&) { } - // The "type" parameter is a portable mechanism for - // the iterator_adaptor class to tell this member function what - // the Reference type is, which is needed for the return type. - template - Reference dereference(type, const Base& x) const - { return *x; } + template + typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const + { return *x.base(); } - template - void increment(Base& x) - { ++x; } + template + void increment(IteratorAdaptor& x) + { ++x.base(); } - template - void decrement(Base& x) - { --x; } + template + void decrement(IteratorAdaptor& x) + { --x.base(); } - template - void advance(Base& x, DifferenceType n) - { x += n; } + template + void advance(IteratorAdaptor& x, DifferenceType n) + { x.base() += n; } - template - Difference distance(type, const Iterator1& x, - const Iterator2& y) const - { return y - x; } + template + typename IteratorAdaptor1::difference_type + distance(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const + { return y.base() - x.base(); } - 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; } + template + bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const + { return x.base() == y.base(); } }; // putting the comparisons in a base class avoids the g++ @@ -277,7 +271,7 @@ inline bool operator==(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return x.policies().equal(x.iter(), y.iter()); + return x.policies().equal(x, y); } template @@ -286,7 +280,7 @@ inline bool operator!=(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return !x.policies().equal(x.iter(), y.iter()); + return !x.policies().equal(x, y); } template @@ -295,7 +289,7 @@ inline bool operator<(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return x.policies().less(x.iter(), y.iter()); + return x.policies().distance(x, y) > 0; } template @@ -304,7 +298,7 @@ inline bool operator>(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return x.policies().less(y.iter(), x.iter()); + return x.policies().distance(y, x) > 0; } template @@ -313,7 +307,7 @@ inline bool operator>=(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return !x.policies().less(x.iter(), y.iter()); + return !(x.policies().distance(x, y) > 0); } template @@ -322,7 +316,7 @@ inline bool operator<=(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return !x.policies().less(y.iter(), x.iter()); + return !(x.policies().distance(y, x) > 0); } #endif @@ -417,7 +411,7 @@ namespace detail { { BOOST_STATIC_CONSTANT(bool, is_ptr = boost::is_pointer::value); - typedef iterator_defaults_select::template traits traits; + typedef typename iterator_defaults_select::template traits traits; typedef typename traits::pointer pointer; typedef typename traits::reference reference; }; @@ -446,25 +440,45 @@ namespace detail { //=========================================================================== // Specify the defaults for iterator_adaptor's template parameters - + + struct default_argument { }; + // This class template is a workaround for MSVC. + struct dummy_default_gen { + template + struct select { typedef default_argument type; }; + }; + // This class template is a workaround for MSVC. + template struct default_generator { + typedef dummy_default_gen type; + }; + struct default_value_type { template struct select { typedef typename boost::detail::iterator_traits::value_type type; }; }; + template <> struct default_generator + { typedef default_value_type type; }; // VC++ workaround + struct default_difference_type { template struct select { typedef typename boost::detail::iterator_traits::difference_type type; }; }; + template <> struct default_generator + { typedef default_difference_type type; }; // VC++ workaround + struct default_iterator_category { template struct select { typedef typename boost::detail::iterator_traits::iterator_category type; }; }; + template <> struct default_generator + { typedef default_iterator_category type; }; // VC++ workaround + struct default_pointer { template struct select { @@ -473,6 +487,9 @@ namespace detail { type; }; }; + template <> struct default_generator + { typedef default_pointer type; }; // VC++ workaround + struct default_reference { template struct select { @@ -481,72 +498,219 @@ namespace detail { type; }; }; + template <> struct default_generator + { typedef default_reference type; }; // VC++ workaround + +} // namespace detail + //=========================================================================== // Support for named template parameters -#if !defined(__BORLANDC__) - // Borland C++ thinks the nested recursive inheritance here is illegal. +struct named_template_param_base { }; - template - struct iter_traits_gen : public named_template_param_base { - template - struct value_type : public iter_traits_gen { }; - template - struct reference : public iter_traits_gen { }; - template - struct pointer : public iter_traits_gen { }; - template - struct iterator_category : public iter_traits_gen{}; - template - struct difference_type : public iter_traits_gen { }; +namespace detail { + struct value_type_tag { }; + struct reference_tag { }; + struct pointer_tag { }; + struct difference_type_tag { }; + struct iterator_category_tag { }; - typedef boost::iterator traits; + // avoid using std::pair because A or B might be a reference type, and g++ + // complains about forming references to references inside std::pair + template + struct cons_type { + typedef A first_type; + typedef B second_type; + }; + +} // namespace detail + +template struct value_type_is : public named_template_param_base +{ + typedef detail::cons_type type; +}; +template struct reference_is : public named_template_param_base +{ + typedef detail::cons_type type; +}; +template struct pointer_is : public named_template_param_base +{ + typedef detail::cons_type type; +}; +template struct difference_type_is + : public named_template_param_base +{ + typedef detail::cons_type type; +}; +template struct iterator_category_is + : public named_template_param_base +{ + typedef detail::cons_type type; +}; + +namespace detail { + + struct end_of_list { }; + + // Given an associative list, find the value with the matching key. + // An associative list is a list of key-value pairs. The list is + // built out of cons_type's and is terminated by end_of_list. + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct find_param; + + struct find_param_continue { + template struct bind { + typedef typename AssocList::first_type Head; + typedef typename Head::first_type Key1; + typedef typename Head::second_type Value; + typedef typename ct_if::value, + Value, + typename find_param::type + >::type type; + }; + }; + struct find_param_end { + template + struct bind { typedef detail::default_argument type; }; + }; + template struct find_param_helper1 + { typedef find_param_continue type; }; + template <> struct find_param_helper1 + { typedef find_param_end type; }; + + template + struct find_param { + typedef typename find_param_helper1::type select1; + typedef typename select1::template bind::type type; + }; +#else + template struct find_param; + + template + struct find_param { typedef default_argument type; }; + + // Found a matching Key, return the associated Value + template + struct find_param, Rest>, Key> { + typedef Value type; + }; + + // Non-matching keys, continue the search + template + struct find_param, Rest>, Key2> { + typedef typename find_param::type type; }; #endif - BOOST_NAMED_TEMPLATE_PARAM(value_type); - BOOST_NAMED_TEMPLATE_PARAM(reference); - BOOST_NAMED_TEMPLATE_PARAM(pointer); - BOOST_NAMED_TEMPLATE_PARAM(iterator_category); - BOOST_NAMED_TEMPLATE_PARAM(difference_type); + struct make_named_arg { + template + struct bind { typedef typename Value::type type; }; + }; + struct make_key_value { + template + struct bind { typedef detail::cons_type type; }; + }; + + template + struct make_arg { + enum { is_named = is_convertible::value }; + typedef typename ct_if::type Make; + typedef typename Make::template bind::type type; + }; + + // Mechanism for resolving the default argument for a template parameter. + + template struct is_default { typedef type_traits::no_type type; }; + template <> struct is_default + { typedef type_traits::yes_type type; }; + + struct choose_default { + template + struct bind { + typedef typename default_generator::type Gen; + typedef typename Gen::template select::type type; + }; + }; + struct choose_arg { + template + struct bind { + typedef Arg type; + }; + }; + + template + struct choose_arg_or_default { typedef choose_arg type; }; + template <> struct choose_arg_or_default { + typedef choose_default type; + }; + + template + class resolve_default { + typedef typename choose_arg_or_default::type>::type + Selector; + public: + typedef typename Selector + ::template bind::type type; + }; template class iterator_adaptor_traits_gen { + // Form an associative list out of the template parameters + // If the argument is a normal parameter (not named) then make_arg + // creates a key-value pair. If the argument is a named parameter, + // then make_arg extracts the key-value pair defined inside the + // named parameter. + typedef detail::cons_type< typename make_arg::type, + detail::cons_type::type, + detail::cons_type::type, + detail::cons_type::type, + detail::cons_type::type, + end_of_list> > > > > ArgList; + + // Search the list for particular parameters + typedef typename find_param::type Val; + typedef typename find_param::type Diff; + typedef typename find_param::type Cat; + typedef typename find_param::type Ptr; + typedef typename find_param::type Ref; + typedef boost::iterator Traits0; - typedef typename get_value_type::type, Traits0 - >::type value_type; - typedef typename get_difference_type::type - difference_type; - typedef typename get_iterator_category::type - iterator_category; + // Compute the defaults if necessary + typedef typename resolve_default::type + value_type; + // if getting default value type from iterator_traits, then it won't be const + typedef typename resolve_default::type difference_type; + typedef typename resolve_default::type iterator_category; typedef boost::iterator Traits1; + + // Compute the defaults for pointer and reference. This is done as a + // separate step because the defaults for pointer and reference depend + // on value_type. + typedef typename resolve_default::type + pointer; + typedef typename resolve_default::type + reference; - typedef typename get_pointer::type pointer; - typedef typename get_reference::type reference; public: - typedef boost::iterator type; + typedef boost::iterator::type, + difference_type, pointer, reference> type; }; - + } // namespace detail -#if !defined(__BORLANDC__) -struct iterator_traits_generator - : public detail::iter_traits_gen<> { }; -#endif // This macro definition is only temporary in this file # if !defined(BOOST_MSVC) @@ -587,10 +751,10 @@ template struct undefined; // supplied, iterator_traits::difference_type is used. template ::type, - class Pointer = BOOST_ARG_DEPENDENT_TYPENAME detail::choose_default_argument::type, - class Category = BOOST_ARG_DEPENDENT_TYPENAME detail::choose_default_argument::type, - class Distance = BOOST_ARG_DEPENDENT_TYPENAME detail::choose_default_argument::type + class Reference = detail::default_argument, + class Pointer = detail::default_argument, + class Category = detail::default_argument, + class Distance = detail::default_argument > struct iterator_adaptor : #ifdef BOOST_RELOPS_AMBIGUITY_BUG @@ -641,15 +805,15 @@ struct iterator_adaptor : explicit iterator_adaptor(const Base& it, const Policies& p = Policies()) : m_iter_p(it, p) { - policies().initialize(iter()); + policies().initialize(base()); } template iterator_adaptor ( const iterator_adaptor& src) - : m_iter_p(src.iter(), src.policies()) + : m_iter_p(src.base(), src.policies()) { - policies().initialize(iter()); + policies().initialize(base()); } #if defined(BOOST_MSVC) || defined(__BORLANDC__) @@ -661,7 +825,7 @@ struct iterator_adaptor : } #endif reference operator*() const { - return policies().dereference(type(), iter()); + return policies().dereference(*this); } #ifdef BOOST_MSVC @@ -684,9 +848,9 @@ struct iterator_adaptor : #ifdef __MWERKS__ // Odd bug, MWERKS couldn't deduce the type for the member template // Workaround by explicitly specifying the type. - policies().increment(iter()); + policies().increment(*this); #else - policies().increment(iter()); + policies().increment(*this); #endif return *this; } @@ -695,9 +859,9 @@ struct iterator_adaptor : self& operator--() { #ifdef __MWERKS__ - policies().decrement(iter()); + policies().decrement(*this); #else - policies().decrement(iter()); + policies().decrement(*this); #endif return *this; } @@ -705,16 +869,16 @@ struct iterator_adaptor : self operator--(int) { self tmp(*this); --*this; return tmp; } self& operator+=(difference_type n) { - policies().advance(iter(), n); + policies().advance(*this, n); return *this; } self& operator-=(difference_type n) { - policies().advance(iter(), -n); + policies().advance(*this, -n); return *this; } - base_type base() const { return m_iter_p.first(); } + base_type const& base() const { return m_iter_p.first(); } // Moved from global scope to avoid ambiguity with the operator-() which // subtracts iterators from one another. @@ -724,11 +888,9 @@ private: compressed_pair m_iter_p; public: // implementation details (too many compilers have trouble when these are private). + base_type& base() { return m_iter_p.first(); } Policies& policies() { return m_iter_p.second(); } const Policies& policies() const { return m_iter_p.second(); } - - Base& iter() { return m_iter_p.first(); } - const Base& iter() const { return m_iter_p.first(); } }; template ::difference_type difference_type; - return x.policies().distance(type(), y.iter(), x.iter()); + return x.policies().distance(y, x); } #ifndef BOOST_RELOPS_AMBIGUITY_BUG @@ -773,7 +935,7 @@ operator==( const iterator_adaptor& x, const iterator_adaptor& y) { - return x.policies().equal(x.iter(), y.iter()); + return x.policies().equal(x, y); } template & x, const iterator_adaptor& y) { - return x.policies().less(x.iter(), y.iter()); + return x.policies().distance(x, y) > 0; } template ( const iterator_adaptor& x, const iterator_adaptor& y) { - return x.policies().less(y.iter(), x.iter()); + return x.policies().distance(y, x) > 0; } template =( const iterator_adaptor& x, const iterator_adaptor& y) { - return !x.policies().less(x.iter(), y.iter()); + return !(x.policies().distance(x, y) > 0); } template & x, const iterator_adaptor& y) { - return !x.policies().less(y.iter(), x.iter()); + return !(x.policies().distance(y, x) > 0); } template & x, const iterator_adaptor& y) { - return !x.policies().equal(x.iter(), y.iter()); + return !x.policies().equal(x, y); } #endif @@ -844,9 +1006,10 @@ 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); } + template + typename IteratorAdaptor::reference + dereference(const IteratorAdaptor& iter) const + { return m_f(*iter.base()); } AdaptableUnaryFunction m_f; }; @@ -889,9 +1052,9 @@ make_transform_iterator( struct indirect_iterator_policies : public default_iterator_policies { - template - Reference dereference(type, const Iterator& x) const - { return **x; } + template + typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const + { return **x.base(); } }; namespace detail { @@ -984,34 +1147,30 @@ make_indirect_iterator(OuterIterator base) struct reverse_iterator_policies : public default_iterator_policies { - template - Reference dereference(type, const BidirectionalIterator& x) const - { return *boost::prior(x); } + template + typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const + { return *boost::prior(x.base()); } template void increment(BidirectionalIterator& x) const - { --x; } + { --x.base(); } template void decrement(BidirectionalIterator& x) const - { ++x; } + { ++x.base(); } template void advance(BidirectionalIterator& x, DifferenceType n) const - { x -= n; } + { x.base() -= n; } - template - Difference distance(type, const Iterator1& x, - const Iterator2& y) const - { return x - y; } + template + typename Iterator1::difference_type distance( + const Iterator1& x, const Iterator2& y) const + { return x.base() - y.base(); } 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; } + { return x.base() == y.base(); } }; template - Reference dereference (type, Iterator const& iter) const { - return m_f(*iter); + template + typename IteratorAdaptor::reference dereference(IteratorAdaptor const& iter) const { + return m_f(*iter.base()); } AdaptableUnaryFunction m_f; @@ -1113,28 +1272,29 @@ public: // The Iter template argument is neccessary for compatibility with a MWCW // bug workaround - template - void increment(Iter& x) { - ++x; - satisfy_predicate(x); + template + void increment(IteratorAdaptor& x) { + ++x.base(); + satisfy_predicate(x.base()); } - template - Reference dereference(type, const Iter& x) const - { return *x; } + template + typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const + { return *x.base(); } - template - bool equal(const Iterator1& x, const Iterator2& y) const - { return x == y; } + template + bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const + { return x.base() == y.base(); } private: void satisfy_predicate(Iterator& iter); Predicate m_predicate; Iterator m_end; }; + template -void filter_iterator_policies -::satisfy_predicate(Iterator& iter) +void filter_iterator_policies::satisfy_predicate( + Iterator& iter) { while (m_end != iter && !m_predicate(*iter)) ++iter; From 79370a6dfb7d22935a5fd181ee436e2a513782cd Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 4 Nov 2001 23:24:12 +0000 Subject: [PATCH 132/265] non-named parameter version of some BGL algorithms some VC++ compiler stuff [SVN r11576] --- include/boost/iterator_adaptors.hpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index f81cf63..da811da 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -341,11 +341,8 @@ namespace detail { template inline operator_arrow_proxy operator_arrow(const Iter& i, std::input_iterator_tag) { - return operator_arrow_proxy< -#ifndef BOOST_MSVC - typename -#endif - Iter::value_type>(*i); + typedef typename Iter::value_type value_t; // VC++ needs this typedef + return operator_arrow_proxy(*i); } template From 75023a1dd3b6f32af3c1f85dae74a145101eabc5 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 5 Nov 2001 06:25:31 +0000 Subject: [PATCH 133/265] Fixed comparison bugs; more remain. [SVN r11581] --- include/boost/iterator_adaptors.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index da811da..d6066ca 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -289,7 +289,7 @@ inline bool operator<(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return x.policies().distance(x, y) > 0; + return x.policies().distance(y, x) < 0; } template @@ -307,7 +307,7 @@ inline bool operator>=(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return !(x.policies().distance(x, y) > 0); + return x.policies().distance(y, x) >= 0; } template @@ -316,7 +316,7 @@ inline bool operator<=(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return !(x.policies().distance(y, x) > 0); + return x.policies().distance(y, x) <= 0; } #endif @@ -943,7 +943,7 @@ operator<( const iterator_adaptor& x, const iterator_adaptor& y) { - return x.policies().distance(x, y) > 0; + return x.policies().distance(y, x) < 0; } template =( const iterator_adaptor& x, const iterator_adaptor& y) { - return !(x.policies().distance(x, y) > 0); + return x.policies().distance(y, x) >= 0; } template & x, const iterator_adaptor& y) { - return !(x.policies().distance(y, x) > 0); + return x.policies().distance(y, x) <= 0; } template Date: Mon, 5 Nov 2001 15:25:45 +0000 Subject: [PATCH 134/265] Cleanups for MWERKS, without changing functionality [SVN r11585] --- include/boost/iterator_adaptors.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index d6066ca..5f8b378 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -842,12 +842,12 @@ struct iterator_adaptor : { return *(*this + n); } self& operator++() { -#ifdef __MWERKS__ +#if !defined(__MWERKS__) || __MWERKS__ >= 0x2405 + policies().increment(*this); +#else // Odd bug, MWERKS couldn't deduce the type for the member template // Workaround by explicitly specifying the type. policies().increment(*this); -#else - policies().increment(*this); #endif return *this; } @@ -855,10 +855,10 @@ struct iterator_adaptor : self operator++(int) { self tmp(*this); ++*this; return tmp; } self& operator--() { -#ifdef __MWERKS__ - policies().decrement(*this); -#else +#if !defined(__MWERKS__) || __MWERKS__ >= 0x2405 policies().decrement(*this); +#else + policies().decrement(*this); #endif return *this; } @@ -1314,7 +1314,7 @@ namespace detail { template struct non_bidirectional_category { -# if !defined(__MWERKS__) || __MWERKS__ > 0x4000 +# if !defined(__MWERKS__) || __MWERKS__ > 0x2405 typedef typename reduce_to_base_class< std::forward_iterator_tag, typename iterator_traits::iterator_category From e60df6ad92afe4e1eaf908d36c7ac6db1bfac413 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 5 Nov 2001 16:33:40 +0000 Subject: [PATCH 135/265] Workarounds for CWPro7, MSVC Changed all "bind" to "select" (again), to avoid conflicting with Peter Dimov's code. [SVN r11590] --- include/boost/iterator_adaptors.hpp | 36 ++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 5f8b378..2185768 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -559,7 +559,7 @@ namespace detail { struct find_param; struct find_param_continue { - template struct bind { + template struct select { typedef typename AssocList::first_type Head; typedef typename Head::first_type Key1; typedef typename Head::second_type Value; @@ -571,7 +571,7 @@ namespace detail { }; struct find_param_end { template - struct bind { typedef detail::default_argument type; }; + struct select { typedef detail::default_argument type; }; }; template struct find_param_helper1 { typedef find_param_continue type; }; @@ -581,7 +581,7 @@ namespace detail { template struct find_param { typedef typename find_param_helper1::type select1; - typedef typename select1::template bind::type type; + typedef typename select1::template select::type type; }; #else template struct find_param; @@ -604,18 +604,32 @@ namespace detail { struct make_named_arg { template - struct bind { typedef typename Value::type type; }; + struct select { typedef typename Value::type type; }; }; struct make_key_value { template - struct bind { typedef detail::cons_type type; }; + struct select { typedef detail::cons_type type; }; }; + template + struct is_named_parameter + { + enum { value = is_convertible::value }; + }; + +#if defined(__MWERKS__) && __MWERKS__ <= 0x2405 // workaround for broken is_convertible implementation + template struct is_named_parameter > { enum { value = true }; }; + template struct is_named_parameter > { enum { value = true }; }; + template struct is_named_parameter > { enum { value = true }; }; + template struct is_named_parameter > { enum { value = true }; }; + template struct is_named_parameter > { enum { value = true }; }; +#endif + template struct make_arg { - enum { is_named = is_convertible::value }; + enum { is_named = is_named_parameter::value }; typedef typename ct_if::type Make; - typedef typename Make::template bind::type type; + typedef typename Make::template select::type type; }; // Mechanism for resolving the default argument for a template parameter. @@ -626,14 +640,14 @@ namespace detail { struct choose_default { template - struct bind { + struct select { typedef typename default_generator::type Gen; typedef typename Gen::template select::type type; }; }; struct choose_arg { template - struct bind { + struct select { typedef Arg type; }; }; @@ -650,7 +664,7 @@ namespace detail { Selector; public: typedef typename Selector - ::template bind::type type; + ::template select::type type; }; template = ForwardIterator must produce real references // as required by the C++ standard requirements in Table 74. BOOST_STATIC_CONSTANT(bool, forward_iter_with_real_reference = @@ -791,7 +806,6 @@ struct iterator_adaptor : || boost::is_same::value || boost::is_same::value)); -#if !defined(BOOST_MSVC) // This check gives incorrect results in iter_traits_gen_test.cpp BOOST_STATIC_ASSERT(forward_iter_with_real_reference); #endif From e162a75e535f9b6c6d2ca13fbcefc4706d796416 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Tue, 6 Nov 2001 15:28:04 +0000 Subject: [PATCH 136/265] *** empty log message *** [SVN r11609] --- include/boost/iterator_adaptors.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 2185768..725bdf4 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -116,7 +116,6 @@ # 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 @@ -554,7 +553,7 @@ namespace detail { // An associative list is a list of key-value pairs. The list is // built out of cons_type's and is terminated by end_of_list. -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(__BORLANDC__) template struct find_param; @@ -563,8 +562,8 @@ namespace detail { typedef typename AssocList::first_type Head; typedef typename Head::first_type Key1; typedef typename Head::second_type Value; - typedef typename ct_if::value, - Value, + typedef typename if_true<(is_same::value)>::template + then::type >::type type; }; @@ -628,7 +627,8 @@ namespace detail { template struct make_arg { enum { is_named = is_named_parameter::value }; - typedef typename ct_if::type Make; + typedef typename if_true<(is_named)>::template + then::type Make; typedef typename Make::template select::type type; }; From 4da7371246ae37f0b0ace28b4d7c2a7079429e86 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Tue, 6 Nov 2001 15:52:56 +0000 Subject: [PATCH 137/265] *** empty log message *** [SVN r11611] --- include/boost/iterator_adaptors.hpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 725bdf4..35b1c56 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -354,7 +354,6 @@ namespace detail { struct operator_arrow_result_generator { typedef operator_arrow_proxy proxy; - // Borland chokes unless it's an actual enum (!) enum { is_input_iter = (boost::is_convertible::value @@ -626,9 +625,16 @@ namespace detail { template struct make_arg { +#ifdef __BORLANDC__ + // Borland C++ doesn't like the extra indirection of is_named_parameter + typedef typename + if_true<(is_convertible::value)>:: + template then::type Make; +#else enum { is_named = is_named_parameter::value }; typedef typename if_true<(is_named)>::template then::type Make; +#endif typedef typename Make::template select::type type; }; @@ -779,7 +785,8 @@ struct iterator_adaptor : { typedef iterator_adaptor self; public: - typedef typename detail::iterator_adaptor_traits_gen::type Traits; + typedef detail::iterator_adaptor_traits_gen TraitsGen; + typedef typename TraitsGen::type Traits; typedef typename Traits::difference_type difference_type; typedef typename Traits::value_type value_type; From 8a4839354e8f34259531882945bf0f466bcecfeb Mon Sep 17 00:00:00 2001 From: Toon Knapen Date: Fri, 30 Nov 2001 10:38:36 +0000 Subject: [PATCH 138/265] permutation_iterator_adaptor and generator [SVN r11823] --- include/boost/permutation_iterator.hpp | 71 ++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 include/boost/permutation_iterator.hpp diff --git a/include/boost/permutation_iterator.hpp b/include/boost/permutation_iterator.hpp new file mode 100644 index 0000000..7c05cab --- /dev/null +++ b/include/boost/permutation_iterator.hpp @@ -0,0 +1,71 @@ +// (C) Copyright Toon Knapen 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. +// + +#include + +namespace boost { + + template < typename OrderIt > + struct permutation_iterator_policies : public default_iterator_policies + { + permutation_iterator_policies() {} + + permutation_iterator_policies(OrderIt order_it) + : order_it_( order_it ) + {} + + template + typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const + { return *(x.base() + *order_it_); } + + template + void increment(IteratorAdaptor& x) + { ++order_it_; } + + template + void decrement(IteratorAdaptor& x) + { --order_it_; } + + template + void advance(IteratorAdaptor& x, DifferenceType n) + { std::advance( order_it_, n ); } + + template + typename IteratorAdaptor1::difference_type + distance(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const + { return std::distance( x.policies().order_it_, y.policies().order_it_ ); } + + template + bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const + { return x.policies().order_it_ == y.policies().order_it_; } + + OrderIt order_it_; + }; + + /// generate an iterator that will access the elements + /// behind the random-access iterator RAIt in the + /// order specified by the OrderIt iterator. + /// preconditions: + /// The OrderIt::value_type will be used in iterator arithmetic + template < typename RAIt, typename OrderIt > + struct permutation_iterator_generator + { + typedef boost::iterator_adaptor + < RAIt, + permutation_iterator_policies< OrderIt > + > type; + }; + + template < class OrderIt, class RAIt > + inline typename permutation_iterator_generator< RAIt, OrderIt >::type + make_permutation_iterator(RAIt base, OrderIt order) + { + typedef typename permutation_iterator_generator< RAIt, OrderIt >::type result_t; + return result_t( base, order ); + } + +} // namespace boost From 50a502bb8128f8658fdf5c37adf369420707c742 Mon Sep 17 00:00:00 2001 From: Toon Knapen Date: Fri, 30 Nov 2001 11:14:24 +0000 Subject: [PATCH 139/265] uses proper template argument names : ElementIterator and IndexIterator [SVN r11826] --- include/boost/permutation_iterator.hpp | 29 +++++++++++--------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/include/boost/permutation_iterator.hpp b/include/boost/permutation_iterator.hpp index 7c05cab..581c486 100644 --- a/include/boost/permutation_iterator.hpp +++ b/include/boost/permutation_iterator.hpp @@ -9,12 +9,12 @@ namespace boost { - template < typename OrderIt > + template < typename IndexIterator > struct permutation_iterator_policies : public default_iterator_policies { permutation_iterator_policies() {} - permutation_iterator_policies(OrderIt order_it) + permutation_iterator_policies(IndexIterator order_it) : order_it_( order_it ) {} @@ -23,11 +23,11 @@ namespace boost { { return *(x.base() + *order_it_); } template - void increment(IteratorAdaptor& x) + void increment(IteratorAdaptor&) { ++order_it_; } template - void decrement(IteratorAdaptor& x) + void decrement(IteratorAdaptor&) { --order_it_; } template @@ -43,28 +43,23 @@ namespace boost { bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const { return x.policies().order_it_ == y.policies().order_it_; } - OrderIt order_it_; + IndexIterator order_it_; }; - /// generate an iterator that will access the elements - /// behind the random-access iterator RAIt in the - /// order specified by the OrderIt iterator. - /// preconditions: - /// The OrderIt::value_type will be used in iterator arithmetic - template < typename RAIt, typename OrderIt > + template < typename ElementIterator, typename IndexIterator > struct permutation_iterator_generator { typedef boost::iterator_adaptor - < RAIt, - permutation_iterator_policies< OrderIt > + < ElementIterator, + permutation_iterator_policies< IndexIterator > > type; }; - template < class OrderIt, class RAIt > - inline typename permutation_iterator_generator< RAIt, OrderIt >::type - make_permutation_iterator(RAIt base, OrderIt order) + template < class IndexIterator, class ElementIterator > + inline typename permutation_iterator_generator< ElementIterator, IndexIterator >::type + make_permutation_iterator(ElementIterator base, IndexIterator order) { - typedef typename permutation_iterator_generator< RAIt, OrderIt >::type result_t; + typedef typename permutation_iterator_generator< ElementIterator, IndexIterator >::type result_t; return result_t( base, order ); } From 37aee7c13be6f70d933eecb86be3c4db748ce4d4 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 13 Dec 2001 14:34:11 +0000 Subject: [PATCH 140/265] Re-enabled some STATIC_ASSERTs for MSVC, using bitwise operators to avoid ICEs. [SVN r12030] --- include/boost/iterator_adaptors.hpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 35b1c56..1cba09a 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -800,22 +800,20 @@ struct iterator_adaptor : private: BOOST_STATIC_CONSTANT(bool, is_input_or_output_iter = (boost::is_convertible::value - || boost::is_convertible::value)); + | boost::is_convertible::value)); // Iterators should satisfy one of the known categories BOOST_STATIC_ASSERT(is_input_or_output_iter); -#if !defined(BOOST_MSVC) // Iterators >= ForwardIterator must produce real references // as required by the C++ standard requirements in Table 74. - BOOST_STATIC_CONSTANT(bool, forward_iter_with_real_reference = - (!boost::is_convertible::value - || boost::is_same::value - || boost::is_same::value)); + BOOST_STATIC_CONSTANT(bool, forward_iter_with_real_reference + = ((!boost::is_convertible::value) + | boost::is_same::value + | boost::is_same::value)); // This check gives incorrect results in iter_traits_gen_test.cpp BOOST_STATIC_ASSERT(forward_iter_with_real_reference); -#endif public: iterator_adaptor() { } From 76a307d31edb555043be78ac47e0b5a6bf96ddb0 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 24 Dec 2001 19:27:39 +0000 Subject: [PATCH 141/265] fixes [SVN r12146] --- include/boost/iterator_adaptors.hpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 1cba09a..3387bb6 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,8 @@ // // Revision History: +// 20 Dec 2001 David Abrahams +// Adjusted is_convertible workarounds for __MWERKS__ == 0x2406 // 03 Nov 2001 Jeremy Siek // Changed the named template parameter interface and internal. // 04 Oct 2001 Jeremy Siek @@ -615,7 +617,7 @@ namespace detail { enum { value = is_convertible::value }; }; -#if defined(__MWERKS__) && __MWERKS__ <= 0x2405 // workaround for broken is_convertible implementation +#if defined(__MWERKS__) && __MWERKS__ <= 0x2406 // workaround for broken is_convertible implementation template struct is_named_parameter > { enum { value = true }; }; template struct is_named_parameter > { enum { value = true }; }; template struct is_named_parameter > { enum { value = true }; }; @@ -767,11 +769,11 @@ template struct undefined; // Distance - the difference_type of the resulting iterator. If not // supplied, iterator_traits::difference_type is used. template struct iterator_adaptor : #ifdef BOOST_RELOPS_AMBIGUITY_BUG From 15a7a839f9b31d1cf6f5801732caf00ab4cfa3b7 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 7 Jan 2002 15:43:30 +0000 Subject: [PATCH 142/265] Choose proxy for operator->() only if the reference type is not a reference. Updated workarounds for __MWERKS__ == 0x2406 [SVN r12245] --- include/boost/iterator_adaptors.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 3387bb6..96bc148 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,9 @@ // // Revision History: +// 07 Jan 2001 David Abrahams +// Choose proxy for operator->() only if the reference type is not a reference. +// Updated workarounds for __MWERKS__ == 0x2406 // 20 Dec 2001 David Abrahams // Adjusted is_convertible workarounds for __MWERKS__ == 0x2406 // 03 Nov 2001 Jeremy Siek @@ -352,17 +355,14 @@ namespace detail { return &(*i); } - template + template struct operator_arrow_result_generator { typedef operator_arrow_proxy proxy; // Borland chokes unless it's an actual enum (!) - enum { is_input_iter - = (boost::is_convertible::value - & !boost::is_convertible::value) - }; + enum { use_proxy = !boost::is_reference::value }; - typedef typename boost::detail::if_true<(is_input_iter)>::template + typedef typename boost::detail::if_true<(use_proxy)>::template then< proxy, // else @@ -851,7 +851,7 @@ struct iterator_adaptor : # pragma warning( disable : 4284 ) #endif - typename boost::detail::operator_arrow_result_generator::type + typename boost::detail::operator_arrow_result_generator::type operator->() const { return detail::operator_arrow(*this, iterator_category()); } @@ -1335,7 +1335,7 @@ namespace detail { template struct non_bidirectional_category { -# if !defined(__MWERKS__) || __MWERKS__ > 0x2405 +# if !defined(__MWERKS__) || __MWERKS__ > 0x2406 typedef typename reduce_to_base_class< std::forward_iterator_tag, typename iterator_traits::iterator_category From ebcb4d861a78c1534720de91c1f1748b392fb3f7 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 8 Jan 2002 18:36:26 +0000 Subject: [PATCH 143/265] Borland workarounds [SVN r12251] --- include/boost/counting_iterator.hpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index 84dce41..0e39a6d 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -199,15 +199,20 @@ struct counting_iterator_policies : public default_iterator_policies template struct counting_iterator_generator { - typedef counting_iterator_traits traits; + typedef typename boost::remove_const< + Incrementable + >::type value_type; - typedef iterator_adaptor, - Incrementable, - const Incrementable&, - const Incrementable*, - typename traits::iterator_category, - typename traits::difference_type + typedef counting_iterator_traits traits; + + typedef iterator_adaptor< + value_type + , counting_iterator_policies + , value_type + , value_type const& + , value_type const* + , typename traits::iterator_category + , typename traits::difference_type > type; }; From 57251d58ccbe6ca62233f3b8cf4b8babef34bb7c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 9 Jan 2002 12:14:16 +0000 Subject: [PATCH 144/265] Moved concept checks into a separate class, which makes MSVC better at dealing with them [SVN r12255] --- include/boost/iterator_adaptors.hpp | 179 +++++++++++++++------------- 1 file changed, 96 insertions(+), 83 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 96bc148..6088b8d 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,9 @@ // // Revision History: +// 08 Jan 2001 David Abrahams +// Moved concept checks into a separate class, which makes MSVC +// better at dealing with them. // 07 Jan 2001 David Abrahams // Choose proxy for operator->() only if the reference type is not a reference. // Updated workarounds for __MWERKS__ == 0x2406 @@ -124,7 +127,7 @@ // 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 +// 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 @@ -168,7 +171,7 @@ struct ForwardIteratorPoliciesConcept { typedef typename Traits::iterator_category iterator_category; void constraints() { - function_requires< + function_requires< TrivialIteratorPoliciesConcept >(); @@ -186,7 +189,7 @@ struct BidirectionalIteratorPoliciesConcept { typedef typename Traits::iterator_category iterator_category; void constraints() { - function_requires< + function_requires< ForwardIteratorPoliciesConcept >(); @@ -204,7 +207,7 @@ struct RandomAccessIteratorPoliciesConcept typedef typename Traits::difference_type DifferenceType; typedef typename Traits::iterator_category iterator_category; void constraints() { - function_requires< + function_requires< BidirectionalIteratorPoliciesConcept >(); @@ -262,7 +265,7 @@ struct default_iterator_policies { return x.base() == y.base(); } }; -// putting the comparisons in a base class avoids the g++ +// putting the comparisons in a base class avoids the g++ // ambiguous overload bug due to the relops operators #ifdef BOOST_RELOPS_AMBIGUITY_BUG @@ -270,7 +273,7 @@ template struct iterator_comparisons : Base { }; template -inline bool operator==(const iterator_comparisons& xb, +inline bool operator==(const iterator_comparisons& xb, const iterator_comparisons& yb) { const D1& x = static_cast(xb); @@ -279,7 +282,7 @@ inline bool operator==(const iterator_comparisons& xb, } template -inline bool operator!=(const iterator_comparisons& xb, +inline bool operator!=(const iterator_comparisons& xb, const iterator_comparisons& yb) { const D1& x = static_cast(xb); @@ -288,7 +291,7 @@ inline bool operator!=(const iterator_comparisons& xb, } template -inline bool operator<(const iterator_comparisons& xb, +inline bool operator<(const iterator_comparisons& xb, const iterator_comparisons& yb) { const D1& x = static_cast(xb); @@ -297,16 +300,16 @@ inline bool operator<(const iterator_comparisons& xb, } template -inline bool operator>(const iterator_comparisons& xb, +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().distance(y, x) > 0; } template -inline bool operator>=(const iterator_comparisons& xb, +inline bool operator>=(const iterator_comparisons& xb, const iterator_comparisons& yb) { const D1& x = static_cast(xb); @@ -315,7 +318,7 @@ inline bool operator>=(const iterator_comparisons& xb, } template -inline bool operator<=(const iterator_comparisons& xb, +inline bool operator<=(const iterator_comparisons& xb, const iterator_comparisons& yb) { const D1& x = static_cast(xb); @@ -361,7 +364,7 @@ namespace detail { typedef operator_arrow_proxy proxy; // Borland chokes unless it's an actual enum (!) enum { use_proxy = !boost::is_reference::value }; - + typedef typename boost::detail::if_true<(use_proxy)>::template then< proxy, @@ -424,14 +427,14 @@ namespace detail { typename iterator_traits::pointer, Value* >::type pointer; - + typedef typename if_true<( ::boost::is_same::value_type>::value )>::template then< typename iterator_traits::reference, Value& >::type reference; - + }; # endif @@ -480,7 +483,7 @@ namespace detail { template struct select { typedef typename Traits::value_type Value; - typedef typename boost::detail::iterator_defaults::pointer + typedef typename boost::detail::iterator_defaults::pointer type; }; }; @@ -491,7 +494,7 @@ namespace detail { template struct select { typedef typename Traits::value_type Value; - typedef typename boost::detail::iterator_defaults::reference + typedef typename boost::detail::iterator_defaults::reference type; }; }; @@ -540,7 +543,7 @@ template struct difference_type_is { typedef detail::cons_type type; }; -template struct iterator_category_is +template struct iterator_category_is : public named_template_param_base { typedef detail::cons_type type; @@ -554,7 +557,7 @@ namespace detail { // An associative list is a list of key-value pairs. The list is // built out of cons_type's and is terminated by end_of_list. -#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(__BORLANDC__) +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(__BORLANDC__) template struct find_param; @@ -564,7 +567,7 @@ namespace detail { typedef typename Head::first_type Key1; typedef typename Head::second_type Value; typedef typename if_true<(is_same::value)>::template - then::type >::type type; }; @@ -583,7 +586,7 @@ namespace detail { typedef typename find_param_helper1::type select1; typedef typename select1::template select::type type; }; -#else +# else template struct find_param; template @@ -600,7 +603,7 @@ namespace detail { struct find_param, Rest>, Key2> { typedef typename find_param::type type; }; -#endif +# endif struct make_named_arg { template @@ -617,26 +620,26 @@ namespace detail { enum { value = is_convertible::value }; }; -#if defined(__MWERKS__) && __MWERKS__ <= 0x2406 // workaround for broken is_convertible implementation +# if defined(__MWERKS__) && __MWERKS__ <= 0x2406 // workaround for broken is_convertible implementation template struct is_named_parameter > { enum { value = true }; }; template struct is_named_parameter > { enum { value = true }; }; template struct is_named_parameter > { enum { value = true }; }; template struct is_named_parameter > { enum { value = true }; }; template struct is_named_parameter > { enum { value = true }; }; -#endif +# endif template struct make_arg { -#ifdef __BORLANDC__ +# ifdef __BORLANDC__ // Borland C++ doesn't like the extra indirection of is_named_parameter - typedef typename + typedef typename if_true<(is_convertible::value)>:: template then::type Make; -#else +# else enum { is_named = is_named_parameter::value }; typedef typename if_true<(is_named)>::template then::type Make; -#endif +# endif typedef typename Make::template select::type type; }; @@ -680,7 +683,7 @@ namespace detail { class iterator_adaptor_traits_gen { // Form an associative list out of the template parameters - // If the argument is a normal parameter (not named) then make_arg + // If the argument is a normal parameter (not named) then make_arg // creates a key-value pair. If the argument is a named parameter, // then make_arg extracts the key-value pair defined inside the // named parameter. @@ -705,9 +708,9 @@ namespace detail { typedef typename resolve_default::type value_type; // if getting default value type from iterator_traits, then it won't be const - typedef typename resolve_default::type difference_type; - typedef typename resolve_default::type iterator_category; typedef boost::iterator::type reference; - + public: typedef boost::iterator::type, + typename remove_const::type, difference_type, pointer, reference> type; }; + // This is really a partial concept check for iterators. Should it + // be moved or done differently? + template + struct validator + { + BOOST_STATIC_CONSTANT( + bool, is_input_or_output_iter + = (boost::is_convertible::value + | boost::is_convertible::value)); + + // Iterators should satisfy one of the known categories + BOOST_STATIC_ASSERT(is_input_or_output_iter); + + // Iterators >= ForwardIterator must produce real references + // as required by the C++ standard requirements in Table 74. + BOOST_STATIC_CONSTANT( + bool, forward_iter_with_real_reference + = ((!boost::is_convertible::value) + | boost::is_same::value + | boost::is_same::type&>::value)); + + BOOST_STATIC_ASSERT(forward_iter_with_real_reference); + }; } // namespace detail @@ -738,8 +764,6 @@ namespace detail { # define BOOST_ARG_DEPENDENT_TYPENAME # endif -template struct undefined; - //============================================================================ //iterator_adaptor - Adapts a generic piece of data as an iterator. Adaptation // is especially easy if the data being adapted is itself an iterator @@ -768,7 +792,7 @@ template struct undefined; // // Distance - the difference_type of the resulting iterator. If not // supplied, iterator_traits::difference_type is used. -template ::value - | boost::is_convertible::value)); - - // Iterators should satisfy one of the known categories - BOOST_STATIC_ASSERT(is_input_or_output_iter); - - // Iterators >= ForwardIterator must produce real references - // as required by the C++ standard requirements in Table 74. - BOOST_STATIC_CONSTANT(bool, forward_iter_with_real_reference - = ((!boost::is_convertible::value) - | boost::is_same::value - | boost::is_same::value)); - - // This check gives incorrect results in iter_traits_gen_test.cpp - BOOST_STATIC_ASSERT(forward_iter_with_real_reference); + typedef detail::validator< + iterator_category,value_type,difference_type,pointer,reference + > concept_check; public: - iterator_adaptor() { } + iterator_adaptor() + { + } explicit iterator_adaptor(const Base& it, const Policies& p = Policies()) : m_iter_p(it, p) { - policies().initialize(base()); + policies().initialize(base()); } template @@ -861,7 +874,7 @@ struct iterator_adaptor : value_type operator[](difference_type n) const { return *(*this + n); } - + self& operator++() { #if !defined(__MWERKS__) || __MWERKS__ >= 0x2405 policies().increment(*this); @@ -874,7 +887,7 @@ struct iterator_adaptor : } self operator++(int) { self tmp(*this); ++*this; return tmp; } - + self& operator--() { #if !defined(__MWERKS__) || __MWERKS__ >= 0x2405 policies().decrement(*this); @@ -883,14 +896,14 @@ struct iterator_adaptor : #endif return *this; } - + self operator--(int) { self tmp(*this); --*this; return tmp; } self& operator+=(difference_type n) { policies().advance(*this, n); return *this; } - + self& operator-=(difference_type n) { policies().advance(*this, -n); return *this; @@ -948,7 +961,7 @@ operator-( template -inline bool +inline bool operator==( const iterator_adaptor& x, const iterator_adaptor& y) @@ -959,7 +972,7 @@ operator==( template -inline bool +inline bool operator<( const iterator_adaptor& x, const iterator_adaptor& y) @@ -970,18 +983,18 @@ operator<( template -inline bool +inline bool operator>( const iterator_adaptor& x, const iterator_adaptor& y) -{ +{ return x.policies().distance(y, x) > 0; } template -inline bool +inline bool operator>=( const iterator_adaptor& x, const iterator_adaptor& y) @@ -992,7 +1005,7 @@ operator>=( template -inline bool +inline bool operator<=( const iterator_adaptor& x, const iterator_adaptor& y) @@ -1003,9 +1016,9 @@ operator<=( template -inline bool +inline bool operator!=( - const iterator_adaptor& x, + const iterator_adaptor& x, const iterator_adaptor& y) { return !x.policies().equal(x, y); @@ -1023,7 +1036,7 @@ struct transform_iterator_policies : public default_iterator_policies { transform_iterator_policies() { } transform_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { } - + template typename IteratorAdaptor::reference dereference(const IteratorAdaptor& iter) const @@ -1037,7 +1050,7 @@ class transform_iterator_generator { typedef typename AdaptableUnaryFunction::result_type value_type; public: - typedef iterator_adaptor, value_type, value_type, value_type*, std::input_iterator_tag> type; @@ -1093,7 +1106,7 @@ template ::value_type #endif - , class Reference + , class Reference #if !defined(BOOST_MSVC) = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::reference @@ -1102,7 +1115,7 @@ template ::iterator_category - , class Pointer + , class Pointer #if !defined(BOOST_MSVC) = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::pointer @@ -1122,7 +1135,7 @@ template ::value_type #endif - , class Reference + , class Reference #if !defined(BOOST_MSVC) = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::reference @@ -1132,7 +1145,7 @@ template ::iterator_category - , class Pointer + , class Pointer #if !defined(BOOST_MSVC) = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::pointer @@ -1168,29 +1181,29 @@ struct reverse_iterator_policies : public default_iterator_policies template typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const { return *boost::prior(x.base()); } - + template void increment(BidirectionalIterator& x) const { --x.base(); } - + template void decrement(BidirectionalIterator& x) const { ++x.base(); } - + template void advance(BidirectionalIterator& x, DifferenceType n) const { x.base() -= n; } - + template typename Iterator1::difference_type distance( const Iterator1& x, const Iterator2& y) const { return x.base() - y.base(); } - + template bool equal(const Iterator1& x, const Iterator2& y) const { return x.base() == y.base(); } }; - + template ::value_type, class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, @@ -1226,7 +1239,7 @@ struct projection_iterator_policies : public default_iterator_policies return m_f(*iter.base()); } - AdaptableUnaryFunction m_f; + AdaptableUnaryFunction m_f; }; template @@ -1255,7 +1268,7 @@ struct projection_iterator_pair_generator { template inline typename projection_iterator_generator::type make_projection_iterator( - Iterator iter, + Iterator iter, const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) { typedef typename projection_iterator_generator::type result_t; @@ -1265,7 +1278,7 @@ make_projection_iterator( template inline typename const_projection_iterator_generator::type make_const_projection_iterator( - Iterator iter, + Iterator iter, const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) { typedef typename const_projection_iterator_generator::type result_t; @@ -1281,7 +1294,7 @@ class filter_iterator_policies public: filter_iterator_policies() { } - filter_iterator_policies(const Predicate& p, const Iterator& end) + filter_iterator_policies(const Predicate& p, const Iterator& end) : m_predicate(p), m_end(end) { } void initialize(Iterator& x) { @@ -1361,7 +1374,7 @@ namespace detail { }; } -template ::value_type, class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, From bd666dc0e9680599bf9f0c92783850fac4b915f2 Mon Sep 17 00:00:00 2001 From: Toon Knapen Date: Sat, 26 Jan 2002 09:26:09 +0000 Subject: [PATCH 145/265] added include guards [SVN r12517] --- include/boost/permutation_iterator.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/boost/permutation_iterator.hpp b/include/boost/permutation_iterator.hpp index 581c486..28ecfbb 100644 --- a/include/boost/permutation_iterator.hpp +++ b/include/boost/permutation_iterator.hpp @@ -5,6 +5,9 @@ // to its suitability for any purpose. // +#ifndef boost_permutation_iterator_hpp +#define boost_permutation_iterator_hpp + #include namespace boost { @@ -64,3 +67,6 @@ namespace boost { } } // namespace boost + +#endif // boost_permutation_iterator_hpp + From 8cb49713b47bcf31fd5179cf3bc0b265fd3c712f Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sun, 27 Jan 2002 14:55:20 +0000 Subject: [PATCH 146/265] half_open_range.hpp: - counting_iterator_traits does not contain the iterator traits value_type, reference, pointer, etc. [SVN r12526] --- include/boost/half_open_range.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/boost/half_open_range.hpp b/include/boost/half_open_range.hpp index 1de1e9d..c281846 100644 --- a/include/boost/half_open_range.hpp +++ b/include/boost/half_open_range.hpp @@ -99,17 +99,17 @@ struct half_open_range public: typedef iter_t 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; + typedef typename iterator::value_type value_type; + typedef typename iterator::difference_type difference_type; + typedef typename iterator::reference reference; + typedef typename iterator::reference const_reference; + typedef typename iterator::pointer pointer; + typedef typename iterator::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; + typedef typename iterator::difference_type size_type; half_open_range(Incrementable start, Incrementable finish) : m_start(start), From 2be5179020b30682849d9554708d3700785ede74 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 4 Feb 2002 20:01:51 +0000 Subject: [PATCH 147/265] killed tabs [SVN r12702] --- include/boost/iterator_adaptors.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 6088b8d..3bbbb93 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -484,7 +484,7 @@ namespace detail { struct select { typedef typename Traits::value_type Value; typedef typename boost::detail::iterator_defaults::pointer - type; + type; }; }; template <> struct default_generator @@ -495,7 +495,7 @@ namespace detail { struct select { typedef typename Traits::value_type Value; typedef typename boost::detail::iterator_defaults::reference - type; + type; }; }; template <> struct default_generator From 4772bb099e3d13563d1d55f84458bcf06ec9b9b1 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 4 Feb 2002 20:25:45 +0000 Subject: [PATCH 148/265] added more comments in the default_iterator_policies [SVN r12706] --- include/boost/iterator_adaptors.hpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 3bbbb93..4dec933 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,8 @@ // // Revision History: +// 01 Feb 2002 Jeremy Siek +// Added more comments in default_iterator_policies. // 08 Jan 2001 David Abrahams // Moved concept checks into a separate class, which makes MSVC // better at dealing with them. @@ -231,9 +233,15 @@ struct RandomAccessIteratorPoliciesConcept // 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. + // Some of the member functions were defined static, but Borland + // got confused and thought they were non-const. Also, Sun C++ + // does not like static function templates. + // + // The reason some members were defined static is because there is + // not state (data members) needed by those members of the + // default_iterator_policies class. If your policies class member + // functions need to access state stored in the policies object, + // then the member functions should not be static (they can't be). template void initialize(Base&) From 12b9366f33848a0d354cbf3aeefb86b1657528a4 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 1 Apr 2002 18:57:43 +0000 Subject: [PATCH 149/265] BOOST_NO_LIMITS should not be used by user code; use instead BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS should not be defined when BOOST_NO_LIMITS is defined [SVN r13340] --- include/boost/counting_iterator.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index 0e39a6d..94173c4 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -56,9 +56,7 @@ # include # include # include -# ifndef BOOST_NO_LIMITS -# include -# endif +# include namespace boost { From 2574365b5c29b31d280958da56ad76c30a6d97d8 Mon Sep 17 00:00:00 2001 From: Toon Knapen Date: Fri, 3 May 2002 13:52:39 +0000 Subject: [PATCH 150/265] added support for reference named_parameters [SVN r13638] --- 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 4dec933..6fc8bd6 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -625,7 +625,7 @@ namespace detail { template struct is_named_parameter { - enum { value = is_convertible::value }; + enum { value = is_convertible< add_reference< Value >::type, add_reference< named_template_param_base >::type >::value }; }; # if defined(__MWERKS__) && __MWERKS__ <= 0x2406 // workaround for broken is_convertible implementation From e9b33b336c79c488579dcbfeb86e4eee9c753e63 Mon Sep 17 00:00:00 2001 From: Toon Knapen Date: Mon, 6 May 2002 06:44:14 +0000 Subject: [PATCH 151/265] added typename keyword (Bertolt Mildner) [SVN r13675] --- 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 6fc8bd6..7da2738 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -625,7 +625,7 @@ namespace detail { template struct is_named_parameter { - enum { value = is_convertible< add_reference< Value >::type, add_reference< named_template_param_base >::type >::value }; + enum { value = is_convertible< typename add_reference< Value >::type, add_reference< named_template_param_base >::type >::value }; }; # if defined(__MWERKS__) && __MWERKS__ <= 0x2406 // workaround for broken is_convertible implementation From fdd1601ba4064593fe5765fd1332bd95fed4ad6e Mon Sep 17 00:00:00 2001 From: John Maddock Date: Tue, 7 May 2002 11:24:29 +0000 Subject: [PATCH 152/265] Added new config macro BOOST_HAS_MS_INT64 to detect presence of __int64 data type. Modified boost source to use BOOST_HAS_LONG_LONG and BOOST_HAS_MS_INT64 where appropriate to do so. [SVN r13714] --- include/boost/counting_iterator.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index 94173c4..ef3b07d 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -133,7 +133,7 @@ namespace detail { // For a while, this wasn't true, but we rely on it below. This is a regression assert. BOOST_STATIC_ASSERT(::boost::is_integral::value); # ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS -# if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) +# if defined(BOOST_HAS_LONG_LONG) BOOST_STATIC_CONSTANT(bool, value = ( std::numeric_limits::is_specialized From 3844edc4bffc63dd2561a4324c392a1ca7de90ec Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 7 May 2002 11:56:08 +0000 Subject: [PATCH 153/265] Fixed input iterator requirements. For a == b a++ == b++ is no longer required. See 24.1.1/3 for details. (Thomas Witt) [SVN r13716] --- include/boost/pending/iterator_tests.hpp | 65 +++++++++++++++++++----- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp index c3c3601..88e1c05 100644 --- a/include/boost/pending/iterator_tests.hpp +++ b/include/boost/pending/iterator_tests.hpp @@ -5,6 +5,10 @@ // test suite for STL concepts such as iterators and containers. // // Revision History: +// 28 Apr 2002 Fixed input iterator requirements. +// For a == b a++ == b++ is no longer required. +// See 24.1.1/3 for details. +// (Thomas Witt) // 08 Feb 2001 Fixed bidirectional iterator test so that // --i is no longer a precondition. // (Jeremy Siek) @@ -74,22 +78,40 @@ void mutable_trivial_iterator_test(const Iterator i, const Iterator j, T val) template void input_iterator_test(Iterator i, T v1, T v2) { - Iterator i1 = i, i2 = i; + Iterator i1(i); - assert(i == i1++); - assert(i != ++i2); - - trivial_iterator_test(i, i1, v1); - trivial_iterator_test(i, i2, v1); - - ++i; assert(i == i1); - assert(i == i2); - ++i1; - ++i2; + assert(!(i != i1)); - trivial_iterator_test(i, i1, v2); - trivial_iterator_test(i, i2, v2); + // I can see no generic way to create an input iterator + // that is in the domain of== of i and != i. + // The following works for istream_iterator but is not + // guaranteed to work for arbitrary input iterators. + // + // Iterator i2; + // + // assert(i != i2); + // assert(!(i == i2)); + + assert(*i1 == v1); + assert(*i == v1); + + // we cannot test for equivalence of (void)++i & (void)i++ + // as i is only guaranteed to be single pass. + assert(*i++ == v1); + + i1 = i; + + assert(i == i1); + assert(!(i != i1)); + + assert(*i1 == v2); + assert(*i == v2); + + // i is dereferencable, so it must be incrementable. + ++i; + + // how to test for operator-> ? } // how to test output iterator? @@ -124,6 +146,23 @@ void forward_iterator_test(Iterator i, T v1, T v2) { input_iterator_test(i, v1, v2); + Iterator i1 = i, i2 = i; + + assert(i == i1++); + assert(i != ++i2); + + trivial_iterator_test(i, i1, v1); + trivial_iterator_test(i, i2, v1); + + ++i; + assert(i == i1); + assert(i == i2); + ++i1; + ++i2; + + trivial_iterator_test(i, i1, v2); + trivial_iterator_test(i, i2, v2); + // borland doesn't allow non-type template parameters # if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551) lvalue_test<(boost::is_pointer::value)>::check(i); From 4a24e0f401106b501e9ab5ca27013fb8c385aced Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 13 Jul 2002 12:11:06 +0000 Subject: [PATCH 154/265] Fixed for VC7.1 [SVN r14433] --- include/boost/iterator_adaptors.hpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 7da2738..f0ef010 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -147,7 +147,7 @@ namespace boost { template struct TrivialIteratorPoliciesConcept { - typedef typename Traits::reference Reference; + typedef typename Traits::reference reference; void constraints() { function_requires< AssignableConcept >(); function_requires< DefaultConstructibleConcept >(); @@ -157,7 +157,7 @@ struct TrivialIteratorPoliciesConcept const_constraints(); } void const_constraints() const { - Reference r = p.dereference(x); + reference r = p.dereference(x); b = p.equal(x, x); ignore_unused_variable_warning(r); } @@ -766,7 +766,7 @@ namespace detail { // This macro definition is only temporary in this file -# if !defined(BOOST_MSVC) +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 # define BOOST_ARG_DEPENDENT_TYPENAME typename # else # define BOOST_ARG_DEPENDENT_TYPENAME @@ -855,9 +855,9 @@ struct iterator_adaptor : policies().initialize(base()); } -#if defined(BOOST_MSVC) || defined(__BORLANDC__) +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__BORLANDC__) // This is required to prevent a bug in how VC++ generates - // the assignment operator for compressed_pairv + // the assignment operator for compressed_pair iterator_adaptor& operator= (const iterator_adaptor& x) { m_iter_p = x.m_iter_p; return *this; @@ -1097,7 +1097,7 @@ struct indirect_iterator_policies : public default_iterator_policies }; namespace detail { -# if !defined(BOOST_MSVC) // stragely instantiated even when unused! Maybe try a recursive template someday ;-) +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // strangely instantiated even when unused! Maybe try a recursive template someday ;-) template struct traits_of_value_type { typedef typename boost::detail::iterator_traits::value_type outer_value; @@ -1110,12 +1110,12 @@ namespace detail { template 1300 = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::value_type #endif , class Reference -#if !defined(BOOST_MSVC) +#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::reference #else @@ -1124,7 +1124,7 @@ template ::iterator_category , class Pointer -#if !defined(BOOST_MSVC) +#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::pointer #else @@ -1139,12 +1139,12 @@ struct indirect_iterator_generator template 1300 = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::value_type #endif , class Reference -#if !defined(BOOST_MSVC) +#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::reference #else @@ -1154,7 +1154,7 @@ template ::iterator_category , class Pointer -#if !defined(BOOST_MSVC) +#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::pointer #else @@ -1170,7 +1170,7 @@ struct indirect_iterator_pair_generator Value, ConstReference,Category,ConstPointer>::type const_iterator; }; -#ifndef BOOST_MSVC +#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 template inline typename indirect_iterator_generator::type make_indirect_iterator(OuterIterator base) @@ -1392,7 +1392,7 @@ template ::value)); -#ifndef BOOST_MSVC // I don't have any idea why this occurs, but it doesn't seem to hurt too badly. +#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // I don't have any idea why this occurs, but it doesn't seem to hurt too badly. BOOST_STATIC_ASSERT(!is_bidirectional); #endif typedef filter_iterator_policies policies_type; From b22a3adc02e1e8efa905a1e35186762e3b3f1865 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sat, 3 Aug 2002 22:45:13 +0000 Subject: [PATCH 155/265] Add BOOST_NO_STD_ITERATOR_TRAITS workaround [SVN r14663] --- 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 f0ef010..b383bc3 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -382,7 +382,7 @@ namespace detail { }; -# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS) // Select default pointer and reference types for adapted non-pointer // iterators based on the iterator and the value_type. Poor man's partial From 34c159dd8d154a4b29126cba2d634943c895dd94 Mon Sep 17 00:00:00 2001 From: Gennadiy Rozental Date: Thu, 8 Aug 2002 16:42:18 +0000 Subject: [PATCH 156/265] Minor sunpro compartibility fix [SVN r14741] --- include/boost/iterator_adaptors.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index b383bc3..df91dcf 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -1150,7 +1150,7 @@ template ::iterator_category , class Pointer @@ -1160,7 +1160,7 @@ template struct indirect_iterator_pair_generator { From a586f20d19fb2311f31dd727494e3a791e03f754 Mon Sep 17 00:00:00 2001 From: Ronald Garcia Date: Thu, 5 Sep 2002 14:05:29 +0000 Subject: [PATCH 157/265] Added Shared Container Iterator adaptor to iterator adaptor library. [SVN r15169] --- include/boost/shared_container_iterator.hpp | 58 +++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 include/boost/shared_container_iterator.hpp diff --git a/include/boost/shared_container_iterator.hpp b/include/boost/shared_container_iterator.hpp new file mode 100644 index 0000000..cf8d736 --- /dev/null +++ b/include/boost/shared_container_iterator.hpp @@ -0,0 +1,58 @@ +// (C) Copyright Ronald Garcia 2002. 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 SHARED_CONTAINER_ITERATOR_RG08102002_HPP +#define SHARED_CONTAINER_ITERATOR_RG08102002_HPP + +#include "boost/iterator_adaptors.hpp" +#include "boost/shared_ptr.hpp" +#include + +namespace boost { + +template +struct shared_container_iterator_policies : + public boost::default_iterator_policies { + typedef boost::shared_ptr container_ref_t; + container_ref_t container_ref; + shared_container_iterator_policies(container_ref_t const& c) : + container_ref(c) { } + shared_container_iterator_policies() { } +}; + + +template +class shared_container_iterator_generator { + typedef typename Container::iterator iterator; + typedef shared_container_iterator_policies policy; +public: + typedef boost::iterator_adaptor type; +}; + +template +typename shared_container_iterator_generator::type +make_shared_container_iterator(typename Container::iterator iter, + boost::shared_ptr const& container) { + typedef typename shared_container_iterator_generator::type + iterator; + typedef shared_container_iterator_policies policy; + return iterator(iter,policy(container)); +} + +template +std::pair< + typename shared_container_iterator_generator::type, + typename shared_container_iterator_generator::type> +make_shared_container_range(boost::shared_ptr const& container) { + return + std::make_pair( + make_shared_container_iterator(container->begin(),container), + make_shared_container_iterator(container->end(),container)); +} + + +} // namespace boost +#endif // SHARED_CONTAINER_ITERATOR_RG08102002_HPP From 2c302ee549acb95affbffd08b321a6798627e834 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 9 Sep 2002 21:15:41 +0000 Subject: [PATCH 158/265] operator[] workaround from "Yitzhak Sapir" [SVN r15244] --- 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 df91dcf..26c0cda 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -761,6 +761,12 @@ namespace detail { BOOST_STATIC_ASSERT(forward_iter_with_real_reference); }; + + template struct dependent + { + typedef Result type; + }; + } // namespace detail @@ -880,7 +886,8 @@ struct iterator_adaptor : # pragma warning(pop) #endif - value_type operator[](difference_type n) const + template + typename detail::dependent::type operator[](diff_type n) const { return *(*this + n); } self& operator++() { From 77c1698c6edc67eb6b694928a144e38af93f0a77 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 11 Sep 2002 05:35:41 +0000 Subject: [PATCH 159/265] mpl_v2 branch checkin [SVN r15258] --- include/boost/iterator_adaptors.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 26c0cda..a16b7f0 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -124,6 +124,7 @@ # include # include # include +# include # include # include @@ -1353,9 +1354,9 @@ namespace detail { template struct reduce_to_base_class { - typedef typename if_true<( - ::boost::is_convertible::value - )>::template then::type type; + BOOST_STATIC_CONSTANT(bool, convertible = (::boost::is_convertible::value)); + typedef typename if_true::template then::type type; }; // "Steps down" the category of iterators below bidirectional so the category From 5bacd289b6c8185ba8421cd0c9b1c3ef75e8e602 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 11 Sep 2002 14:46:40 +0000 Subject: [PATCH 160/265] Roll back MPL v2 fix as it's no longer needed and was breaking Borland [SVN r15264] --- include/boost/iterator_adaptors.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index a16b7f0..18e7c9c 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -1354,9 +1354,9 @@ namespace detail { template struct reduce_to_base_class { - BOOST_STATIC_CONSTANT(bool, convertible = (::boost::is_convertible::value)); - typedef typename if_true::template then::type type; + typedef typename if_true<( + ::boost::is_convertible::value + )>::template then::type type; }; // "Steps down" the category of iterators below bidirectional so the category From ef0bff57d3838f748e160a972e8b4c8e51c08077 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 6 Dec 2002 19:09:22 +0000 Subject: [PATCH 161/265] Use BOOST_WORKAROUND [SVN r16528] --- include/boost/iterator_adaptors.hpp | 45 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 18e7c9c..e11db07 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -127,12 +127,9 @@ # 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) +# if BOOST_WORKAROUND(__GNUC__, == 2) && __GNUC_MINOR__ <= 96 && !defined(__STL_USE_NAMESPACES) # define BOOST_RELOPS_AMBIGUITY_BUG 1 # endif @@ -566,7 +563,7 @@ namespace detail { // An associative list is a list of key-value pairs. The list is // built out of cons_type's and is terminated by end_of_list. -# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(__BORLANDC__) +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || BOOST_WORKAROUND(__BORLANDC__, != 0) template struct find_param; @@ -629,7 +626,7 @@ namespace detail { enum { value = is_convertible< typename add_reference< Value >::type, add_reference< named_template_param_base >::type >::value }; }; -# if defined(__MWERKS__) && __MWERKS__ <= 0x2406 // workaround for broken is_convertible implementation +# if BOOST_WORKAROUND(__MWERKS__, <= 0x2407) // workaround for broken is_convertible implementation template struct is_named_parameter > { enum { value = true }; }; template struct is_named_parameter > { enum { value = true }; }; template struct is_named_parameter > { enum { value = true }; }; @@ -639,7 +636,7 @@ namespace detail { template struct make_arg { -# ifdef __BORLANDC__ +# if BOOST_WORKAROUND(__BORLANDC__, > 0) // Borland C++ doesn't like the extra indirection of is_named_parameter typedef typename if_true<(is_convertible::value)>:: @@ -773,7 +770,7 @@ namespace detail { // This macro definition is only temporary in this file -# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) # define BOOST_ARG_DEPENDENT_TYPENAME typename # else # define BOOST_ARG_DEPENDENT_TYPENAME @@ -862,7 +859,7 @@ struct iterator_adaptor : policies().initialize(base()); } -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__BORLANDC__) +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(__BORLANDC__, > 0) // This is required to prevent a bug in how VC++ generates // the assignment operator for compressed_pair iterator_adaptor& operator= (const iterator_adaptor& x) { @@ -874,7 +871,7 @@ struct iterator_adaptor : return policies().dereference(*this); } -#ifdef BOOST_MSVC +#if BOOST_WORKAROUND(BOOST_MSVC, > 0) # pragma warning(push) # pragma warning( disable : 4284 ) #endif @@ -883,7 +880,7 @@ struct iterator_adaptor : operator->() const { return detail::operator_arrow(*this, iterator_category()); } -#ifdef BOOST_MSVC +#if BOOST_WORKAROUND(BOOST_MSVC, > 0) # pragma warning(pop) #endif @@ -892,7 +889,7 @@ struct iterator_adaptor : { return *(*this + n); } self& operator++() { -#if !defined(__MWERKS__) || __MWERKS__ >= 0x2405 +#if !BOOST_WORKAROUND(__MWERKS__, < 0x2405) policies().increment(*this); #else // Odd bug, MWERKS couldn't deduce the type for the member template @@ -905,7 +902,7 @@ struct iterator_adaptor : self operator++(int) { self tmp(*this); ++*this; return tmp; } self& operator--() { -#if !defined(__MWERKS__) || __MWERKS__ >= 0x2405 +#if !BOOST_WORKAROUND(__MWERKS__, < 0x2405) policies().decrement(*this); #else policies().decrement(*this); @@ -1105,7 +1102,7 @@ struct indirect_iterator_policies : public default_iterator_policies }; namespace detail { -# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // strangely instantiated even when unused! Maybe try a recursive template someday ;-) +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // strangely instantiated even when unused! Maybe try a recursive template someday ;-) template struct traits_of_value_type { typedef typename boost::detail::iterator_traits::value_type outer_value; @@ -1118,12 +1115,12 @@ namespace detail { template 1300 +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::value_type #endif , class Reference -#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::reference #else @@ -1132,7 +1129,7 @@ template ::iterator_category , class Pointer -#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::pointer #else @@ -1147,12 +1144,12 @@ struct indirect_iterator_generator template 1300 +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::value_type #endif , class Reference -#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::reference #else @@ -1162,7 +1159,7 @@ template ::iterator_category , class Pointer -#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< OuterIterator>::pointer #else @@ -1178,7 +1175,7 @@ struct indirect_iterator_pair_generator Value, ConstReference,Category,ConstPointer>::type const_iterator; }; -#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) template inline typename indirect_iterator_generator::type make_indirect_iterator(OuterIterator base) @@ -1364,7 +1361,7 @@ namespace detail { template struct non_bidirectional_category { -# if !defined(__MWERKS__) || __MWERKS__ > 0x2406 +# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) typedef typename reduce_to_base_class< std::forward_iterator_tag, typename iterator_traits::iterator_category @@ -1400,7 +1397,7 @@ template ::value)); -#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // I don't have any idea why this occurs, but it doesn't seem to hurt too badly. +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // I don't have any idea why this occurs, but it doesn't seem to hurt too badly. BOOST_STATIC_ASSERT(!is_bidirectional); #endif typedef filter_iterator_policies policies_type; From 8dace06f0408208be43942f6338c4cacb0ec763d Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 27 Dec 2002 16:51:53 +0000 Subject: [PATCH 162/265] add or update See www.boost.org comments [SVN r16708] --- include/boost/counting_iterator.hpp | 2 +- include/boost/iterator.hpp | 2 +- include/boost/iterator_adaptors.hpp | 4 +++- include/boost/permutation_iterator.hpp | 2 ++ include/boost/shared_container_iterator.hpp | 1 + 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index ef3b07d..574e176 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/libs/utility/counting_iterator.htm for documentation. // // Supplies: // diff --git a/include/boost/iterator.hpp b/include/boost/iterator.hpp index 0e2ef72..8b82097 100644 --- a/include/boost/iterator.hpp +++ b/include/boost/iterator.hpp @@ -5,7 +5,7 @@ // 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. -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/utility for documentation. // Revision History // 12 Jan 01 added for std::ptrdiff_t (Jens Maurer) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index e11db07..9387f22 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -9,7 +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. -// + +// See http://www.boost.org/libs/utility/iterator_adaptors.htm for documentation. + // Revision History: // 01 Feb 2002 Jeremy Siek diff --git a/include/boost/permutation_iterator.hpp b/include/boost/permutation_iterator.hpp index 28ecfbb..8fdddb2 100644 --- a/include/boost/permutation_iterator.hpp +++ b/include/boost/permutation_iterator.hpp @@ -5,6 +5,8 @@ // to its suitability for any purpose. // +// See http://www.boost.org/libs/utility/permutation_iterator.htm for documentation. + #ifndef boost_permutation_iterator_hpp #define boost_permutation_iterator_hpp diff --git a/include/boost/shared_container_iterator.hpp b/include/boost/shared_container_iterator.hpp index cf8d736..95cf6c1 100644 --- a/include/boost/shared_container_iterator.hpp +++ b/include/boost/shared_container_iterator.hpp @@ -3,6 +3,7 @@ // 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. +// See http://www.boost.org/libs/utility/shared_container_iterator.html for documentation. #ifndef SHARED_CONTAINER_ITERATOR_RG08102002_HPP #define SHARED_CONTAINER_ITERATOR_RG08102002_HPP From 92d461cda16d25d694ae5b5a0768561fa21413cc Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 20 May 2003 23:20:49 +0000 Subject: [PATCH 163/265] Removed unused #include [SVN r18474] --- include/boost/iterator_adaptors.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 9387f22..2796152 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -123,7 +123,6 @@ # include # include # include -# include # include # include # include From e28ca345ea28eb18dc3d2d7a9791830623173a07 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 18 Jun 2003 13:20:02 +0000 Subject: [PATCH 164/265] added copyright/license [SVN r18836] --- include/boost/pending/iterator_adaptors.hpp | 6 ++++++ include/boost/pending/iterator_tests.hpp | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp index 548b9ba..4a3159b 100644 --- a/include/boost/pending/iterator_adaptors.hpp +++ b/include/boost/pending/iterator_adaptors.hpp @@ -1 +1,7 @@ +// Copyright David Abrahams 2003. 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. + #include diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp index 88e1c05..66e21aa 100644 --- a/include/boost/pending/iterator_tests.hpp +++ b/include/boost/pending/iterator_tests.hpp @@ -1,3 +1,8 @@ +// Copyright David Abrahams and Jeremy Siek 2003. 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_TESTS_HPP # define BOOST_ITERATOR_TESTS_HPP From 53eb5346de4fb644786374082526a6d083fdab8e Mon Sep 17 00:00:00 2001 From: Joel de Guzman Date: Mon, 7 Jul 2003 14:14:36 +0000 Subject: [PATCH 165/265] Move from boost-sanbox [ JDG ] [SVN r18958] --- include/boost/iterator/counting_iterator.hpp | 193 ++++++ include/boost/iterator/filter_iterator.hpp | 109 +++ include/boost/iterator/indirect_iterator.hpp | 220 ++++++ include/boost/iterator/interoperable.hpp | 52 ++ include/boost/iterator/iterator_adaptor.hpp | 325 +++++++++ .../boost/iterator/iterator_archetypes.hpp | 350 ++++++++++ .../boost/iterator/iterator_categories.hpp | 405 ++++++++++++ include/boost/iterator/iterator_concepts.hpp | 358 ++++++++++ include/boost/iterator/iterator_facade.hpp | 625 ++++++++++++++++++ include/boost/iterator/iterator_traits.hpp | 93 +++ include/boost/iterator/new_iterator_tests.hpp | 204 ++++++ .../boost/iterator/permutation_iterator.hpp | 92 +++ include/boost/iterator/reverse_iterator.hpp | 71 ++ include/boost/iterator/transform_iterator.hpp | 154 +++++ 14 files changed, 3251 insertions(+) create mode 100644 include/boost/iterator/counting_iterator.hpp create mode 100644 include/boost/iterator/filter_iterator.hpp create mode 100644 include/boost/iterator/indirect_iterator.hpp create mode 100644 include/boost/iterator/interoperable.hpp create mode 100644 include/boost/iterator/iterator_adaptor.hpp create mode 100644 include/boost/iterator/iterator_archetypes.hpp create mode 100644 include/boost/iterator/iterator_categories.hpp create mode 100644 include/boost/iterator/iterator_concepts.hpp create mode 100644 include/boost/iterator/iterator_facade.hpp create mode 100644 include/boost/iterator/iterator_traits.hpp create mode 100644 include/boost/iterator/new_iterator_tests.hpp create mode 100644 include/boost/iterator/permutation_iterator.hpp create mode 100644 include/boost/iterator/reverse_iterator.hpp create mode 100644 include/boost/iterator/transform_iterator.hpp diff --git a/include/boost/iterator/counting_iterator.hpp b/include/boost/iterator/counting_iterator.hpp new file mode 100644 index 0000000..d168e2d --- /dev/null +++ b/include/boost/iterator/counting_iterator.hpp @@ -0,0 +1,193 @@ +// Copyright David Abrahams 2003. 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 COUNTING_ITERATOR_DWA200348_HPP +# define COUNTING_ITERATOR_DWA200348_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { + +template class counting_iterator; + +namespace detail +{ + // Try to detect numeric types at compile time in ways compatible + // with the limitations of the compiler and library. + template + struct is_numeric_impl + { + // For a while, this wasn't true, but we rely on it below. This is a regression assert. + BOOST_STATIC_ASSERT(::boost::is_integral::value); + +# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + +# if defined(BOOST_HAS_LONG_LONG) + BOOST_STATIC_CONSTANT( + bool, value = ( + std::numeric_limits::is_specialized + | boost::is_same::value + | boost::is_same::value + )); +# else + BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_specialized); +# endif + +# else + +# if !defined(__BORLANDC__) + BOOST_STATIC_CONSTANT( + bool, value = ( + boost::is_convertible::value + && boost::is_convertible::value + )); +# else + BOOST_STATIC_CONSTANT(bool, value = ::boost::is_arithmetic::value); +# endif + +# endif + }; + + template + struct is_numeric + : mpl::bool_<(::boost::detail::is_numeric_impl::value)> + {}; + + template + struct numeric_difference + { + typedef typename boost::detail::numeric_traits::difference_type type; + }; + + BOOST_STATIC_ASSERT(is_numeric::value); + template + struct counting_iterator_base + { + typedef typename mpl::apply_if< + is_same + , mpl::apply_if< + is_numeric + , mpl::identity + , BOOST_ITERATOR_CATEGORY + > + , mpl::identity + >::type category; + + typedef typename mpl::apply_if< + is_same + , mpl::apply_if< + is_numeric + , numeric_difference + , iterator_difference + > + , mpl::identity + >::type difference; + + typedef iterator_adaptor< + counting_iterator // self + , Incrementable // Base + , Incrementable // value_type + , category + , Incrementable const& // reference + , difference + > type; + }; + + // Template class distance_policy_select -- choose a policy for computing the + // distance between counting_iterators at compile-time based on whether or not + // the iterator wraps an integer or an iterator, using "poor man's partial + // specialization". + + template struct distance_policy_select; + + // A policy for wrapped iterators + template + struct iterator_distance + { + static Difference distance(Incrementable1 x, Incrementable2 y) + { + return boost::detail::distance(x, y); + } + }; + + // A policy for wrapped numbers + template + struct number_distance + { + static Difference distance(Incrementable1 x, Incrementable2 y) + { + return numeric_distance(x, y); + } + }; +} + +template +class counting_iterator + : public detail::counting_iterator_base::type +{ + typedef typename detail::counting_iterator_base::type super_t; + friend class iterator_core_access; + + public: + typedef typename super_t::difference_type difference_type; + + counting_iterator() { } + + counting_iterator(counting_iterator const& rhs) : super_t(rhs.base()) {} + + counting_iterator(Incrementable x) + : super_t(x) + { + } + +# if 0 + template + counting_iterator( + counting_iterator const& t + , typename enable_if_convertible::type* = 0 + ) + : super_t(t.base()) + {} +# endif + + private: + + typename super_t::reference dereference() const + { + return this->base_reference(); + } + + template + difference_type + distance_to(counting_iterator const& y) const + { + typedef typename mpl::if_< + detail::is_numeric + , detail::number_distance + , detail::iterator_distance + >::type d; + + return d::distance(this->base(), y.base()); + } +}; + +// Manufacture a counting iterator for an arbitrary incrementable type +template +inline counting_iterator +make_counting_iterator(Incrementable x) +{ + typedef counting_iterator result_t; + return result_t(x); +} + + +} // namespace boost::iterator + +#endif // COUNTING_ITERATOR_DWA200348_HPP diff --git a/include/boost/iterator/filter_iterator.hpp b/include/boost/iterator/filter_iterator.hpp new file mode 100644 index 0000000..ae46fba --- /dev/null +++ b/include/boost/iterator/filter_iterator.hpp @@ -0,0 +1,109 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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_FILTER_ITERATOR_23022003THW_HPP +#define BOOST_FILTER_ITERATOR_23022003THW_HPP + +#include +#include +#include + +namespace boost +{ + namespace detail + { + template + struct filter_iterator_category + { + typedef iterator_tag< + typename access_category::type + , typename minimum_category< + bidirectional_traversal_tag + , typename traversal_category::type + >::type + > type; + }; + + } // namespace detail + + template + class filter_iterator + : public iterator_adaptor< + filter_iterator, Iterator + , use_default + , typename detail::filter_iterator_category::type + > + { + typedef iterator_adaptor< + filter_iterator, Iterator + , use_default + , typename detail::filter_iterator_category::type + > super_t; + + friend class iterator_core_access; + + public: + filter_iterator() { } + + filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()) + : super_t(x), m_predicate(f), m_end(end) + { + satisfy_predicate(); + } + + filter_iterator(Iterator x, Iterator end = Iterator()) + : super_t(x), m_predicate(), m_end(end) + { + satisfy_predicate(); + } + + template + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::type* = 0 + ) + : super_t(t.base()), m_predicate(t.predicate()), m_end(t.end()) {} + + Predicate predicate() const { return m_predicate; } + + Iterator end() const { return m_end; } + + private: + void increment() + { + ++(this->base_reference()); + satisfy_predicate(); + } + + void decrement() + { + while(!this->m_predicate(*--(this->base_reference()))){}; + } + + void satisfy_predicate() + { + while (this->base() != this->m_end && !this->m_predicate(*this->base())) + ++(this->base_reference()); + } + + // Probably should be the initial base class so it can be + // optimized away via EBO if it is an empty class. + Predicate m_predicate; + Iterator m_end; + }; + + template + filter_iterator + make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()) + { + return filter_iterator(f,x,end); + } + +} // namespace boost + +#endif // BOOST_FILTER_ITERATOR_23022003THW_HPP diff --git a/include/boost/iterator/indirect_iterator.hpp b/include/boost/iterator/indirect_iterator.hpp new file mode 100644 index 0000000..f6caa71 --- /dev/null +++ b/include/boost/iterator/indirect_iterator.hpp @@ -0,0 +1,220 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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_INDIRECT_ITERATOR_23022003THW_HPP +#define BOOST_INDIRECT_ITERATOR_23022003THW_HPP + +#include +#include + +#include + +#include +#include +#include + +#ifdef BOOST_NO_MPL_AUX_HAS_XXX +# include +# include +# include +# include +#endif + +#include // must be last #include + +namespace boost +{ + template + struct indirect_iterator; + + namespace detail + { + struct unspecified {}; + + // + // Detection for whether a type has a nested `element_type' + // typedef. Used to detect smart pointers. For compilers not + // supporting mpl's has_xxx, we supply specializations. However, we + // really ought to have a specializable is_pointer template which + // can be used instead with something like + // boost/python/pointee.hpp to find the value_type. + // +# ifndef BOOST_NO_MPL_AUX_HAS_XXX + namespace aux + { + BOOST_MPL_HAS_XXX_TRAIT_DEF(element_type) + } + + template + struct has_element_type + : mpl::bool_< + mpl::if_< + is_class + , ::boost::detail::aux::has_element_type + , mpl::false_ + >::type::value + > + { + }; +# else + template + struct has_element_type + : mpl::false_ {}; + + template + struct has_element_type > + : mpl::true_ {}; + + template + struct has_element_type > + : mpl::true_ {}; + + template + struct has_element_type > + : mpl::true_ {}; +# endif + + // Metafunction returning the nested element_type typedef + template + struct smart_pointer_value : remove_const + {}; + + template + struct iterator_is_mutable + : mpl::not_< + boost::python::detail::is_reference_to_const< + typename iterator_reference::type + > + > + { + }; + + template + struct not_int_impl + { + template + struct apply { + typedef T type; + }; + }; + + template <> + struct not_int_impl {}; + + template + struct not_int + : not_int_impl::template apply {}; + + // If the Value parameter is unspecified, we use this metafunction + // to deduce the default types + template + struct indirect_base + { + typedef typename iterator_value::type dereferenceable; + + typedef mpl::and_< + is_class + , has_element_type + > is_smart_ptr; + + typedef typename mpl::apply_if< + is_smart_ptr + , smart_pointer_value + , iterator_value + >::type value_type; + + typedef typename mpl::if_< + mpl::or_< + is_smart_ptr + , iterator_is_mutable + > + , value_type + , value_type const + >::type cv_value_type; + + typedef iterator_adaptor< + indirect_iterator + , Iter + , cv_value_type + , Category + , Reference + , Difference + > type; + }; + + template <> + struct indirect_base {}; + } // namespace detail + + template < + class Iterator + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class indirect_iterator + : public detail::indirect_base< + Iterator, Value, Category, Reference, Difference + >::type + { + typedef typename detail::indirect_base< + Iterator, Value, Category, Reference, Difference + >::type super_t; + + friend class iterator_core_access; + + public: + indirect_iterator() {} + + indirect_iterator(Iterator iter) + : super_t(iter) {} + + template < + class Iterator2, class Value2, class Category2 + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Category2, Reference2, Difference2 + > const& y + , typename enable_if_convertible::type* = 0 + ) + : super_t(y.base()) + {} + + private: + typename super_t::reference dereference() const + { +# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + return const_cast(**this->base()); +# else + return **this->base(); +# endif + } + }; + + template + inline + indirect_iterator make_indirect_iterator(Iter x) + { + return indirect_iterator(x); + } + + template + inline + indirect_iterator make_indirect_iterator(Iter x, Traits* = 0) + { + return indirect_iterator(x); + } + +} // namespace boost + +#include + +#endif // BOOST_INDIRECT_ITERATOR_23022003THW_HPP diff --git a/include/boost/iterator/interoperable.hpp b/include/boost/iterator/interoperable.hpp new file mode 100644 index 0000000..b326250 --- /dev/null +++ b/include/boost/iterator/interoperable.hpp @@ -0,0 +1,52 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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_INTEROPERABLE_23022003THW_HPP +# define BOOST_INTEROPERABLE_23022003THW_HPP + +# include +# include + +# include + +# include // must appear last + +namespace boost +{ + + // + // Meta function that determines whether two + // iterator types are considered interoperable. + // + // Two iterator types A,B are considered interoperable if either + // A is convertible to B or vice versa. + // This interoperability definition is in sync with the + // standards requirements on constant/mutable container + // iterators (23.1 [lib.container.requirements]). + // + // For compilers that don't support is_convertible + // is_interoperable gives false positives. See comments + // on operator implementation for consequences. + // + template + struct is_interoperable +# ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY + : mpl::true_ +# else + : mpl::or_< + is_convertible< A, B > + , is_convertible< B, A > > +# endif + { + }; + +} // namespace boost + +# include + +#endif // BOOST_INTEROPERABLE_23022003THW_HPP diff --git a/include/boost/iterator/iterator_adaptor.hpp b/include/boost/iterator/iterator_adaptor.hpp new file mode 100644 index 0000000..c29dbd9 --- /dev/null +++ b/include/boost/iterator/iterator_adaptor.hpp @@ -0,0 +1,325 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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_23022003THW_HPP +#define BOOST_ITERATOR_ADAPTOR_23022003THW_HPP + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include + +#include + +namespace boost +{ + namespace detail + { + + // + // Result type used in enable_if_convertible meta function. + // This can be an incomplete type, as only pointers to + // enable_if_convertible< ... >::type are used. + // We could have used void for this, but conversion to + // void* is just to easy. + // + struct enable_type; + } + + + // + // enable_if for use in adapted iterators constructors. + // + // In order to provide interoperability between adapted constant and + // mutable iterators, adapted iterators will usually provide templated + // conversion constructors of the following form + // + // template + // class adapted_iterator : + // public iterator_adaptor< adapted_iterator, Iterator > + // { + // public: + // + // ... + // + // template + // adapted_iterator( + // OtherIterator const& it + // , typename enable_if_convertible::type* = 0); + // + // ... + // }; + // + // enable_if_convertible is used to remove those overloads from the overload + // set that cannot be instantiated. For all practical purposes only overloads + // for constant/mutable interaction will remain. This has the advantage that + // meta functions like boost::is_convertible do not return false positives, + // as they can only look at the signature of the conversion constructor + // and not at the actual instantiation. + // + // enable_if_interoperable can be safely used in user code. It falls back to + // always enabled for compilers that don't support enable_if or is_convertible. + // There is no need for compiler specific workarounds in user code. + // + // The operators implementation relies on boost::is_convertible not returning + // false positives for user/library defined iterator types. See comments + // on operator implementation for consequences. + // +# if defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_SFINAE) + + template + struct enable_if_convertible + { + typedef detail::enable_type type; + }; + +# elif BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) && BOOST_MSVC > 1300 + + // For some reason vc7.1 needs us to "cut off" instantiation + // of is_convertible in a few cases. + template + struct enable_if_convertible + : detail::enable_if< + mpl::or_< + is_same + , is_convertible + > + , detail::enable_type + > + {}; + +# else + + template + struct enable_if_convertible + : detail::enable_if< + is_convertible + , detail::enable_type + > + {}; + +# endif + + // + // Default template argument handling for iterator_adaptor + // + namespace detail + { + // If T is use_default, return the result of invoking + // DefaultNullaryFn, otherwise return T. + template + struct ia_dflt_help + : mpl::apply_if< + is_same + , DefaultNullaryFn + , mpl::identity + > + { + }; + + // A metafunction which computes an iterator_adaptor's base class, + // a specialization of iterator_facade. + template < + class Derived + , class Base + , class Value + , class Category + , class Reference + , class Difference + > + struct iterator_adaptor_base + { + private: // intermediate results + typedef typename detail::ia_dflt_help< + Category, BOOST_ITERATOR_CATEGORY + >::type category; + + typedef typename detail::ia_dflt_help< + Reference + , mpl::apply_if< + is_same + , iterator_reference + , mpl::identity + > + >::type reference; + + public: // return type + typedef iterator_facade< + Derived + + , typename detail::ia_dflt_help< + Value, iterator_value + >::type + + , typename access_category_tag::type + + , typename traversal_category_tag::type + + , reference + + , typename detail::ia_dflt_help< + Difference, iterator_difference + >::type + > + type; + }; + } + + // + // Iterator Adaptor + // + // The parameter ordering changed slightly with respect to former + // versions of iterator_adaptor The idea is that when the user needs + // to fiddle with the reference type it is highly likely that the + // iterator category has to be adjusted as well. Any of the + // following four template arguments may be ommitted or explicitly + // replaced by use_default. + // + // Value - if supplied, the value_type of the resulting iterator, unless + // const. If const, a conforming compiler strips constness for the + // value_type. If not supplied, iterator_traits::value_type is used + // + // Category - the iterator_category of the resulting iterator. If not + // supplied, iterator_traits::iterator_category is used. + // + // Reference - the reference type of the resulting iterator, and in + // particular, the result type of operator*(). If not supplied but + // Value is supplied, Value& is used. Otherwise + // iterator_traits::reference is used. + // + // Difference - the difference_type of the resulting iterator. If not + // supplied, iterator_traits::difference_type is used. + // + template < + class Derived + , class Base + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class iterator_adaptor + : public detail::iterator_adaptor_base< + Derived, Base, Value, Category, Reference, Difference + >::type + { + friend class iterator_core_access; + + typedef typename detail::iterator_adaptor_base< + Derived, Base, Value, Category, Reference, Difference + >::type super_t; + + public: + iterator_adaptor() {} + + explicit iterator_adaptor(Base iter) + : m_iterator(iter) + { + } + + Base base() const + { return m_iterator; } + + protected: + // + // lvalue access to the Base object for Derived + // + Base const& base_reference() const + { return m_iterator; } + + Base& base_reference() + { return m_iterator; } + + private: + // + // Core iterator interface for iterator_facade. This is private + // to prevent temptation for Derived classes to use it, which + // will often result in an error. Derived classes should use + // base_reference(), above, to get direct access to m_iterator. + // + typename super_t::reference dereference() const + { return *m_iterator; } + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + bool equal(iterator_adaptor const& x) const + { + // Maybe readd with same_distance + // BOOST_STATIC_ASSERT( + // (detail::same_category_and_difference::value) + // ); + return m_iterator == x.base(); + } + + void advance(typename super_t::difference_type n) + { + BOOST_STATIC_ASSERT( + (detail::is_tag< + random_access_traversal_tag + , BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal + >::value) + ); + m_iterator += n; + } + + void increment() { ++m_iterator; } + + void decrement() + { + BOOST_STATIC_ASSERT( + (detail::is_tag< + bidirectional_traversal_tag + , BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal + >::value) + ); + --m_iterator; + } + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + typename super_t::difference_type distance_to( + iterator_adaptor const& y) const + { + BOOST_STATIC_ASSERT( + (detail::is_tag< + random_access_traversal_tag + , BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal + >::value) + ); + // Maybe readd with same_distance + // BOOST_STATIC_ASSERT( + // (detail::same_category_and_difference::value) + // ); + return y.base() - m_iterator; + } + + private: // data members + Base m_iterator; + }; + +} // namespace boost + +#include + +#endif // BOOST_ITERATOR_ADAPTOR_23022003THW_HPP diff --git a/include/boost/iterator/iterator_archetypes.hpp b/include/boost/iterator/iterator_archetypes.hpp new file mode 100644 index 0000000..e9439e7 --- /dev/null +++ b/include/boost/iterator/iterator_archetypes.hpp @@ -0,0 +1,350 @@ +// (C) Copyright Jeremy Siek 2002. 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_ARCHETYPES_HPP +#define BOOST_ITERATOR_ARCHETYPES_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace boost +{ + + template + struct access_archetype; + + template + struct traversal_archetype; + + namespace detail { + + template + struct assign_proxy + { + assign_proxy& operator=(T); + }; + + template + struct read_write_proxy : + assign_proxy + { + operator T(); + }; + + template + struct arrow_proxy + { + T const* operator->() const; + }; + + struct no_operator_brackets {}; + + template + struct readable_operator_brackets + { + ValueType operator[](std::ptrdiff_t n) const; + }; + + template + struct writable_operator_brackets + { + read_write_proxy operator[](std::ptrdiff_t n) const; + }; + + template + struct operator_brackets : + mpl::if_< is_tag, + mpl::if_< is_tag, + writable_operator_brackets< Value >, + mpl::if_< is_tag, + readable_operator_brackets, + no_operator_brackets > >, + no_operator_brackets >::type + { + }; + + template + struct traversal_archetype_impl + { + template struct archetype; + }; + + template + struct traversal_archetype_ + : mpl::aux::msvc_eti_base< + typename traversal_archetype_impl::template archetype + >::type + {}; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + { + typedef void difference_type; + + Derived& operator++(); + Derived operator++(int) const; + }; + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public equality_comparable< traversal_archetype_ >, + public traversal_archetype_ + { + }; + }; + + template + bool operator==(traversal_archetype_ const&, + traversal_archetype_ const&); + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + // doesn't seem to pick up != from equality_comparable + template + bool operator!=(traversal_archetype_ const&, + traversal_archetype_ const&); +#endif + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + typedef std::ptrdiff_t difference_type; + }; + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + Derived& operator--(); + Derived operator--(int) const; + }; + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public partially_ordered >, + public traversal_archetype_ + { + Derived& operator+=(std::ptrdiff_t); + Derived& operator-=(std::ptrdiff_t); + }; + }; + + template + Derived& operator+(traversal_archetype_ const&, + std::ptrdiff_t); + + template + Derived& operator+(std::ptrdiff_t, + traversal_archetype_ const&); + + template + Derived& operator-(traversal_archetype_ const&, + std::ptrdiff_t); + + template + std::ptrdiff_t operator-(traversal_archetype_ const&, + traversal_archetype_ const&); + + template + bool operator<(traversal_archetype_ const&, + traversal_archetype_ const&); + + struct bogus_type; + + template + struct convertible_type + : mpl::if_< is_const, + typename remove_const::type, + bogus_type > + {}; + + } // namespace detail + + + template struct undefined; + + template + struct access_archetype_impl + { + template struct archetype; + }; + + template + struct access_archetype + : mpl::aux::msvc_eti_base< + typename access_archetype_impl::template archetype + >::type + { + }; + + template <> + struct access_archetype_impl + { + template + struct archetype + { + typedef typename remove_cv::type value_type; + typedef Value reference; + typedef Value* pointer; + + value_type operator*() const; + + detail::arrow_proxy operator->() const; + }; + }; + + template <> + struct access_archetype_impl + { + template + struct archetype + { +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + BOOST_STATIC_ASSERT(!is_const::value); +# endif + typedef void value_type; + typedef void reference; + typedef void pointer; + + detail::assign_proxy operator*() const; + }; + }; + + template <> + struct access_archetype_impl + { + template + struct archetype + : public virtual access_archetype + { + typedef detail::read_write_proxy reference; + + detail::read_write_proxy operator*() const; + }; + }; + + template <> + struct access_archetype_impl + { + template + struct archetype + : public virtual access_archetype + { + typedef Value& reference; + + Value& operator*() const; + Value* operator->() const; + }; + }; + + template <> + struct access_archetype_impl + { + template + struct archetype + : public virtual access_archetype + { +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + BOOST_STATIC_ASSERT((!is_const::value)); +# endif + }; + }; + + + template + struct iterator_archetype; + + template + struct traversal_archetype_base + : detail::operator_brackets< + typename remove_cv::type + , AccessCategory + , TraversalCategory + > + , detail::traversal_archetype_< + iterator_archetype + , Value + , TraversalCategory + > + { + }; + + template + struct iterator_archetype + : public traversal_archetype_base + , public access_archetype + + // These broken libraries require derivation from std::iterator + // (or related magic) in order to handle iter_swap and other + // iterator operations +# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ + || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) + , public std::iterator< + iterator_tag + , typename access_archetype::value_type + , typename traversal_archetype_base< + Value, AccessCategory, TraversalCategory + >::difference_type + > +# endif + { + // Derivation from std::iterator above caused ambiguity, so now + // we have to declare all the types here. +# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ + || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) + typedef typename access_archetype::value_type value_type; + + typedef typename access_archetype::pointer pointer; + + typedef typename access_archetype::reference reference; + + typedef typename traversal_archetype_base< + Value, AccessCategory, TraversalCategory + >::difference_type difference_type; +# endif + + typedef iterator_tag iterator_category; + + iterator_archetype(); + iterator_archetype(iterator_archetype const&); + + iterator_archetype& operator=(iterator_archetype const&); + + // Optional conversion from mutable + // iterator_archetype(iterator_archetype::type, AccessCategory, TraversalCategory> const&); + }; + +} // namespace boost + + +#endif // BOOST_ITERATOR_ARCHETYPES_HPP diff --git a/include/boost/iterator/iterator_categories.hpp b/include/boost/iterator/iterator_categories.hpp new file mode 100644 index 0000000..23724b1 --- /dev/null +++ b/include/boost/iterator/iterator_categories.hpp @@ -0,0 +1,405 @@ +// (C) Copyright Jeremy Siek 2002. 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. + +// TODO: +// Add separate category tag for operator[]. + +#ifndef BOOST_ITERATOR_CATEGORIES_HPP +#define BOOST_ITERATOR_CATEGORIES_HPP + +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include // must be last #include + +#if BOOST_WORKAROUND(__MWERKS__, <=0x2407) +# define BOOST_NO_IS_CONVERTIBLE // "Convertible does not provide enough/is not working" +#endif + +namespace boost { + + namespace detail + { + // Helper metafunction for std_category below + template + struct match_tag + : mpl::apply_if, mpl::identity, Next> + { + }; + + // Converts a possibly user-defined category tag to the + // most-derived standard tag which is a base of that tag. + template + struct std_category + : match_tag< + Category, std::random_access_iterator_tag + , match_tag +# else + , void +# endif + > + > + > + > + > + { + }; + + // std_to_new_tags -- + // + // A metafunction which converts any standard tag into its + // corresponding new-style traversal tag. + // + // Also, instantiations are metafunction classes which convert a + // reference type into a corresponding new-style access tag. + template struct std_to_new_tags +# if BOOST_WORKAROUND(BOOST_MSVC, == 1300) // handle ETI + { + typedef void type; + template struct apply { typedef void type; }; + } +# endif + ; + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // handle ETI + template <> struct std_to_new_tags {}; +# endif + + // + // Specializations for specific standard tags + // + template <> + struct std_to_new_tags + { + typedef single_pass_traversal_tag type; + + template + struct apply + : mpl::identity {}; + + }; + + template <> + struct std_to_new_tags + { + typedef incrementable_traversal_tag type; + + template + struct apply + : mpl::identity {}; + }; + + template <> + struct std_to_new_tags + { + typedef forward_traversal_tag type; + + template + struct apply + : mpl::if_< + python::detail::is_reference_to_const + , boost::readable_lvalue_iterator_tag + , boost::writable_lvalue_iterator_tag + > + {}; + }; + + template <> + struct std_to_new_tags + : std_to_new_tags + { + typedef bidirectional_traversal_tag type; + }; + + template <> + struct std_to_new_tags + : std_to_new_tags + { + typedef random_access_traversal_tag type; + }; + + template + struct old_tag_converter + : std_to_new_tags< + typename std_category::type + > + { + }; + + template + struct iter_category_to_traversal + : std_to_new_tags< + typename std_category::type + > + {}; + + template + struct iter_category_to_access + : mpl::apply1< + iter_category_to_traversal + , Reference + > + {}; + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + // Deal with ETI + template <> struct iter_category_to_access {}; + template <> struct iter_category_to_traversal {}; +# endif + + // A metafunction returning true iff T is boost::iterator_tag + template + struct is_boost_iterator_tag; + +#if BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + // + // has_xxx fails, so we have to use + // something less sophisticated. + // + // The solution depends on the fact that only + // std iterator categories work with is_xxx_iterator + // meta functions, as BOOST_NO_IS_CONVERTIBLE is + // defined for cwpro7. + // + template + struct is_new_iterator_tag + : mpl::not_< + mpl::or_< + is_tag + , is_tag + > + > + {}; + +#elif BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + + template + struct is_new_iterator_tag + : is_boost_iterator_tag + { + }; + +#else + + BOOST_MPL_HAS_XXX_TRAIT_DEF(traversal) + + template + struct is_new_iterator_tag + : mpl::if_< + is_class + , has_traversal + , mpl::false_ + >::type + { + }; + +#endif + + } // namespace detail + + namespace detail { + + template + struct get_traversal_category { + typedef typename NewCategoryTag::traversal type; + }; + + // Remove all writability from the given access tag. This + // functionality is part of new_category_to_access in order to + // support deduction of the proper default access category for + // iterator_adaptor; when the reference type is a reference to + // constant we must strip writability. + template + struct remove_access_writability + : mpl::apply_if< + is_tag + , mpl::identity + + , mpl::apply_if< + is_tag + , mpl::identity + + , mpl::if_< + is_tag + // Is this OK? I think it may correct be for all + // legitimate cases, because at this point the + // iterator is not readable, so it could not have + // been any more than writable + swappable. + , swappable_iterator_tag + , AccessTag + > + > + > + {}; + + template + struct new_category_to_access + : mpl::apply_if< + python::detail::is_reference_to_const + , remove_access_writability + , mpl::identity + > + {}; + + template + struct access_category_tag + : mpl::apply_if< + is_new_iterator_tag + , new_category_to_access + , iter_category_to_access + > + { + }; + + template + struct traversal_category_tag + : mpl::apply_if< + is_new_iterator_tag + , get_traversal_category + , iter_category_to_traversal + > + { + }; + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + // Deal with ETI + template <> struct access_category_tag { typedef void type; }; + template <> struct traversal_category_tag { typedef void type; }; +# endif + + // iterator_tag_base - a metafunction to compute the appropriate + // old-style tag (if any) to use as a base for a new-style tag. + template + struct iterator_tag_base + : minimum_category< + typename KnownAccessTag::max_category + , typename KnownTraversalTag::max_category + > + {}; + +# if BOOST_WORKAROUND(BOOST_MSVC,<=1200) + template <> + struct iterator_tag_base + : mpl::false_ {}; // just using false_ so that the result will be + // a legal base class +# endif + + // specialization for this special case. Otherwise we get + // input_output_iterator_tag, because the standard hierarchy has a + // sudden anomalous distinction between readability and + // writability at the level of input iterator/output iterator. + template <> + struct iterator_tag_base< + readable_lvalue_iterator_tag,single_pass_traversal_tag> + { + typedef std::input_iterator_tag type; + }; + + } // namespace detail + + template + struct access_category + : detail::access_category_tag< + typename detail::iterator_traits::iterator_category + , typename detail::iterator_traits::reference> + {}; + + template + struct traversal_category + : detail::traversal_category_tag< + typename detail::iterator_traits::iterator_category + > + { + }; + +# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + template + struct access_category + : mpl::if_< + is_const + , readable_lvalue_iterator_tag + , writable_lvalue_iterator_tag> + { + }; + + template + struct traversal_category + { + typedef random_access_traversal_tag type; + }; + +# endif + + template + struct iterator_tag + : detail::iterator_tag_base< + typename detail::max_known_access_tag::type + , typename detail::max_known_traversal_tag::type + >::type + { + typedef AccessTag access; + typedef TraversalTag traversal; + }; + + namespace detail + { +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct is_boost_iterator_tag + : mpl::false_ {}; + + template + struct is_boost_iterator_tag > + : mpl::true_ {}; +# else + template + struct is_boost_iterator_tag + { + typedef char (&yes)[1]; + typedef char (&no)[2]; + + template + static yes test(mpl::identity >*); + static no test(...); + + static mpl::identity* inst; + BOOST_STATIC_CONSTANT(bool, value = sizeof(test(inst)) == sizeof(yes)); + typedef mpl::bool_ type; + }; +# endif + } + +} // namespace boost + +#include + +#endif // BOOST_ITERATOR_CATEGORIES_HPP diff --git a/include/boost/iterator/iterator_concepts.hpp b/include/boost/iterator/iterator_concepts.hpp new file mode 100644 index 0000000..fe5b433 --- /dev/null +++ b/include/boost/iterator/iterator_concepts.hpp @@ -0,0 +1,358 @@ +// (C) Copyright Jeremy Siek 2002. 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_CONCEPTS_HPP +#define BOOST_ITERATOR_CONCEPTS_HPP + +// Revision History +// 26 Apr 2003 thw +// Adapted to new iterator concepts +// 22 Nov 2002 Thomas Witt +// Added interoperable concept. + +#include +#include +#include +#include +#include +#include +#include +#include + +// Use boost::detail::iterator_traits to work around some MSVC/Dinkumware problems. +#include + +// Use boost/limits to work around missing limits headers on some compilers +#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. + + // We use this in place of STATIC_ASSERT((is_convertible<...>)) + // because some compilers (CWPro7.x) can't detect convertibility. + // + // Of course, that just gets us a different error at the moment with + // some tests, since new iterator category deduction still depends + // on convertibility detection. We might need some specializations + // to support this compiler. + template + struct static_assert_base_and_derived + { + static_assert_base_and_derived(Target* = (Source*)0) {} + }; + + //=========================================================================== + // Iterator Access Concepts + + template + class ReadableIteratorConcept { + public: + typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits::reference reference; + typedef BOOST_DEDUCED_TYPENAME ::boost::access_category::type access_category; + + void constraints() { + boost::function_requires< boost::SGIAssignableConcept >(); + boost::function_requires< boost::EqualityComparableConcept >(); + boost::function_requires< + boost::DefaultConstructibleConcept >(); + + BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + + 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::access_category::type access_category; + + void constraints() { + boost::function_requires< boost::SGIAssignableConcept >(); + boost::function_requires< boost::EqualityComparableConcept >(); + boost::function_requires< + boost::DefaultConstructibleConcept >(); + + BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + + *i = v; // a good alternative could be something like write(x, v) + } + ValueType v; + Iterator i; + }; + + template + class SwappableIteratorConcept { + public: + typedef typename boost::access_category::type access_category; + + void constraints() { + BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + + std::iter_swap(i1, i2); + } + Iterator i1; + Iterator i2; + }; + + template + class ReadableLvalueIteratorConcept { + public: + typedef typename boost::detail::iterator_traits::value_type value_type; + typedef typename boost::detail::iterator_traits::reference reference; + typedef typename boost::access_category::type access_category; + + void constraints() { + boost::function_requires< ReadableIteratorConcept >(); + + BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + + typedef boost::mpl::or_< + boost::is_same, + boost::is_same > correct_reference; + + BOOST_STATIC_ASSERT(correct_reference::value); + + reference v = *i; + boost::ignore_unused_variable_warning(v); + } + Iterator i; + }; + + template + class WritableLvalueIteratorConcept { + public: + typedef typename boost::detail::iterator_traits::value_type value_type; + typedef typename boost::detail::iterator_traits::reference reference; + typedef typename boost::access_category::type access_category; + + void constraints() { + boost::function_requires< + ReadableLvalueIteratorConcept >(); + boost::function_requires< + WritableIteratorConcept >(); + boost::function_requires< + SwappableIteratorConcept >(); + + BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + }; + + //=========================================================================== + // Iterator Traversal Concepts + + template + class IncrementableIteratorConcept { + public: + typedef typename boost::traversal_category::type traversal_category; + + void constraints() { + boost::function_requires< boost::SGIAssignableConcept >(); + boost::function_requires< + boost::DefaultConstructibleConcept >(); + + BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + + ++i; + (void)i++; + } + Iterator i; + }; + + template + class SinglePassIteratorConcept { + public: + typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::detail::iterator_traits::difference_type difference_type; + + void constraints() { + boost::function_requires< IncrementableIteratorConcept >(); + boost::function_requires< boost::EqualityComparableConcept >(); + + BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + } + }; + + template + class ForwardTraversalConcept { + public: + typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::detail::iterator_traits::difference_type difference_type; + + void constraints() { + boost::function_requires< SinglePassIteratorConcept >(); + + typedef boost::mpl::and_< + boost::is_integral, + boost::mpl::bool_< std::numeric_limits::is_signed > + > difference_type_is_signed_integral; + + BOOST_STATIC_ASSERT(difference_type_is_signed_integral::value); + BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + } + }; + + template + class BidirectionalTraversalConcept { + public: + typedef typename boost::traversal_category::type traversal_category; + + void constraints() { + boost::function_requires< ForwardTraversalConcept >(); + + BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + + --i; + (void)i--; + } + Iterator i; + }; + + template + class RandomAccessTraversalConcept { + public: + typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::detail::iterator_traits::difference_type + difference_type; + + void constraints() { + boost::function_requires< BidirectionalTraversalConcept >(); + + BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + + i += n; + i = i + n; + i = n + i; + i -= n; + i = i - n; + n = i - j; + } + difference_type n; + Iterator i, j; + }; + + //=========================================================================== + // Iterator Interoperability Concept + +namespace detail +{ + + template + struct Operations; + + template <> + struct Operations + { + template + static void constraints(Iterator1 const& i1, Iterator2 const& i2) + { + // no interoperability constraints + } + }; + + template <> + struct Operations + { + template + static void constraints(Iterator1 const& i1, Iterator2 const& i2) + { + Operations(i1, i2); + i1 == i2; + i1 != i2; + + i2 == i1; + i2 != i1; + } + }; + + template <> + struct Operations + { + template + static void constraints(Iterator1 const& i1, Iterator2 const& i2) + { + Operations::constraints(i1, i2); + } + }; + + template <> + struct Operations + { + template + static void constraints(Iterator1 const& i1, Iterator2 const& i2) + { + Operations::constraints(i1, i2); + } + }; + + template <> + struct Operations + { + template + static void constraints(Iterator1 const& i1, Iterator2 const& i2) + { + Operations::constraints(i1, i2); + + i1 < i2; + i1 <= i2; + i1 > i2; + i1 >= i2; + i1 - i2; + + i2 < i1; + i2 <= i1; + i2 > i1; + i2 >= i1; + i2 - i1; + } + }; + + } // namespace detail + + template + class InteroperableConcept + { + public: + typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::detail::iterator_traits::difference_type + difference_type; + + typedef typename boost::traversal_category::type + const_traversal_category; + typedef typename boost::detail::iterator_traits::difference_type + const_difference_type; + + void constraints() { + BOOST_STATIC_ASSERT((boost::is_same< difference_type, + const_difference_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same< traversal_category, + const_traversal_category>::value)); + + // ToDo check what the std really requires + + // detail::Operations::constraints(i, ci); + + ci = i; + + } + Iterator i; + ConstIterator ci; + }; + +} // namespace boost_concepts + + +#endif // BOOST_ITERATOR_CONCEPTS_HPP diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp new file mode 100644 index 0000000..1abe0e0 --- /dev/null +++ b/include/boost/iterator/iterator_facade.hpp @@ -0,0 +1,625 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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_FACADE_23022003THW_HPP +#define BOOST_ITERATOR_FACADE_23022003THW_HPP + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include // this goes last + +namespace boost +{ + + struct use_default; + + namespace detail + { + + // + // enable if for use in operator implementation. + // + // enable_if_interoperable falls back to always enabled for compilers + // that don't support enable_if or is_convertible. + // + template < + class Facade1 + , class Facade2 + , class Return + > + struct enable_if_interoperable +#ifndef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY + : ::boost::detail::enable_if< + mpl::or_< + is_convertible + , is_convertible + > + , Return + > +#endif + { +#ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY + typedef Return type; +#endif + }; + + + // + // Add const qualification for iterators which are not writable + // + template + struct const_qualified_ref : + mpl::if_< is_tag< writable_iterator_tag, AccessCategory >, + Value&, + Value const& > + {}; + + // The apparent duplication here works around a Borland problem + template + struct const_qualified_ptr : + mpl::if_< is_tag< writable_iterator_tag, AccessCategory >, + Value*, + Value const* > + {}; + + // + // Generates the associated types for an iterator_facade with the + // given parameters. Additionally generates a 'base' type for + // compiler/library combinations which require user-defined + // iterators to inherit from std::iterator. + // + template < + class Value + , class AccessCategory + , class TraversalCategory + , class Reference + , class Difference + > + struct iterator_facade_types + { + typedef iterator_tag iterator_category; + + typedef typename remove_cv::type value_type; + + typedef Difference difference_type; + + typedef typename const_qualified_ptr::type pointer; + + // The use_default support is needed for iterator_adaptor. + // For practical reasons iterator_adaptor needs to specify + // a fixed number of template arguments of iterator_facade. + // So use_default is its way to say: "What I really mean + // is your default parameter". + typedef typename mpl::if_< + is_same + , typename const_qualified_ref::type + , Reference + >::type reference; + +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \ + || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \ + || BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101)) \ + || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 310) + + // To interoperate with some broken library/compiler + // combinations, user-defined iterators must be derived from + // std::iterator. It is possible to implement a standard + // library for broken compilers without this limitation. +# define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1 + + typedef + iterator + base; +# endif + }; + + + // 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(T const* px) : m_value(*px) {} + const T* operator->() const { return &m_value; } + // This function is needed for MWCW and BCC, which won't call operator-> + // again automatically per 13.3.1.2 para 8 + operator const T*() const { return &m_value; } + T m_value; + }; + + // A metafunction that gets the result type for operator->. Also + // has a static function make() which builds the result from a + // Reference + template + struct operator_arrow_result + { + // CWPro8.3 won't accept "operator_arrow_result::type", and we + // need that type below, so metafunction forwarding would be a + // losing proposition here. + typedef typename mpl::if_< + is_tag< + readable_lvalue_iterator_tag + , typename access_category_tag::type + > + , Pointer + , operator_arrow_proxy + >::type type; + + static type make(Reference x) + { + return type(&x); + } + }; + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + // Deal with ETI + template<> + struct operator_arrow_result + { + typedef int type; + }; +# endif + + // + // Facade is actually an iterator. We require Facade here + // so that we do not have to go through iterator_traits + // to access the traits + // + template + class operator_brackets_proxy + { + typedef typename Iterator::reference reference; + typedef typename Iterator::value_type value_type; + + public: + operator_brackets_proxy(Iterator const& iter) + : m_iter(iter) + {} + + operator reference() + { + return *m_iter; + } + + operator_brackets_proxy& operator=(value_type const& val) + { + *m_iter = val; + return *this; + } + + private: + Iterator m_iter; + }; + + template + struct operator_brackets_result + { + typedef typename access_category_tag::type access_category; + + typedef is_tag use_proxy; + + typedef typename mpl::if_< + use_proxy + , operator_brackets_proxy + , ValueType + >::type type; + }; + + template + operator_brackets_proxy make_operator_brackets_result(Iterator const& iter, mpl::true_) + { + return operator_brackets_proxy(iter); + } + + template + typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::false_) + { + return *iter; + } + + } // namespace detail + + + // Macros which describe the declarations of binary operators +# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ + template < \ + class Derived1, class V1, class AC1, class TC1, class R1, class D1 \ + , class Derived2, class V2, class AC2, class TC2, class R2, class D2 \ + > \ + prefix typename detail::enable_if_interoperable< \ + Derived1, Derived2, result_type \ + >::type \ + operator op( \ + iterator_facade const& lhs \ + , iterator_facade const& rhs) + +# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \ + template \ + prefix Derived operator+ args + + // + // Helper class for granting access to the iterator core interface. + // + // The simple core interface is used by iterator_facade. The core + // interface of a user/library defined iterator type should not be made public + // so that it does not clutter the public interface. Instead iterator_core_access + // should be made friend so that iterator_facade can access the core + // interface through iterator_core_access. + // + class iterator_core_access + { +# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + // Tasteless as this may seem, making all members public allows member templates + // to work in the absence of member template friends. + public: +# else + + template friend class iterator_facade; + +# define BOOST_ITERATOR_FACADE_RELATION(op) \ + BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, bool); + + BOOST_ITERATOR_FACADE_RELATION(==) + BOOST_ITERATOR_FACADE_RELATION(!=) + + BOOST_ITERATOR_FACADE_RELATION(<) + BOOST_ITERATOR_FACADE_RELATION(>) + BOOST_ITERATOR_FACADE_RELATION(<=) + BOOST_ITERATOR_FACADE_RELATION(>=) +# undef BOOST_ITERATOR_FACADE_RELATION + + BOOST_ITERATOR_FACADE_INTEROP_HEAD( + friend, -, typename Derived1::difference_type) + ; + + BOOST_ITERATOR_FACADE_PLUS_HEAD( + friend + , (iterator_facade const& + , typename Derived::difference_type) + ) + ; + + BOOST_ITERATOR_FACADE_PLUS_HEAD( + friend + , (typename Derived::difference_type + , iterator_facade const&) + ) + ; + +# endif + + template + static typename Facade::reference dereference(Facade const& f) + { + return f.dereference(); + } + + template + static void increment(Facade& f) + { + f.increment(); + } + + template + static void decrement(Facade& f) + { + f.decrement(); + } + + template + static bool equal(Facade1 const& f1, Facade2 const& f2) + { + return f1.equal(f2); + } + + template + static void advance(Facade& f, typename Facade::difference_type n) + { + f.advance(n); + } + + template + static typename Facade1::difference_type distance_to( + Facade1 const& f1, Facade2 const& f2) + { + return f1.distance_to(f2); + } + + private: + // objects of this class are useless + iterator_core_access(); //undefined + }; + + // + // iterator_facade - use as a public base class for defining new + // standard-conforming iterators. + // + template < + class Derived // The derived iterator type being constructed + , class Value + , class AccessCategory + , class TraversalCategory + , class Reference = typename detail::const_qualified_ref::type + , class Difference = std::ptrdiff_t + > + class iterator_facade +# ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE + : public detail::iterator_facade_types< + Value, AccessCategory, TraversalCategory, Reference, Difference + >::base +# undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE +# endif + { + private: + typedef typename + detail::iterator_facade_types + types; + + // + // Curiously Recursive Template interface. + // + typedef Derived derived_t; + + Derived& derived() + { + return static_cast(*this); + } + + Derived const& derived() const + { + return static_cast(*this); + } + + public: + + typedef typename types::value_type value_type; + typedef typename types::reference reference; + typedef typename types::difference_type difference_type; + typedef typename types::pointer pointer; + typedef typename types::iterator_category iterator_category; + + reference operator*() const + { + return iterator_core_access::dereference(this->derived()); + } + + typename detail::operator_arrow_result< + value_type + , iterator_category + , reference + , pointer + >::type + operator->() const + { + return detail::operator_arrow_result< + value_type + , iterator_category + , reference + , pointer + >::make(*this->derived()); + } + + typename detail::operator_brackets_result::type + operator[](difference_type n) const + { + typedef typename + detail::operator_brackets_result::use_proxy + use_proxy; + + return detail::make_operator_brackets_result(this->derived() + n, use_proxy()); + } + + Derived& operator++() + { + iterator_core_access::increment(this->derived()); + return this->derived(); + } + + Derived operator++(int) + { + Derived tmp(this->derived()); + ++*this; + return tmp; + } + + Derived& operator--() + { + iterator_core_access::decrement(this->derived()); + return this->derived(); + } + + Derived operator--(int) + { + Derived tmp(this->derived()); + --*this; + return tmp; + } + + Derived& operator+=(difference_type n) + { + iterator_core_access::advance(this->derived(), n); + return this->derived(); + } + + Derived& operator-=(difference_type n) + { + iterator_core_access::advance(this->derived(), -n); + return this->derived(); + } + + Derived operator-(difference_type x) const + { + Derived result(this->derived()); + return result -= x; + } + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + // There appears to be a bug which trashes the data of classes + // derived from iterator_facade when they are assigned unless we + // define this assignment operator. This bug is only revealed + // (so far) in STLPort debug mode, but it's clearly a codegen + // problem so we apply the workaround for all MSVC6. + iterator_facade& operator=(iterator_facade const&) + { + return *this; + } +# endif + }; + + // + // Operator implementation. The library supplied operators + // enables the user to provide fully interoperable constant/mutable + // iterator types. I.e. the library provides all operators + // for all mutable/constant iterator combinations. + // + // Note though that this kind of interoperability for constant/mutable + // iterators is not required by the standard for container iterators. + // All the standard asks for is a conversion mutable -> constant. + // Most standard library implementations nowadays provide fully interoperable + // iterator implementations, but there are still heavily used implementations + // that do not provide them. (Actually it's even worse, they do not provide + // them for only a few iterators.) + // + // ?? Maybe a BOOST_ITERATOR_NO_FULL_INTEROPERABILITY macro should + // enable the user to turn off mixed type operators + // + // The library takes care to provide only the right operator overloads. + // I.e. + // + // bool operator==(Iterator, Iterator); + // bool operator==(ConstIterator, Iterator); + // bool operator==(Iterator, ConstIterator); + // bool operator==(ConstIterator, ConstIterator); + // + // ... + // + // In order to do so it uses c++ idioms that are not yet widely supported + // by current compiler releases. The library is designed to degrade gracefully + // in the face of compiler deficiencies. In general compiler + // deficiencies result in less strict error checking and more obscure + // error messages, functionality is not affected. + // + // For full operation compiler support for "Substitution Failure Is Not An Error" + // (aka. enable_if) and boost::is_convertible is required. + // + // The following problems occur if support is lacking. + // + // Pseudo code + // + // --------------- + // AdaptorA a1; + // AdaptorA a2; + // + // // This will result in a no such overload error in full operation + // // If enable_if or is_convertible is not supported + // // The instantiation will fail with an error hopefully indicating that + // // there is no operator== for Iterator1, Iterator2 + // // The same will happen if no enable_if is used to remove + // // false overloads from the templated conversion constructor + // // of AdaptorA. + // + // a1 == a2; + // ---------------- + // + // AdaptorA a; + // AdaptorB b; + // + // // This will result in a no such overload error in full operation + // // If enable_if is not supported the static assert used + // // in the operator implementation will fail. + // // This will accidently work if is_convertible is not supported. + // + // a == b; + // ---------------- + // + +# define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, condition, return_prefix, base_op) \ + BOOST_ITERATOR_FACADE_INTEROP_HEAD(inline, op, result_type) \ + { \ + /* For those compilers that do not support enable_if */ \ + BOOST_STATIC_ASSERT(( \ + is_interoperable< Derived1, Derived2 >::value \ + && condition \ + )); \ + return_prefix iterator_core_access::base_op( \ + static_cast(rhs), static_cast(lhs)); \ + } + +# define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \ + BOOST_ITERATOR_FACADE_INTEROP( \ + op \ + , bool \ + , true \ + , return_prefix \ + , base_op \ + ) + + BOOST_ITERATOR_FACADE_RELATION(==, return, equal) + BOOST_ITERATOR_FACADE_RELATION(!=, return !, equal) + + BOOST_ITERATOR_FACADE_RELATION(<, return 0 >, distance_to) + BOOST_ITERATOR_FACADE_RELATION(>, return 0 <, distance_to) + BOOST_ITERATOR_FACADE_RELATION(<=, return 0 >=, distance_to) + BOOST_ITERATOR_FACADE_RELATION(>=, return 0 <=, distance_to) +# undef BOOST_ITERATOR_FACADE_RELATION + + // operator- requires an additional part in the static assertion + BOOST_ITERATOR_FACADE_INTEROP( + - + , typename Derived1::difference_type + , (is_same< + BOOST_DEDUCED_TYPENAME Derived1::difference_type + , BOOST_DEDUCED_TYPENAME Derived2::difference_type + >::value) + , return + , distance_to ) +# undef BOOST_ITERATOR_FACADE_INTEROP +# undef BOOST_ITERATOR_FACADE_INTEROP_HEAD + +# define BOOST_ITERATOR_FACADE_PLUS(args) \ + BOOST_ITERATOR_FACADE_PLUS_HEAD(inline, args) \ + { \ + Derived tmp(static_cast(i)); \ + return tmp += n; \ + } + +BOOST_ITERATOR_FACADE_PLUS(( + iterator_facade const& i + , typename Derived::difference_type n +)) + +BOOST_ITERATOR_FACADE_PLUS(( + typename Derived::difference_type n + , iterator_facade const& i +)) +# undef BOOST_ITERATOR_FACADE_PLUS +# undef BOOST_ITERATOR_FACADE_PLUS_HEAD + +} // namespace boost + +#include + +#endif // BOOST_ITERATOR_FACADE_23022003THW_HPP diff --git a/include/boost/iterator/iterator_traits.hpp b/include/boost/iterator/iterator_traits.hpp new file mode 100644 index 0000000..4f0d46f --- /dev/null +++ b/include/boost/iterator/iterator_traits.hpp @@ -0,0 +1,93 @@ +// Copyright David Abrahams 2003. 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 ITERATOR_TRAITS_DWA200347_HPP +# define ITERATOR_TRAITS_DWA200347_HPP + +# include +# include + +namespace boost { + +// Unfortunately, g++ 2.95.x chokes when we define a class template +// iterator_category which has the same name as its +// std::iterator_category() function, probably due in part to the +// "std:: is visible globally" hack it uses. Use +// BOOST_ITERATOR_CATEGORY to write code that's portable to older +// GCCs. + +# if BOOST_WORKAROUND(__GNUC__, <= 2) +# define BOOST_ITERATOR_CATEGORY iterator_category_ +# else +# define BOOST_ITERATOR_CATEGORY iterator_category +# endif + + +template +struct iterator_value +{ + typedef typename detail::iterator_traits::value_type type; +}; + +template +struct iterator_reference +{ + typedef typename detail::iterator_traits::reference type; +}; + + +template +struct iterator_pointer +{ + typedef typename detail::iterator_traits::pointer type; +}; + +template +struct iterator_difference +{ + typedef typename detail::iterator_traits::difference_type type; +}; + +template +struct BOOST_ITERATOR_CATEGORY +{ + typedef typename detail::iterator_traits::iterator_category type; +}; + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) +template <> +struct iterator_value +{ + typedef void type; +}; + +template <> +struct iterator_reference +{ + typedef void type; +}; + +template <> +struct iterator_pointer +{ + typedef void type; +}; + +template <> +struct iterator_difference +{ + typedef void type; +}; + +template <> +struct BOOST_ITERATOR_CATEGORY +{ + typedef void type; +}; +# endif + +} // namespace boost::iterator + +#endif // ITERATOR_TRAITS_DWA200347_HPP diff --git a/include/boost/iterator/new_iterator_tests.hpp b/include/boost/iterator/new_iterator_tests.hpp new file mode 100644 index 0000000..759f8de --- /dev/null +++ b/include/boost/iterator/new_iterator_tests.hpp @@ -0,0 +1,204 @@ +#ifndef BOOST_NEW_ITERATOR_TESTS_HPP +# define BOOST_NEW_ITERATOR_TESTS_HPP + +// This is meant to be the beginnings of a comprehensive, generic +// test suite for STL concepts such as iterators and containers. +// +// Revision History: +// 28 Oct 2002 Started update for new iterator categories +// (Jeremy Siek) +// 28 Apr 2002 Fixed input iterator requirements. +// For a == b a++ == b++ is no longer required. +// See 24.1.1/3 for details. +// (Thomas Witt) +// 08 Feb 2001 Fixed bidirectional iterator test so that +// --i is no longer a precondition. +// (Jeremy Siek) +// 04 Feb 2001 Added lvalue test, corrected preconditions +// (David Abrahams) + +# include +# include +# include +# include +# include // for detail::dummy_constructor +# include +# include + +namespace boost { + +void is_readable(readable_iterator_tag) { } +void is_writable(writable_iterator_tag) { } +void is_swappable(swappable_iterator_tag) { } +void is_constant_lvalue(readable_lvalue_iterator_tag) { } +void is_mutable_lvalue(writable_lvalue_iterator_tag) { } + +// Preconditions: *i == v +template +void readable_iterator_test(const Iterator i1, T v) +{ + Iterator i2(i1); // Copy Constructible + typedef typename detail::iterator_traits::reference ref_t; + ref_t r1 = *i1; + ref_t r2 = *i2; + T v1 = r1; + T v2 = r2; + assert(v1 == v); + assert(v2 == v); + typedef typename access_category::type result_category; + is_readable(result_category()); +} + +template +void writable_iterator_test(Iterator i, T v) +{ + Iterator i2(i); // Copy Constructible + *i2 = v; + is_writable(typename access_category::type()); +} + +template +void swappable_iterator_test(Iterator i, Iterator j) +{ + Iterator i2(i), j2(j); + typename detail::iterator_traits::value_type bi = *i, bj = *j; + iter_swap(i2, j2); + typename detail::iterator_traits::value_type ai = *i, aj = *j; + assert(bi == aj && bj == ai); + typedef typename access_category::type result_category; + is_swappable(result_category()); +} + +template +void constant_lvalue_iterator_test(Iterator i, T v1) +{ + Iterator i2(i); + typedef typename detail::iterator_traits::value_type value_type; + typedef typename detail::iterator_traits::reference reference; + BOOST_STATIC_ASSERT((is_same::value)); + const T& v2 = *i2; + assert(v1 == v2); + typedef typename access_category::type result_category; + is_constant_lvalue(result_category()); +} + +template +void mutable_lvalue_iterator_test(Iterator i, T v1, T v2) +{ + Iterator i2(i); + typedef typename detail::iterator_traits::value_type value_type; + typedef typename detail::iterator_traits::reference reference; + BOOST_STATIC_ASSERT((is_same::value)); + T& v3 = *i2; + assert(v1 == v3); + *i = v2; + T& v4 = *i2; + assert(v2 == v4); + typedef typename access_category::type result_category; + is_mutable_lvalue(result_category()); +} + +template +void forward_readable_iterator_test(Iterator i, Iterator j, T val1, T val2) +{ + Iterator i2; + Iterator i3(i); + i2 = i; + assert(i2 == i3); + assert(i != j); + assert(i2 != j); + readable_iterator_test(i, val1); + readable_iterator_test(i2, val1); + readable_iterator_test(i3, val1); + + assert(i == i2++); + assert(i != ++i3); + + readable_iterator_test(i2, val2); + readable_iterator_test(i3, val2); + + readable_iterator_test(i, val1); +} + +template +void forward_swappable_iterator_test(Iterator i, Iterator j, T val1, T val2) +{ + forward_readable_iterator_test(i, j, val1, val2); + Iterator i2 = i; + ++i2; + swappable_iterator_test(i, i2); +} + +// bidirectional +// Preconditions: *i == v1, *++i == v2 +template +void bidirectional_readable_iterator_test(Iterator i, T v1, T v2) +{ + Iterator j(i); + ++j; + forward_readable_iterator_test(i, j, v1, v2); + ++i; + + Iterator i1 = i, i2 = i; + + assert(i == i1--); + assert(i != --i2); + + readable_iterator_test(i, v2); + readable_iterator_test(i1, v1); + readable_iterator_test(i2, v1); + + --i; + assert(i == i1); + assert(i == i2); + ++i1; + ++i2; + + readable_iterator_test(i, v1); + readable_iterator_test(i1, v2); + readable_iterator_test(i2, v2); +} + + +// random access +// Preconditions: [i,i+N) is a valid range +template +void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals) +{ + bidirectional_readable_iterator_test(i, vals[0], vals[1]); + const Iterator j = i; + int c; + + for (c = 0; c < N-1; ++c) { + assert(i == j + c); + assert(*i == vals[c]); + assert(*i == j[c]); + assert(*i == *(j + c)); + assert(*i == *(c + j)); + ++i; + assert(i > j); + assert(i >= j); + assert(j <= i); + assert(j < i); + } + + Iterator k = j + N - 1; + for (c = 0; c < N-1; ++c) { + assert(i == k - c); + assert(*i == vals[N - 1 - c]); + assert(*i == j[N - 1 - c]); + Iterator q = k - c; + assert(*i == *q); + assert(i > j); + assert(i >= j); + assert(j <= i); + assert(j < i); + --i; + } +} + +// #if 0'd code snipped; see CVS v 1.4 if you need it back + +} // namespace boost + +#endif // BOOST_NEW_ITERATOR_TESTS_HPP diff --git a/include/boost/iterator/permutation_iterator.hpp b/include/boost/iterator/permutation_iterator.hpp new file mode 100644 index 0000000..f41da1a --- /dev/null +++ b/include/boost/iterator/permutation_iterator.hpp @@ -0,0 +1,92 @@ +// (C) Copyright Toon Knapen 2001. +// (C) Copyright David Abrahams 2003. +// (C) Copyright Roland Richter 2003. +// 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_PERMUTATION_ITERATOR_HPP +#define BOOST_PERMUTATION_ITERATOR_HPP + +#include + +#include + + +namespace boost +{ + +template< class ElementIterator + , class IndexIterator + , class ValueT = use_default + , class CategoryT = use_default + , class ReferenceT = use_default + , class DifferenceT = use_default > +class permutation_iterator + : public iterator_adaptor< + permutation_iterator + , ElementIterator, ValueT, CategoryT, ReferenceT, DifferenceT > +{ + typedef iterator_adaptor< + permutation_iterator + , ElementIterator, ValueT, CategoryT, ReferenceT, DifferenceT > super_t; + + friend class iterator_core_access; + +public: + permutation_iterator() : order_it_() {} + + explicit permutation_iterator(ElementIterator x, IndexIterator y) + : super_t(x), order_it_(y) {} + + template + permutation_iterator( + permutation_iterator const& r + , typename enable_if_convertible::type* = 0 + , typename enable_if_convertible::type* = 0 + ) + : super_t(r.base()) + {} + +private: + typename super_t::reference dereference() const + { return *(this->base() + *this->order_it_); } + + void increment() { ++this->order_it_; } + void decrement() { --this->order_it_; } + + void advance(typename super_t::difference_type n) + { + std::advance( order_it_, n ); + } + + template + typename super_t::difference_type + distance_to( permutation_iterator const& y ) const + { + return std::distance( this->order_it_, y.order_it_ ); + } + + template + bool + equal( permutation_iterator const& y ) const + { + return( y.order_it_ == this->order_it_ ); + } + + IndexIterator order_it_; +}; + + +template +permutation_iterator +make_permutation_iterator( ElementIterator e, IndexIterator i ) +{ + return permutation_iterator( e, i ); +} + + +} // namespace boost + +#endif diff --git a/include/boost/iterator/reverse_iterator.hpp b/include/boost/iterator/reverse_iterator.hpp new file mode 100644 index 0000000..43942eb --- /dev/null +++ b/include/boost/iterator/reverse_iterator.hpp @@ -0,0 +1,71 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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_REVERSE_ITERATOR_23022003THW_HPP +#define BOOST_REVERSE_ITERATOR_23022003THW_HPP + +#include +#include +#include + +namespace boost +{ + + // + // + // + template + class reverse_iterator + : public iterator_adaptor< reverse_iterator, Iterator > + { + typedef iterator_adaptor< reverse_iterator, Iterator > super_t; + + friend class iterator_core_access; + + public: + reverse_iterator() {} + + explicit reverse_iterator(Iterator x) + : super_t(x) {} + + template + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::type* = 0 + ) + : super_t(r.base()) + {} + + private: + typename super_t::reference dereference() const { return *boost::prior(this->base()); } + + void increment() { --this->base_reference(); } + void decrement() { ++this->base_reference(); } + + void advance(typename super_t::difference_type n) + { + this->base_reference() += -n; + } + + template + typename super_t::difference_type + distance_to(reverse_iterator const& y) const + { + return this->base_reference() - y.base(); + } + }; + + template + reverse_iterator make_reverse_iterator(BidirectionalIterator x) + { + return reverse_iterator(x); + } + +} // namespace boost + +#endif // BOOST_REVERSE_ITERATOR_23022003THW_HPP diff --git a/include/boost/iterator/transform_iterator.hpp b/include/boost/iterator/transform_iterator.hpp new file mode 100644 index 0000000..26ed994 --- /dev/null +++ b/include/boost/iterator/transform_iterator.hpp @@ -0,0 +1,154 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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_TRANSFORM_ITERATOR_23022003THW_HPP +#define BOOST_TRANSFORM_ITERATOR_23022003THW_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + template + class transform_iterator; + + namespace detail + { + + template + struct function_object_result + { + typedef typename UnaryFunction::result_type type; + }; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct function_object_result + { + typedef Return type; + }; +#endif + + // Given the transform iterator's transformation and iterator, this + // is the type used as its traits. + template + struct transform_iterator_base + { + private: + + // transform_iterator does not support writable/swappable iterators +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + BOOST_STATIC_ASSERT((is_tag< readable_iterator_tag, typename access_category::type >::value)); +#endif + + typedef typename mpl::apply_if< + is_same< Reference, use_default > + , function_object_result + , mpl::identity + >::type result_type; + + typedef typename mpl::if_< + is_same< Value, use_default > + , typename remove_reference< result_type >::type + , Value + >::type cv_value_type; + + typedef typename mpl::if_< + is_reference< result_type > + , typename mpl::if_< + is_const< cv_value_type > + , readable_lvalue_iterator_tag + , writable_lvalue_iterator_tag + >::type + , readable_iterator_tag + >::type maximum_access_tag; + + typedef typename minimum_category< + maximum_access_tag + , typename access_category::type + >::type access_category; + + public: + typedef iterator_adaptor< + transform_iterator + , Iterator + , cv_value_type + , iterator_tag< + access_category + , typename traversal_category::type + > + , result_type + > type; + }; + + } + + template + class transform_iterator + : public detail::transform_iterator_base::type + { + typedef typename + detail::transform_iterator_base::type + super_t; + + friend class iterator_core_access; + + public: + transform_iterator() { } + + transform_iterator(Iterator const& x, UnaryFunction f) + : super_t(x), m_f(f) { } + + template + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::type* = 0 + ) + : super_t(t.base()), m_f(t.functor()) {} + + UnaryFunction functor() const + { return m_f; } + + private: + typename super_t::reference dereference() const + { return m_f(*this->base()); } + + // Probably should be the initial base class so it can be + // optimized away via EBO if it is an empty class. + UnaryFunction m_f; + }; + + template + transform_iterator make_transform_iterator(Iterator it, UnaryFunction fun) + { + return transform_iterator(it, fun); + } + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + template + transform_iterator< Return (*)(Argument), Iterator, Return> + make_transform_iterator(Iterator it, Return (*fun)(Argument)) + { + return transform_iterator(it, fun); + } +#endif + +} // namespace boost + +#endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP From 80d9e8e4c1942fe810de1e772e6ca7aea680388e Mon Sep 17 00:00:00 2001 From: Joel de Guzman Date: Mon, 7 Jul 2003 14:20:34 +0000 Subject: [PATCH 166/265] Move from boost-sandbox [SVN r18959] --- doc/access.png | Bin 0 -> 11127 bytes doc/access2old.png | Bin 0 -> 42175 bytes doc/default.css | 188 ++ doc/facade-and-adaptor.rst | 1598 +++++++++++++++++ doc/iterator-categories.html | 822 +++++++++ doc/new-iter-concepts.rst | 731 ++++++++ doc/oldeqnew.png | Bin 0 -> 33786 bytes doc/traversal.png | Bin 0 -> 9112 bytes example/Jamfile | 1 + example/reverse_iterator.cpp | 16 + include/boost/iterator/detail/categories.hpp | 338 ++++ include/boost/iterator/detail/config_def.hpp | 104 ++ .../boost/iterator/detail/config_undef.hpp | 26 + include/boost/iterator/detail/enable_if.hpp | 88 + 14 files changed, 3912 insertions(+) create mode 100644 doc/access.png create mode 100644 doc/access2old.png create mode 100644 doc/default.css create mode 100644 doc/facade-and-adaptor.rst create mode 100644 doc/iterator-categories.html create mode 100644 doc/new-iter-concepts.rst create mode 100644 doc/oldeqnew.png create mode 100644 doc/traversal.png create mode 100644 example/Jamfile create mode 100644 example/reverse_iterator.cpp create mode 100644 include/boost/iterator/detail/categories.hpp create mode 100644 include/boost/iterator/detail/config_def.hpp create mode 100644 include/boost/iterator/detail/config_undef.hpp create mode 100644 include/boost/iterator/detail/enable_if.hpp diff --git a/doc/access.png b/doc/access.png new file mode 100644 index 0000000000000000000000000000000000000000..80011dcc7c82a35cbc173b314a9e247db0bf3f8c GIT binary patch literal 11127 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 Ofx*+&&t;ucLK6UGF@%Z$ literal 0 HcmV?d00001 diff --git a/doc/default.css b/doc/default.css new file mode 100644 index 0000000..2e1fddb --- /dev/null +++ b/doc/default.css @@ -0,0 +1,188 @@ +/* +:Author: David Goodger +:Contact: goodger@users.sourceforge.net +:date: $Date$ +:version: $Revision$ +:copyright: This stylesheet has been placed in the public domain. + +Default cascading style sheet for the HTML output of Docutils. +*/ + +.first { + margin-top: 0 } + +.last { + margin-bottom: 0 } + +a.toc-backref { + text-decoration: none ; + color: black } + +dd { + margin-bottom: 0.5em } + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.attention, div.caution, div.danger, div.error, div.hint, +div.important, div.note, div.tip, div.warning { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +div.hint p.admonition-title, div.important p.admonition-title, +div.note p.admonition-title, div.tip p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em } + +div.footer, div.header { + font-size: smaller } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr { + width: 75% } + +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.label { + white-space: nowrap } + +p.topic-title { + font-weight: bold } + +pre.address { + margin-bottom: 0 ; + margin-top: 0 ; + font-family: serif ; + font-size: 100% } + +pre.line-block { + font-family: serif ; + font-size: 100% } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em ; + background-color: #eeeeee } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.interpreted { + font-family: sans-serif } + +span.option-argument { + font-style: italic } + +span.pre { + white-space: pre } + +span.problematic { + color: red } + +table { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.citation { + border-left: solid thin gray ; + padding-left: 0.5ex } + +table.docinfo { + margin: 2em 4em } + +table.footnote { + border-left: solid thin black ; + padding-left: 0.5ex } + +td, th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: top } + +th.docinfo-name, th.field-name { + font-weight: bold ; + text-align: left ; + white-space: nowrap } + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + font-size: 100% } + +tt { + background-color: #eeeeee } + +ul.auto-toc { + list-style-type: none } diff --git a/doc/facade-and-adaptor.rst b/doc/facade-and-adaptor.rst new file mode 100644 index 0000000..169b856 --- /dev/null +++ b/doc/facade-and-adaptor.rst @@ -0,0 +1,1598 @@ ++++++++++++++++++++++++++++++ + Iterator Facade and Adaptor ++++++++++++++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, University of Hanover `Institute for Transport + Railway Operation and Construction`_ +:date: $Date$ +:Number: N1476=03-0059 +:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:abstract: We propose a set of class templates that help programmers + build standard-conforming iterators, both from scratch and + by adapting other iterators. + +.. contents:: Table of Contents + +============ + Motivation +============ + +Iterators play an important role in modern C++ programming. The +iterator is the central abstraction of the algorithms of the Standard +Library, allowing algorithms to be re-used in in a wide variety of +contexts. The C++ Standard Library contains a wide variety of useful +iterators. Every one of the standard containers comes with constant +and mutable iterators [#mutable]_, and also reverse versions of those +same iterators which traverse the container in the opposite direction. +The Standard also supplies ``istream_iterator`` and +``ostream_iterator`` for reading from and writing to streams, +``insert_iterator``, ``front_insert_iterator`` and +``back_insert_iterator`` for inserting elements into containers, and +``raw_storage_iterator`` for initializing raw memory [7]. + +Despite the many iterators supplied by the Standard Library, obvious +and useful iterators are missing, and creating new iterator types is +still a common task for C++ programmers. The literature documents +several of these, for example line_iterator [3] and Constant_iterator +[9]. The iterator abstraction is so powerful that we expect +programmers will always need to invent new iterator types. + +Although it is easy to create iterators that *almost* conform to the +standard, the iterator requirements contain subtleties which can make +creating an iterator which *actually* conforms quite difficult. +Further, the iterator interface is rich, containing many operators +that are technically redundant and tedious to implement. To automate +the repetitive work of constructing iterators, we propose +``iterator_facade``, an iterator base class template which provides +the rich interface of standard iterators and delegates its +implementation to member functions of the derived class. In addition +to reducing the amount of code necessary to create an iterator, the +``iterator_facade`` also provides compile-time error detection. +Iterator implementation mistakes that often go unnoticed are turned +into compile-time errors because the derived class implementation must +match the expectations of the ``iterator_facade``. + +A common pattern of iterator construction is the adaptation of one +iterator to form a new one. The functionality of an iterator is +composed of four orthogonal aspects: traversal, indirection, equality +comparison and distance measurement. Adapting an old iterator to +create a new one often saves work because one can reuse one aspect of +functionality while redefining the other. For example, the Standard +provides ``reverse_iterator``, which adapts any Bidirectional Iterator +by inverting its direction of traversal. As with plain iterators, +iterator adaptors defined outside the Standard have become commonplace +in the literature: + +* Checked iter[13] adds bounds-checking to an existing iterator. + +* The iterators of the View Template Library[14], which adapts + containers, are themselves adaptors over the underlying iterators. + +* Smart iterators [5] adapt an iterator's dereferencing behavior by + applying a function object to the object being referenced and + returning the result. + +* Custom iterators [4], in which a variety of adaptor types are enumerated. + +* Compound iterators [1], which access a slice out of a container of containers. + +* Several iterator adaptors from the MTL [12]. The MTL contains a + strided iterator, where each call to ``operator++()`` moves the + iterator ahead by some constant factor, and a scaled iterator, which + multiplies the dereferenced value by some constant. + +.. [#concept] We use the term concept to mean a set of requirements + that a type must satisfy to be used with a particular template + parameter. + +.. [#mutable] The term mutable iterator refers to iterators over objects that + can be changed by assigning to the dereferenced iterator, while + constant iterator refers to iterators over objects that cannot be + modified. + +To fulfill the need for constructing adaptors, we propose the +``iterator_adaptor`` class template. Instantiations of +``iterator_adaptor`` serve as a base classes for new iterators, +providing the default behavior of forwarding all operations to the +underlying iterator. The user can selectively replace these features +in the derived iterator class. This proposal also includes a number +of more specialized adaptors, such as the ``transform_iterator`` that +applies some user-specified function during the dereference of the +iterator. + +======================== + Impact on the Standard +======================== + +This proposal is purely an addition to the C++ standard library. +However, note that this proposal relies on the proposal for New +Iterator Concepts. + +======== + Design +======== + +Iterator Concepts +================= + +This proposal is formulated in terms of the new ``iterator concepts`` +as proposed in `n1477`_, since user-defined and especially adapted +iterators suffer from the well known categorization problems that are +inherent to the current iterator categories. + +.. _`n1477`: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/papers/2003/n1477.html + +This proposal does not strictly depend on proposal `n1477`_, as there +is a direct mapping between new and old categories. This proposal +could be reformulated using this mapping if `n1477`_ was not accepted. + +Interoperability +================ + +The question of iterator interoperability is poorly addressed in the +current standard. There are currently two defect reports that are +concerned with interoperability issues. + +Issue `179`_ concerns the fact that mutable container iterator types +are only required to be convertible to the corresponding constant +iterator types, but objects of these types are not required to +interoperate in comparison or subtraction expressions. This situation +is tedious in practice and out of line with the way built in types +work. This proposal implements the proposed resolution to issue +`179`_, as most standard library implementations do nowadays. In other +words, if an iterator type A has an implicit or user defined +conversion to an iterator type B, the iterator types are interoperable +and the usual set of operators are available. + +Issue `280`_ concerns the current lack of interoperability between +reverse iterator types. The proposed new reverse_iterator template +fixes the issues raised in 280. It provides the desired +interoperability without introducing unwanted overloads. + +.. _`179`: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#179 +.. _`280`: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#280 + + +Iterator Facade +=============== + +While the iterator interface is rich, there is a core subset of the +interface that is necessary for all the functionality. We have +identified the following core behaviors for iterators: + +* dereferencing +* incrementing +* decrementing +* equality comparison +* random-access motion +* distance measurement + +In addition to the behaviors listed above, the core interface elements +include the associated types exposed through iterator traits: +``value_type``, ``reference``, ``difference_type``, and +``iterator_category``. + +Iterator facade uses the Curiously Recurring Template Pattern (CRTP) +[Cop95]_ so that the user can specify the behavior of +``iterator_facade`` in a derived class. Former designs used policy +objects to specify the behavior. The proposal does not use policy +objects for several reasons: + + 1. the creation and eventual copying of the policy object may create + overhead that can be avoided with the current approach. + + 2. The policy object approach does not allow for custom constructors + on the created iterator types, an essential feature if + ``iterator_facade`` should be used in other library + implementations. + + 3. Without the use of CRTP, the standard requirement that an + iterator's ``operator++`` returns the iterator type itself means + that all iterators generated by ``iterator_facade`` would be + instantiations of ``iterator_facade``. Cumbersome type generator + metafunctions would be needed to build new parameterized + iterators, and a separate ``iterator_adaptor`` layer would be + impossible. + +The user of ``iterator_facade`` derives his iterator class from an +instantiation of ``iterator_facade`` and defines member functions +implementing the core behaviors. The following table describes +expressions which are required to be valid depending on the category +of the derived iterator type. These member functions are described +briefly below and in more detail in the `iterator facade requirements`_. + + +----------------------------------------+-------------------------------------------+ + | Expression | Effects | + +========================================+===========================================+ + | ``i.dereference()`` | Access the value referred to | + +----------------------------------------+-------------------------------------------+ + | ``i.equal(j)`` | Compare for equality with ``j`` | + +----------------------------------------+-------------------------------------------+ + | ``i.increment()`` | Advance by one position | + +----------------------------------------+-------------------------------------------+ + | ``i.decrement()`` | Retreat by one position | + +----------------------------------------+-------------------------------------------+ + | ``i.advance(n)`` | Advance by ``n`` positions | + +----------------------------------------+-------------------------------------------+ + | ``i.distance_to(j)`` | Measure the distance to ``j`` | + +----------------------------------------+-------------------------------------------+ + +.. Should we add a comment that a zero overhead implementation of iterator_facade + is possible with proper inlining? + +In addition to implementing the core interface functions, an iterator +derived from ``iterator_facade`` typically defines several +constructors. To model any of the standard iterator concepts, the +iterator must at least have a copy constructor. Also, if the iterator +type ``X`` is meant to be automatically interoperate with another +iterator type ``Y`` (as with constant and mutable iterators) then +there must be an implicit conversion from ``X`` to ``Y`` or from ``Y`` +to ``X`` (but not both), typically implemented as a conversion +constructor. Also, if the iterator is to model Forward Traversal +Iterator, a default constructor is required. + + + +Iterator Core Access +==================== + +``iterator_facade`` and the operator implementations need to be able +to access the core member functions in the derived class. Making the +core member functions public would expose an implementation detail to +the user. This proposal frees the public interface of the derived +iterator type from any implementation detail. + +Preventing direct access to the core member functions has two +advantages. First, there is no possibility for the user to accidently +use a member function of the iterator when a member of the value_type +was intended. This has been an issue with smart pointer +implementations in the past. The second and main advantage is that +library implementers can freely exchange a hand-rolled iterator +implementation for one based on ``iterator_facade`` without fear of +breaking code that was accessing the public core member functions +directly. + +In a naive implementation, keeping the derived class' core member +functions private would require it to grant friendship to +``iterator_facade`` and each of the seven operators. In order to +reduce the burden of limiting access, this proposal provides +``iterator_core_access``, a class that acts as a gateway to the core +member functions in the derived iterator class. The author of the +derived class only needs to grant friendship to +``iterator_core_access`` to make his core member functions available +to the library. + +.. This is no long uptodate -thw +.. Yes it is; I made sure of it! -DWA + +``iterator_core_access`` will be typically implemented as an empty +class containing only private static member functions which invoke the +iterator core member functions. There is, however, no need to +standardize the gateway protocol. Note that even if +``iterator_core_access`` used public member functions it would not +open a safety loophole, as every core member function preserves the +invariants of the iterator. + +``operator[]`` +================ + +The indexing operator for a generalized iterator presents special +challenges. A random access iterator's ``operator[]`` is only +required to return something convertible to its ``value_type``. +Requiring that it return an lvalue would rule out currently-legal +random-access iterators which hold the referenced value in a data +member (e.g. `counting_iterator`_), because ``*(p+n)`` is a reference +into the temporary iterator ``p+n``, which is destroyed when +``operator[]`` returns. + +Writable iterators built with ``iterator_facade`` implement the +semantics required by the preferred resolution to `issue 299`_ and +adopted by proposal `n1477`_: the result of ``p[n]`` is a proxy object +containing a copy of ``p+n``, and ``p[n] = x`` is equivalent to ``*(p ++ n) = x``. This approach will work properly for any random-access +iterator regardless of the other details of its implementation. A +user who knows more about the implementation of her iterator is free +to implement an ``operator[]`` which returns an lvalue in the derived +iterator class; it will hide the one supplied by ``iterator_facade`` +from clients of her iterator. + +.. _issue 299: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#299 + +``operator->`` +============== + +The ``reference`` type of a readable iterator (and today's input +iterator) need not in fact be a reference, so long as it is +convertible to the iterator's ``value_type``. When the ``value_type`` +is a class, however, it must still be possible to access members +through ``operator->``. Therefore, an iterator whose ``reference`` +type is not in fact a reference must return a proxy containing a copy +of the referenced value from its ``operator->``. + +This proposal does not explicitly specify the return type for +``operator->`` and ``operator[]``. Instead it requires each +``iterator_facade`` instantiation to meet the requirements of its +``iterator_category``. + +Iterator Adaptor +================ + +The ``iterator_adaptor`` class template adapts some ``Base`` [#base]_ +type to create a new iterator. Instantiations of ``iterator_adaptor`` +are derived from a corresponding instantiation of ``iterator_facade`` +and implement the core behaviors in terms of the ``Base`` type. In +essence, ``iterator_adaptor`` merely forwards all operations to an +instance of the ``Base`` type, which it stores as a member. + +.. [#base] The term "Base" here does not refer to a base class and is + not meant to imply the use of derivation. We have followed the lead + of the standard library, which provides a base() function to access + the underlying iterator object of a ``reverse_iterator`` adaptor. + +The user of ``iterator_adaptor`` creates a class derived from an +instantiation of ``iterator_adaptor`` and then selectively +redefines some of the core member functions described in the table +above. The ``Base`` type need not meet the full requirements for an +iterator. It need only support the operations used by the core +interface functions of ``iterator_adaptor`` that have not been +redefined in the user's derived class. + +Several of the template parameters of ``iterator_adaptor`` default to +``use_default``. This allows the user to make use of a default +parameter even when the user wants to specify a parameter later in the +parameter list. Also, the defaults for the corresponding associated +types are fairly complicated, so metaprogramming is required to +compute them, and ``use_default`` can help to simplify the +implementation. Finally, ``use_default`` is not left unspecified +because specification helps to highlight that the ``Reference`` +template parameter may not always be identical to the iterator's +``reference`` type, and will keep users making mistakes based on that +assumtion. + +Specialized Adaptors +==================== + +This proposal also contains several examples of specialized adaptors +which were easily implemented using ``iterator_adaptor``: + +* ``indirect_iterator``, which iterates over iterators, pointers, + or smart pointers and applies an extra level of dereferencing. + +* A new ``reverse_iterator``, which inverts the direction of a Base + iterator's motion, while allowing adapted constant and mutable + iterators to interact in the expected ways (unlike those in most + implementations of C++98). + +* ``transform_iterator``, which applies a user-defined function object + to the underlying values when dereferenced. + +* ``projection_iterator``, which is similar to ``transform_iterator`` + except that when dereferenced it returns a reference instead of + a value. + +* ``filter_iterator``, which provides a view of an iterator range in + which some elements of the underlying range are skipped. + +.. _counting_iterator: + +* ``counting_iterator``, which adapts any incrementable type + (e.g. integers, iterators) so that incrementing/decrementing the + adapted iterator and dereferencing it produces successive values of + the Base type. + +* ``function_output_iterator``, which makes it easier to create custom + output iterators. + +Based on examples in the Boost library, users have generated many new +adaptors, among them a permutation adaptor which applies some +permutation to a random access iterator, and a strided adaptor, which +adapts a random access iterator by multiplying its unit of motion by a +constant factor. In addition, the Boost Graph Library (BGL) uses +iterator adaptors to adapt other graph libraries, such as LEDA [10] +and Stanford GraphBase [8], to the BGL interface (which requires C++ +Standard compliant iterators). + +=============== + Proposed Text +=============== + + +Header ```` synopsis [lib.iterator.helper.synopsis] +======================================================================= + + +:: + + struct use_default; + + struct iterator_core_access { /* implementation detail */ }; + + template < + class Derived + , class Value + , class AccessCategory + , class TraversalCategory + , class Reference = Value& + , class Difference = ptrdiff_t + > + class iterator_facade; + + template < + class Derived + , class Base + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class iterator_adaptor; + + template < + class Iterator + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class indirect_iterator; + + template + class reverse_iterator; + + template < + class UnaryFunction + , class Iterator + , class Reference = use_default + , class Value = use_default + > + class transform_iterator; + + template + class filter_iterator; + + template < + class Incrementable + , class Category = use_default + , class Difference = use_default + > + class counting_iterator + + template + class function_output_iterator; + + + +Iterator facade [lib.iterator.facade] +===================================== + +``iterator_facade`` is a base class template which implements the +interface of standard iterators in terms of a few core functions +and associated types, to be supplied by a derived iterator class. + +Class template ``iterator_facade`` +---------------------------------- + +:: + + template < + class Derived + , class Value + , class AccessCategory + , class TraversalCategory + , class Reference = /* see below */ + , class Difference = ptrdiff_t + > + class iterator_facade { + public: + typedef remove_cv::type value_type; + typedef Reference reference; + typedef /* see description of operator-> */ pointer; + typedef Difference difference_type; + typedef iterator_tag iterator_category; + + reference operator*() const; + /* see below */ operator->() const; + /* impl defined */ operator[](difference_type n) const; + Derived& operator++(); + Derived operator++(int); + Derived& operator--(); + Derived operator--(int); + Derived& operator+=(difference_type n); + Derived& operator-=(difference_type n); + Derived operator-(difference_type n) const; + }; + + // Comparison operators + template + typename enable_if_interoperable::type // exposition + operator ==(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator !=(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator <(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator <=(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator >(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator >=(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator >=(iterator_facade const& lhs, + iterator_facade const& rhs); + + // Iterator difference + template + typename enable_if_interoperable::type + operator -(iterator_facade const& lhs, + iterator_facade const& rhs); + + // Iterator addition + template + Derived operator+ (iterator_facade const&, + typename Derived::difference_type n) + + +[*Note:* The ``enable_if_interoperable`` template used above is for exposition +purposes. The member operators should be only be in an overload set +provided the derived types ``Dr1`` and ``Dr2`` are interoperable, by +which we mean they are convertible to each other. The +``enable_if_interoperable`` approach uses SFINAE to take the operators +out of the overload set when the types are not interoperable.] + + +.. we need a new label here because the presence of markup in the + title prevents an automatic link from being generated + +.. _iterator facade requirements: + +``iterator_facade`` requirements +-------------------------------- + +The ``Derived`` template parameter must be a class derived from +``iterator_facade``. + +The default for the ``Reference`` parameter is `Value&`` if the access +category for ``iterator_facade`` is implicitly convertible to +``writable_iterator_tag``, and ``const Value&`` otherwise. + +The following table describes the other requirements on the +``Derived`` parameter. Depending on the resulting iterator's +``iterator_category``, a subset of the expressions listed in the table +are required to be valid. The operations in the first column must be +accessible to member functions of class ``iterator_core_access``. + +In the table below, ``X`` is the derived iterator type, ``a`` is an +object of type ``X``, ``b`` and ``c`` are objects of type ``const X``, +``n`` is an object of ``X::difference_type``, ``y`` is a constant +object of a single pass iterator type interoperable with X, and ``z`` +is a constant object of a random access traversal iterator type +interoperable with ``X``. + ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| Expression | Return Type | Assertion/Note/Precondition/Postcondition | Required to implement Iterator Concept(s) | +| | | | | ++========================================+========================================+=================================================+===========================================+ +| ``c.dereference()`` | ``X::reference`` | | Readable Iterator, Writable Iterator | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| ``c.equal(b)`` | convertible to bool |true iff ``b`` and ``c`` are equivalent. | Single Pass Iterator | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| ``c.equal(y)`` | convertible to bool |true iff ``c`` and ``y`` refer to the same | Single Pass Iterator | +| | |position. Implements ``c == y`` and ``c != y``. | | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| ``a.advance(n)`` | unused | | Random Access Traversal Iterator | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| ``a.increment()`` | unused | | Incrementable Iterator | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| ``a.decrement()`` | unused | | Bidirectional Traversal Iterator | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| ``c.distance_to(b)`` | convertible to X::difference_type | equivalent to ``distance(c, b)`` | Random Access Traversal Iterator | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| ``c.distance_to(z)`` | convertible to X::difference_type |equivalent to ``distance(c, z)``. Implements ``c| Random Access Traversal Iterator | +| | |- z``, ``c < z``, ``c <= z``, ``c > z``, and ``c | | +| | |>= c``. | | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ + + +.. We should explain more about how the + functions in the interface of iterator_facade + are there conditionally. -JGS + + +``iterator_facade`` operations +------------------------------ + +The operations in this section are described in terms of operations on +the core interface of ``Derived`` which may be inaccessible +(i.e. private). The implementation should access these operations +through member functions of class ``iterator_core_access``. + +``reference operator*() const;`` + +:Returns: ``static_cast(this)->dereference()`` + +*see below* ``operator->() const;`` + +:Returns: If ``X::reference`` is a reference type, returns an object + of type ``X::pointer`` equal to:: + + &static_cast(this)->dereference() + + Otherwise returns an object of unspecified type such that, given an + object ``a`` of type ``X``, ``a->m`` is equivalent to ``(w = *a, + w.m)`` for some temporary object ``w`` of type ``X::value_type``. + + The type ``X::pointer`` is ``Value*`` if the access category for + ``X`` is implicitly convertible to ``writable_iterator_tag``, and + ``Value const*`` otherwise. + + +*unspecified* ``operator[](difference_type n) const;`` + +:Returns: an object convertible to ``X::reference`` and holding a copy + *p* of ``a+n`` such that, for a constant object ``v`` of type + ``X::value_type``, ``X::reference(a[n] = v)`` is equivalent + to ``p = v``. + + + +``Derived& operator++();`` + +:Effects: + + :: + + static_cast(this)->increment(); + return *this; + +.. I realize that the committee is moving away from specifying things + like this in terms of code, but I worried about the imprecision of + saying that a core interface function is invoked without describing + the downcast. An alternative to what I did would be to mention it + above where we talk about accessibility. + + +``Derived operator++(int);`` + +:Effects: + + :: + + Derived tmp(static_cast(this)); + ++*this; + return tmp; + + +``Derived& operator--();`` + +:Effects: + + :: + + static_cast(this)->decrement(); + return *this; + + +``Derived operator--(int);`` + +:Effects: + + :: + + Derived tmp(static_cast(this)); + --*this; + return tmp; + + +``Derived& operator+=(difference_type n);`` + +:Effects: + + :: + + static_cast(this)->advance(n); + return *this; + + +``Derived& operator-=(difference_type n);`` + +:Effects: + + :: + + static_cast(this)->advance(-n); + return *this; + + +``Derived operator-(difference_type n) const;`` + +:Effects: + + Derived tmp(static_cast(this)); + return tmp -= n; + +:Returns: ``static_cast(this)->advance(-n);`` + + +Iterator adaptor [lib.iterator.adaptor] +======================================= + +The ``iterator_adaptor`` is a base class template derived from an +instantiation of ``iterator_facade``. The core interface functions +expected by ``iterator_facade`` are implemented in terms of the +``iterator_adaptor``\ 's ``Base`` template parameter. A class derived +from ``iterator_adaptor`` typically redefines some of the core +interface functions to adapt the behavior of the ``Base`` type. +Whether the derived class models any of the standard iterator concepts +depends on the operations supported by the ``Base`` type and which +core interface functions of ``iterator_facade`` are redefined in the +``Derived`` class. + + +Class template ``iterator_adaptor`` +----------------------------------- + +:: + + template < + class Derived + , class Base + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class iterator_adaptor + : public iterator_facade + { + friend class iterator_core_access; + public: + iterator_adaptor(); + explicit iterator_adaptor(Base iter); + Base base() const; + protected: + Base const& base_reference() const; + Base& base_reference(); + private: // Core iterator interface for iterator_facade. + typename iterator_adaptor::reference dereference() const; + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + bool equal(iterator_adaptor const& x) const; + + void advance(typename iterator_adaptor::difference_type n); + void increment(); + void decrement(); + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + typename iterator_adaptor::difference_type distance_to( + iterator_adaptor const& y) const; + + private: + Base m_iterator; + }; + + + +``iterator_adaptor`` requirements +--------------------------------- + +The ``Derived`` template parameter must be a derived class of +``iterator_adaptor``. The ``Base`` type must implement the expressions +involving ``m_iterator`` in the specifications of those private member +functions of ``iterator_adaptor`` that are not redefined by the +``Derived`` class and that are needed to model the concept +corresponding to the chosen ``Category`` according to the requirements +of ``iterator_facade``. The rest of the template parameters specify +the types for the member typedefs in ``iterator_facade``. The +following pseudo-code specifies the traits types for +``iterator_adaptor``. + +:: + + if (Value == use_default) + value_type = iterator_traits::value_type; + else + value_type = remove_cv::type; + + if (Reference == use_default) { + if (Value == use_default) + reference = iterator_traits::reference; + else + reference = Value&; + } else + reference = Reference; + + if (Distance == use_default) + difference_type = iterator_traits::difference_type; + else + difference_type = Distance; + + if (Category == use_default) + iterator_category = iterator_tag< + access_category< + iterator< iterator_traits::iterator_category, + Value, + Distance, + Value*, + Reference > >, + traversal_category< + iterator< iterator_traits::iterator_category, + Value, + Distance, + Value*, + Reference > > + else + iterator_category = Category; + + +.. Replaced with new semantics --thw + if (Category == use_default) + iterator_category = iterator_traits::iterator_category; + else + iterator_category = Category; + + + +``iterator_adaptor`` public operations +-------------------------------------- + +``iterator_adaptor();`` + +:Requires: The ``Base`` type must be Default Constructible. +:Returns: An instance of ``iterator_adaptor`` with + ``m_iterator`` default constructed. + + +``explicit iterator_adaptor(Base iter);`` + +:Returns: An instance of ``iterator_adaptor`` with + ``m_iterator`` copy constructed from ``iter``. + +``Base base() const;`` + +:Returns: ``m_iterator`` + + +``iterator_adaptor`` protected member functions +----------------------------------------------- + +``Base const& base_reference() const;`` + +:Returns: A const reference to ``m_iterator``. + + +``Base& base_reference();`` + +:Returns: A non-const reference to ``m_iterator``. + + +``iterator_adaptor`` private member functions +--------------------------------------------- + +``typename iterator_adaptor::reference dereference() const;`` + +:Returns: ``*m_iterator`` + +:: + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + bool equal(iterator_adaptor const& x) const; + +:Returns: ``m_iterator == x.base()`` + + +``void advance(typename iterator_adaptor::difference_type n);`` + +:Effects: ``m_iterator += n;`` + +``void increment();`` + +:Effects: ``++m_iterator;`` + +``void decrement();`` + +:Effects: ``--m_iterator;`` + +:: + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + typename iterator_adaptor::difference_type distance_to( + iterator_adaptor const& y) const; + +:Returns: ``y.base() - m_iterator`` + + + +Specialized adaptors [lib.iterator.special.adaptors] +==================================================== + +.. The requirements for all of these need to be written *much* more + formally -DWA + + +[*Note:* The ``enable_if_convertible::type`` expression used in +this section is for exposition purposes. The converting constructors +for specialized adaptors should be only be in an overload set provided +that an object of type ``X`` is implicitly convertible to an object of +type ``Y``. The ``enable_if_convertible`` approach uses SFINAE to +take the constructor out of the overload set when the types are not +implicitly convertible.] + + +Indirect iterator +----------------- + +The indirect iterator adapts an iterator by applying an *extra* +dereference inside of ``operator*()``. For example, this iterator +adaptor makes it possible to view a container of pointers +(e.g. ``list``) as if it were a container of the pointed-to type +(e.g. ``list``) . + +.. At some point we should add the capability to handle + iterators over smart pointers, which the impl handles. -JGS + + +Class template ``indirect_iterator`` +.................................... + +:: + + template < + class Iterator + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class indirect_iterator + : public iterator_adaptor + { + friend class iterator_core_access; + public: + indirect_iterator(); + indirect_iterator(Iterator x); + template < + class Iterator2, class Value2, class Category2 + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Category2, Reference2, Difference2 + > const& y + , typename enable_if_convertible::type* = 0 // exposition + ); + private: // as-if specification + typename indirect_iterator::reference dereference() const + { + return **this->base(); + } + }; + +``indirect_iterator`` requirements +.................................. + +The ``value_type`` of the ``Iterator`` template parameter should +itself be dereferenceable. The return type of the ``operator*`` for +the ``value_type`` must be the same type as the ``Reference`` template +parameter. The ``Value`` template parameter will be the ``value_type`` +for the ``indirect_iterator``, unless ``Value`` is const. If ``Value`` +is ``const X``, then ``value_type`` will be *non-* ``const X``. The +default for ``Value`` is + +:: + + iterator_traits< iterator_traits::value_type >::value_type + +If the default is used for ``Value``, then there must be a valid +specialization of ``iterator_traits`` for the value type of the base +iterator. + +The ``Reference`` parameter will be the ``reference`` type of the +``indirect_iterator``. The default is ``Value&``. + +The ``Category`` parameter is the ``iterator_category`` type for the +``indirect_iterator``. The default is +``iterator_traits::iterator_category``. + +The indirect iterator will model the most refined standard traversal +concept that is modeled by the ``Iterator`` type. The indirect +iterator will model the most refined standard access concept that is +modeled by the value type of ``Iterator``. + + +``indirect_iterator`` operations +................................ + +``indirect_iterator();`` + +:Requires: ``Iterator`` must be Default Constructible. +:Returns: An instance of ``indirect_iterator`` with + a default constructed base object. + + +``indirect_iterator(Iterator x);`` + +:Returns: An instance of ``indirect_iterator`` with + the ``iterator_adaptor`` subobject copy constructed from ``x``. + +:: + + template < + class Iterator2, class Value2, class Category2 + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Category2, Reference2, Difference2 + > const& y + , typename enable_if_convertible::type* = 0 // exposition + ); + +:Requires: ``Iterator2`` is implicitly convertible to ``Iterator``. +:Returns: An instance of ``indirect_iterator`` that is a copy of ``y``. + +Reverse iterator +---------------- + +.. I think we'd better strike the old reverse_iterator text from the standard, eh? + +The reverse iterator adaptor flips the direction of a base iterator's +motion. Invoking ``operator++()`` moves the base iterator backward and +invoking ``operator--()`` moves the base iterator forward. + +Class template ``reverse_iterator`` +................................... + +:: + + template + class reverse_iterator : + public iterator_adaptor< reverse_iterator, Iterator > + { + friend class iterator_core_access; + public: + reverse_iterator() {} + explicit reverse_iterator(Iterator x) ; + + template + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::type* = 0 // exposition + ); + + private: // as-if specification + typename reverse_iterator::reference dereference() const { return *prior(this->base()); } + + void increment() { --this->base_reference(); } + void decrement() { ++this->base_reference(); } + + void advance(typename reverse_iterator::difference_type n) + { + this->base_reference() += -n; + } + + template + typename reverse_iterator::difference_type + distance_to(reverse_iterator const& y) const + { + return this->base_reference() - y.base(); + } + + }; + + +``reverse_iterator`` requirements +................................. + +The base ``Iterator`` must be a model of Bidirectional Traversal +Iterator. The resulting ``reverse_iterator`` will be a model of the +most refined standard traversal and access concepts that are modeled +by ``Iterator``. + + +``reverse_iterator();`` + +:Requires: ``Iterator`` must be Default Constructible. +:Returns: An instance of ``reverse_iterator`` with a + default constructed base object. + +``explicit reverse_iterator(Iterator x);`` + +:Returns: An instance of ``reverse_iterator`` with a + base object copy constructed from ``x``. + + +:: + + template + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::type* = 0 // exposition + ); + +:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. +:Returns: An instance of ``reverse_iterator`` that is a copy of ``r``. + + +Transform iterator +------------------ + +The transform iterator adapts an iterator by applying some function +object to the result of dereferencing the iterator. In other words, +the ``operator*`` of the transform iterator first dereferences the +base iterator, passes the result of this to the function object, and +then returns the result. + + +Class template ``transform_iterator`` +..................................... + +:: + + template + class transform_iterator + : public iterator_adaptor + { + friend class iterator_core_access; + public: + transform_iterator(); + transform_iterator(Iterator const& x, AdaptableUnaryFunction f); + + template + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + ); + + AdaptableUnaryFunction functor() const; + private: + typename transform_iterator::value_type dereference() const; + AdaptableUnaryFunction m_f; + }; + + +``transform_iterator`` requirements +................................... + +The type ``AdaptableUnaryFunction`` must be Assignable, Copy +Constructible, and the expression ``f(x)`` must be valid where ``f`` +is an object of type ``AdaptableUnaryFunction``, ``x`` is an object of +type ``AdaptableUnaryFunction::argument_type``, and where the type of +``f(x)`` must be ``AdaptableUnaryFunction::result_type``. + +The type ``Iterator`` must at least model Readable Iterator. The +resulting ``transform_iterator`` models the most refined of the +following options that is also modeled by ``Iterator``. + + * Writable Lvalue Iterator if the ``result_type`` of the + ``AdaptableUnaryFunction`` is a non-const reference. + + * Readable Lvalue Iterator if the ``result_type`` is a const + reference. + + * Readable Iterator otherwise. + + +The ``transform_iterator`` models the most refined standard traversal +concept that is modeled by ``Iterator``. + +The ``value_type`` of ``transform_iterator`` is +``remove_reference::type``. The ``reference`` type is +``result_type``. + + +``transform_iterator`` public operations +........................................ + + +``transform_iterator();`` + +:Returns: An instance of ``transform_iterator`` with ``m_f`` + and ``m_iterator`` default constructed. + + +``transform_iterator(Iterator const& x, AdaptableUnaryFunction f);`` + +:Returns: An instance of ``transform_iterator`` with ``m_f`` + initialized to ``f`` and ``m_iterator`` initialized to ``x``. + + +:: + + template + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + ); + +:Returns: An instance of ``transform_iterator`` that is a copy of ``t``. +:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. + +``AdaptableUnaryFunction functor() const;`` + +:Returns: ``m_f`` + +``transform_iterator`` private operations +......................................... + +``typename transform_iterator::value_type dereference() const;`` + +:Returns: ``m_f(transform_iterator::dereference());`` + + + +Filter iterator +--------------- + +The filter iterator adaptor creates a view of an iterator range in +which some elements of the range are skipped over. A predicate +function object controls which elements are skipped. When the +predicate is applied to an element, if it returns ``true`` then the +element is retained and if it returns ``false`` then the element is +skipped over. When skipping over elements, it is necessary for the +filter adaptor to know when to stop so as to avoid going past the end +of the underlying range. Therefore the constructor of the filter +iterator takes two iterator parameters: the position for the filtered +iterator and the end of the range. + + + +Class template ``filter_iterator`` +.................................. + +:: + + template + class filter_iterator + : public iterator_adaptor< + filter_iterator, Iterator + , use_default + , /* see details */ + > + { + public: + filter_iterator(); + filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); + filter_iterator(Iterator x, Iterator end = Iterator()); + template + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + ); + Predicate predicate() const; + Iterator end() const; + + private: // as-if specification + void increment() + { + ++(this->base_reference()); + satisfy_predicate(); + } + + void satisfy_predicate() + { + while (this->base() != this->m_end && !this->m_predicate(*this->base())) + ++(this->base_reference()); + } + + Predicate m_predicate; + Iterator m_end; + }; + + +``filter_iterator`` requirements +-------------------------------- + +The base ``Iterator`` parameter must be a model of Readable Iterator +and Single Pass Iterator. The resulting ``filter_iterator`` will be a +model of Forward Traversal Iterator if ``Iterator`` is, otherwise the +``filter_iterator`` will be a model of Single Pass Iterator. The +access category of the ``filter_iterator`` will be the most refined +standard access category that is modeled by ``Iterator``. + +.. Thomas is going to try implementing filter_iterator so that + it will be bidirectional if the underlying iterator is. -JGS + + +The ``Predicate`` must be Assignable, Copy Constructible, and the +expression ``p(x)`` must be valid where ``p`` is an object of type +``Predicate``, ``x`` is an object of type +``iterator_traits::value_type``, and where the type of +``p(x)`` must be convertible to ``bool``. + + + +``filter_iterator`` operations +------------------------------ + +``filter_iterator();`` + +:Requires: ``Predicate`` and ``Iterator`` must be Default Constructible. +:Returns: a ``filter_iterator`` whose + predicate is a default constructed ``Predicate`` and + whose ``end`` is a default constructed ``Iterator``. + + +``filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());`` + +:Returns: A ``filter_iterator`` at position ``x`` that filters according + to predicate ``f`` and that will not increment past ``end``. + + +``filter_iterator(Iterator x, Iterator end = Iterator());`` + +:Requires: ``Predicate`` must be Default Constructible. +:Returns: A ``filter_iterator`` at position ``x`` that filters + according to a default constructed ``Predicate`` + and that will not increment past ``end``. + + +:: + + template + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + );`` + +:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. +:Returns: A copy of iterator ``t``. + + +``Predicate predicate() const;`` + +:Returns: A copy of the predicate object used to construct ``*this``. + + +``Iterator end() const;`` + +:Returns: The object ``end`` used to construct ``*this``. + + +Counting iterator +----------------- + +The counting iterator adaptor implements dereference by returning a +reference to the base object. The other operations are implemented by +the base ``m_iterator``, as per the inheritance from +``iterator_adaptor``. + + +Class template ``counting_iterator`` +.................................... + +:: + + template + class counting_iterator + : public iterator_adaptor< + counting_iterator + , Incrementable + , Incrementable + , /* see details for category */ + , Incrementable const& + , Incrementable const* + , /* distance = Difference or a signed integral type */> + { + friend class iterator_core_access; + public: + counting_iterator(); + counting_iterator(counting_iterator const& rhs); + counting_iterator(Incrementable x); + private: + typename counting_iterator::reference dereference() const + { + return this->base_reference(); + } + }; + + +[*Note:* implementers are encouraged to provide an implementation of + ``distance_to`` and a ``difference_type`` that avoids overflows in + the cases when the ``Incrementable`` type is a numeric type.] + +``counting_iterator`` requirements +---------------------------------- + +The ``Incrementable`` type must be Default Constructible, Copy +Constructible, and Assignable. The default distance is +an implementation defined signed integegral type. + +The resulting ``counting_iterator`` models Readable Lvalue Iterator. + +Furthermore, if you wish to create a counting iterator that is a Forward +Traversal Iterator, then the following expressions must be valid: +:: + + Incrementable i, j; + ++i // pre-increment + i == j // operator equal + +If you wish to create a counting iterator that is a +Bidirectional Traversal Iterator, then pre-decrement is also required: +:: + + --i + +If you wish to create a counting iterator that is a Random Access +Traversal Iterator, then these additional expressions are also +required: +:: + + counting_iterator::difference_type n; + i += n + n = i - j + i < j + + + + +``counting_iterator`` operations +-------------------------------- + +``counting_iterator();`` + +:Returns: A default constructed instance of ``counting_iterator``. + + +``counting_iterator(counting_iterator const& rhs);`` + +:Returns: An instance of ``counting_iterator`` that is a copy of ``rhs``. + + + +``counting_iterator(Incrementable x);`` + +:Returns: An instance of ``counting_iterator`` with its base + object copy constructed from ``x``. + + +Function output iterator +------------------------ + +The function output iterator adaptor makes it easier to create custom +output iterators. The adaptor takes a unary function and creates a +model of Output Iterator. Each item assigned to the output iterator is +passed as an argument to the unary function. The motivation for this +iterator is that creating a conforming output iterator is non-trivial, +particularly because the proper implementation usually requires a +proxy object. + + +Class template ``function_output_iterator`` +........................................... + +:: + + template + class function_output_iterator { + public: + typedef iterator_tag< + writable_iterator_tag + , incrementable_iterator_tag + > iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + explicit function_output_iterator(const UnaryFunction& f = UnaryFunction()); + + struct output_proxy { + output_proxy(UnaryFunction& f); + template output_proxy& operator=(const T& value); + }; + output_proxy operator*(); + function_output_iterator& operator++(); + function_output_iterator& operator++(int); + }; + + +``function_output_iterator`` requirements +----------------------------------------- + +The ``UnaryFunction`` must be Assignable, Copy Constructible, and the +expression ``f(x)`` must be valid, where ``f`` is an object of type +``UnaryFunction`` and ``x`` is an object of a type accepted by ``f``. +The resulting ``function_output_iterator`` is a model of the Writable +and Incrementable Iterator concepts. + + +``function_output_iterator`` operations +--------------------------------------- + +``explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());`` + +:Returns: An instance of ``function_output_iterator`` with + ``f`` stored as a data member. + + +``output_proxy operator*();`` + +:Returns: An instance of ``output_proxy`` constructed with + a copy of the unary function ``f``. + + +``function_output_iterator& operator++();`` + +:Returns: ``*this`` + + +``function_output_iterator& operator++(int);`` + +:Returns: ``*this`` + + +``function_output_iterator::output_proxy`` operations +----------------------------------------------------- + +``output_proxy(UnaryFunction& f);`` + +:Returns: An instance of ``output_proxy`` with ``f`` stored as + a data member. + + +``template output_proxy& operator=(const T& value);`` + +:Effects: + :: + + m_f(value); + return *this; + + + +.. [Cop95] [Coplien, 1995] Coplien, J., Curiously Recurring Template + Patterns, C++ Report, February 1995, pp. 24-27. + +.. + LocalWords: Abrahams Siek Witt istream ostream iter MTL strided interoperate + LocalWords: CRTP metafunctions inlining lvalue JGS incrementable BGL LEDA cv + LocalWords: GraphBase struct ptrdiff UnaryFunction const int typename bool pp + LocalWords: lhs rhs SFINAE markup iff tmp OtherDerived OtherIterator DWA foo + LocalWords: dereferenceable subobject AdaptableUnaryFunction impl pre ifdef'd + LocalWords: OtherIncrementable Coplien diff --git a/doc/iterator-categories.html b/doc/iterator-categories.html new file mode 100644 index 0000000..eb76523 --- /dev/null +++ b/doc/iterator-categories.html @@ -0,0 +1,822 @@ + +Improved Iterator Categories and Requirements + + + +

+
Improved Iterator Categories and Requirements

+

Introduction

The standard iterator categories and requirements are +flawed because they use a single hierarchy of requirements to address two +orthogonal issues: iterator traversal and dereference return +type. The current iterator requirement hierarchy is mainly geared +towards iterator traversal (hence the category names), while requirements that +address dereference return type sneak in at various places. The following table +gives a summary of the current dereference return type requirements in the +iterator categories. +

+

+
+ + + + + + + + + + + + + +
Output Iterator*i = a
Input Iterator*i is convertible to T
Forward Iterator*i is T& (or const T& once issue + 200 is resolved)
Random Access Iteratori[n] is convertible to T (which is odd because the + operational semantics say i[n] is equivalent to *(i + n) + which would have a return type of T&)
Table 1. Summary of current dereference return type + requirements.
+

Examples of useful iterators that do not ``fit''

+

Because of the mixing of iterator traversal and dereference return type, many +useful iterators can not be appropriately categorized. For example, +vector<bool>::iterator is almost a random access iterator, but +the return type is not bool& (see +issue 96 +and Herb Sutter's paper J16/99-0008 = WG21 N1185). Therefore, the +iterators only meet the requirements of input iterator and output iterator. This +is so nonintuitive that at least one implementation erroneously assigns +random_access_iterator_tag as its iterator_category. Also, +vector<bool> is not the only example of useful iterators that do +not return true references: there is the often cited example of disk-based +collections. +

Another example is a counting iterator, an iterator the returns a sequence of +integers when incremented and dereferenced (see boost::counting_iterator). +There are two ways to implement this iterator, 1) make the reference +type be a true reference (a reference to an integer data member of the counting +iterator) or 2) make the reference type be the same as the +value_type. Option 1) runs into the problems discussed in Issue +198, the reference will not be valid after the iterator is destroyed. Option +2) is therefore a better choice, but then we have a counting iterator that +cannot be a random access iterator. +

Yet another example is a transform iterator, an iterator adaptor that applies +a unary function object to the dereference value of the wrapped iterator (see boost::transform_iterator). +For unary functions such as std::times the return type of +operator* clearly needs to be the result_type of the function +object, which is typically not a reference. However, with the current iterator +requirements, if you wrap int* with a transform iterator, you do not +get a random access iterator as expected, but an input iterator. +

A fourth example is found in the vertex and edge iterators of the Boost Graph +Library. These iterators return vertex and edge descriptors, which are +lightweight handles created on-the-fly. They must be returned by-value. As a +result, their current standard iterator category is +std::input_iterator_tag, which means that, strictly speaking, you could +not use these iterators with algorithms like std::min_element(). As a +temporary solution, we introduced the concept Multi-Pass +Input Iterator to describe the vertex and edge descriptors, but as the +design notes for concept suggest, a better solution is needed. +

In short, there are many useful iterators that do not fit into the current +standard iterator categories. As a result, the following bad things happen: +

    +
  • Iterators are often miss-categorized. +
  • Algorithm requirements are more strict than necessary, because they can + not separate out the need for random-access from the need for a true reference + return type.
+

Proposal for new iterator categories and requirements

The iterator +requirements should be separated into two hierarchies. One set of concepts +handles the return type semantics: +The other set of concepts handles iterator +traversal: + + +

The current Input Iterator and Output Iterator requirements will +continue to be used as is. Note that Input Iterator implies Readable +Iterator and Output Iterator implies Writable Iterator.

+ +

Note: we considered defining a Single-Pass Iterator, which could be +combined with Readable or Writable Iterator to replace the Input and +Output Iterator requirements. We rejected this idea because there are +several differences between Input and Output Iterators that make it +hard to merge them: Input Iterator requires Equality Comparable while +Output Iterator does not and Input Iterator requires Assignable while +Output Iterator does not.

+ +

New category tags and traits classes

+ +

The new iterator categories will require new tag classes.

+ +
namespace std {
+
+  // Returns Category Tags
+  struct readable_iterator_tag { };
+  struct writable_iterator_tag { };
+  struct swappable_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 { };
+
+  // Traversal Category Tags
+  struct input_traversal_tag { };
+  struct output_traversal_tag { };
+  struct forward_traversal_tag { };
+  struct bidirectional_traversal_tag : public forward_traversal_tag { };
+  struct random_access_traversal_tag : public bidirectional_traversal_tag { };
+
+}
+
+ +

Access to the return and traversal tags will be through the +following two traits classes, which have a member typedef named +type that provides the tag type. We explain the +definitions of these classes later.

+ +
+  template <typename Iterator>
+  struct return_category; // contains: typedef ... type;
+
+  template <typename Iterator>
+  struct traversal_category; // contains: typedef ... type;
+
+ +

We want it to be convenient for programmers to create iterators +that satisfy both the old and new iterator requirements. Therefore +the following class is provided as a way to create tags for use as the +old iterator_category typedef within +iterator_traits. + +

namespace std {
+  template <class ReturnTag, class TraversalTag>
+  struct iterator_tag : cvt_iterator_category<ReturnTag, TraversalTag>::type
+  {
+    typedef ReturnTag returns;
+    typedef TraversalTag traversal;
+  };
+
+ +

The cvt_iterator_category template computes the +appropriate old iterator category based on the return and traversal +category.

+ +
namespace std {
+  template <class RC, class TC>
+  struct cvt_iterator_category
+  {
+    // Pseudo-code, <= means inherits or same type
+    if (RC <= constant_lvalue_iterator_tag || RC <= mutable_lvalue_iterator_tag) {
+      if (TC <= random_access_traversal_tag)
+        typedef random_access_iterator_tag type;
+      else if (TC <= bidirectional_traversal_tag)
+        typedef bidirectional_iterator_tag type;
+      else if (TC <= forward_traversal_tag)
+        typedef forward_iterator_tag type;
+      else
+        error;
+   } else if (RC <= readable_iterator_tag && RC <= input_traversal_tag)
+     typedef input_iterator_tag type;
+   else if (RC <= writable_iterator_tag && output_traversal_tag)
+     typedef output_iterator_tag type;
+   else
+     error;
+  };
+}
+
+ +

The following is an example of a new iterator class using the +iterator_tag class to create its iterator_category +member typedef.

+ +
+struct my_iterator {
+  typedef std::iterator_tag<std::readable_iterator_tag, 
+    std::random_access_traversal_tag> iterator_category;
+  ...
+};
+
+ +We also want old iterators to work with new algorithms, that is, +algorithms that use the new iterator categories. We facilitate this by +defining the return_category and traversal_category +in such a way as they can be used with both old and new iterators. +For old iterators, the appropriate return and traversal categories are +computed based on the old iterator category. For new iterators, the +return and traversal tags are extracted from within the +iterator_category tag. + + +
+  template <typename Iterator>
+  class return_category
+  {
+    // Pseudo-code
+    typedef iterator_traits<Iterator>::iterator_category tag;
+    typedef iterator_traits<Iterator>::value_type T;
+  public:
+    if (exists(tag::returns)) // must be a new iterator
+      typedef tag::returns type;
+    else if (tag <= forward_iterator_tag) {
+      if (is-const(T))
+        typedef constant_lvalue_iterator_tag type;
+      else
+        typedef mutable_lvalue_iterator_tag type;
+    } else if (tag <= input_iterator_tag)
+      typedef readable_iterator_tag type;
+    else if (tag <= output_iterator_tag)
+      typedef writable_iterator_tag type;
+    else
+      error;
+  };
+
+  template <typename T>
+  struct return_category<T*>
+  {
+    // Pseudo-code
+    if (is-const(T))
+      typedef boost::constant_lvalue_iterator_tag type;
+    else
+      typedef boost::mutable_lvalue_iterator_tag type;
+  };
+
+  template <typename Iterator>
+  class traversal_category
+  {
+    typedef iterator_traits<Iterator>::iterator_category tag;
+  public:
+    // Pseudo-code
+    if (exists(tag::traversal)) // must be a new iterator
+      typedef tag::traversal type;
+    else if (tag <= random_access_iterator_tag)
+      typedef random_access_traversal_tag type;
+    else if (tag <= bidirectional_iterator_tag)
+      typedef bidirectional_traversal_tag type;
+    else if (tag <= is_forward_iterator_tag)
+      typedef forward_traversal_tag type;
+    else if (tag <= input_iterator_tag)
+      typedef input_traversal_tag type;
+    else if (tag <= out_iterator_tag)
+      typedef output_traversal_tag type;
+    else
+      error;
+  };
+
+  template <typename T>
+  struct traversal_category<T*>
+  {
+    typedef random_access_traversal_tag type;
+  };
+
+ +

Impact on the Standard Algorithms

+ +

Many of the standard algorithms place more requirements than +necessary on their iterator parameters due to the coarseness of the +current iterator categories. By using the new iterator categories a +better fit can be achieved, thereby increasing the reusability of the +algorithms. These changes will not affect user-code, though they will +require changes by standard implementers: dispatching should be based +on the new categories, and in places return values may need to be +handled more carefully. In particular, uses of std::swap() +will need to be replaced with std::iter_swap(), and +std::iter_swap() will need to call std::swap().

+ +

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AlgorithmRequirement Change
find_endForward Iterator
-> Forward Traversal Iterator and + Readable Iterator
find_first_of
adjacent_find
search
search_n
rotate_copy
lower_bound
upper_bound
equal_range
binary_search
min_element
max_element
iter_swapForward Iterator
-> Swappable Iterator
fillForward Iterator
-> Forward Traversal Iterator and + Writable Iterator
generate
swap_rangesForward Iterator
-> Forward Traversal Iterator and + Swappable Iterator
rotate
replaceForward Iterator
-> Forward Traversal Iterator + and
Readable Iterator and Writable Iterator
replace_if
remove
remove_if
unique
reverseBidirectional Iterator
-> Bidirectional Traversal + Iterator and Swappable Iterator
partition
copy_backwardsBidirectional Iterator
-> Bidirectional Traversal Iterator and + Readable Iterator
Bidirectional Iterator
-> Bidirectional + Traversal Iterator and Writable Iterator
next_permutationBidirectional Iterator
-> Bidirectional Traversal + Iterator and
Swappable Iterator and Readable Iterator
prev_permutation
stable_partitionBidirectional Iterator
-> Bidirectional Traversal + Iterator and
Readable Iterator and Writable Iterator
inplace_merge
reverse_copyBidirectional Iterator
-> Bidirectional Traversal Iterator and + Readable Iterator
random_shuffleRandom Access Iterator
-> Random Access Traversal + Iterator and Swappable Iterator
sort
stable_sort
partial_sort
nth_element
push_heap
pop_heap
make_heap
sort_heap
Table 2. Requirement changes for standard + algorithms.
+

The New Iterator Requirements

+

Notation

+ + + + + + + + + + + + + +
XThe iterator type.
TThe value type of X, i.e., + std::iterator_traits<X>::value_type.
x, yAn object of type X.
tAn object of type T.
+

+


+ +

Readable Iterator

A Readable +Iterator is an iterator that dereferences to produce an rvalue that is +convertible to the value_type of the iterator. +

Associated Types

+ + + + + + + + + + + + + +
Value typestd::iterator_traits<X>::value_typeThe type of the objects pointed to by the iterator.
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator. This type must be + convertible to T.
Return Categorystd::return_category<X>::typeA type convertible to std::readable_iterator_tag +
+

Refinement of

Copy +Constructible +

Valid expressions

+ + + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Dereference*x std::iterator_traits<X>::reference
Member accessx->mT is a type with a member named m.If m is a data member, the type of m. If m + is a member function, the return type of m.
+

+


+ +

Writable Iterator

A Writable +Iterator is an iterator that can be used to store a value using the +dereference-assignment expression. +

Definitions

If x is an Writable Iterator of type X, +then the expression *x = a; stores the value a into +x. Note that operator=, like other C++ functions, may be +overloaded; it may, in fact, even be a template function. In general, then, +a may be any of several different types. A type A belongs to +the set of value types of X if, for an object a of type +A, *x = a; is well-defined and does not require performing any +non-trivial conversions on a. +

Associated Types

+ + + + + +
Return Categorystd::return_category<X>::typeA type convertible to std::writable_iterator_tag +
+

Refinement of

Copy +Constructible +

Valid expressions

+ + + + + + + + + +
NameExpressionReturn type
Dereference assignment*x = aunspecified
+

+


+ +

Swappable Iterator

A Swappable +Iterator is an iterator whose dereferenced values can be swapped. +

Note: the requirements for Swappable Iterator are dependent on the issues +surrounding std::swap() being resolved. Here we assume that the issue +will be resolved by allowing the overload of std::swap() for +user-defined types. +

Note: Readable Iterator and Writable Iterator combined implies Swappable +Iterator because of the fully templated std::swap(). However, Swappable +Iterator does not imply Readable Iterator nor Writable Iterator. +

Associated Types

+ + + + + +
Return Categorystd::return_category<X>::typeA type convertible to std::swappable_iterator_tag +
+

Valid expressions

Of the two valid expressions listed below, only one +OR the other is required. If std::iter_swap() is overloaded for +X then std::swap() is not required. If +std::iter_swap() is not overloaded for X then the default +(fully templated) version is used, which will call std::swap() (this +means changing the current requirements for std::iter_swap()). +

+ + + + + + + + + + + + + +
NameExpressionReturn type
Iterator Swapstd::iter_swap(x, y)void
Dereference and Swapstd::swap(*x, *y)void
+

+


+ +

Constant Lvalue Iterator

A +Constant Lvalue Iterator is an iterator that dereferences to produce a const +reference to the pointed-to object, i.e., the associated reference type +is const T&. Changing the value of or destroying an iterator that +models Constant Lvalue Iterator does not invalidate pointers and references +previously obtained from that iterator. +

Refinement of

Readable +Iterator +

Associated Types

+ + + + + + + + + +
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator, which must be const + T&.
Return Categorystd::return_category<X>::typeA type convertible to std::constant_lvalue_iterator_tag +
+

+


+ +

Mutable Lvalue Iterator

A +Mutable Lvalue Iterator is an iterator that dereferences to produce a reference +to the pointed-to object. The associated reference type is +T&. Changing the value of or destroying an iterator that models +Mutable Lvalue Iterator does not invalidate pointers and references previously +obtained from that iterator. +

Refinement of

Readable +Iterator, Writable +Iterator, and Swappable +Iterator. +

Associated Types

+ + + + + + + + + +
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator, which must be + T&.
Return Categorystd::return_category<X>::typeA type convertible to std::mutable_lvalue_iterator_tag +
+

+


+ +

Forward Traversal Iterator +

The Forward Iterator is an iterator that can be incremented. Also, it is +permissible to make multiple passes through the iterator's range. +

Refinement of

Copy +Constructible, Assignable, Default +Constructible, and Equality +Comparable +

Associated types

+ + + + + + + + + +
Difference Typestd::iterator_traits<X>::difference_typeA signed integral type used for representing distances between + iterators that point into the same range.
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::forward_traversal_tag +
+

Valid expressions

+ + + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Preincrement++i X&
Postincrementi++ convertible to const X&
+

+


+ +

Bidirectional Traversal +Iterator

An iterator that can be incremented and decremented. +

Refinement of

Forward +Traversal Iterator +

Associated types

+ + + + + +
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::bidirectional_traversal_tag +
+

Valid expressions

+ + + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Predecrement--i X&
Postdecrementi-- convertible to const X&
+

+


+ +

Random Access Traversal +Iterator

An iterator that provides constant-time methods for moving forward +and backward in arbitrary-sized steps. +

Refinement of

Bidirectional +Traversal Iterator and Less Than +Comparable where < is a total ordering +

Associated types

+ + + + + +
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::random_access_traversal_tag +
+

Valid expressions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Iterator additioni += n X&
Iterator additioni + n or n + i X
Iterator subtractioni -= n X&
Iterator subtractioni - n X
Differencei - j std::iterator_traits<X>::difference_type
Element operatori[n]X must also be a model of Readable + Iterator. std::iterator_traits<X>::reference
Element assignmenti[n] = tX must also be a model of Writable + Iterator.unspecified
+

+


+ diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst new file mode 100644 index 0000000..cd29dbe --- /dev/null +++ b/doc/new-iter-concepts.rst @@ -0,0 +1,731 @@ +++++++++++++++++++++++ + New Iterator Concepts +++++++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ +:date: $Date$ +:Number: N1477=03-0060 +:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:Abstract: We propose a new system of iterator concepts that treat + access and positioning independently. This allows the + concepts to more closely match the requirements + of algorithms and provides better categorizations + of iterators that are used in practice. This proposal + is a revision of paper n1297_. + +.. contents:: Table of Contents + +.. _n1297: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2001/n1297.html + +============ + Motivation +============ + +The standard iterator categories and requirements are flawed because +they use a single hierarchy of concepts to address two orthogonal +issues: *iterator traversal* and *value access*. As a result, many +algorithms with requirements expressed in terms of the iterator +categories are too strict. Also, many real-world iterators can not be +accurately categorized. A proxy-based iterator with random-access +traversal, for example, may only legally have a category of "input +iterator", so generic algorithms are unable to take advantage of its +random-access capabilities. The current iterator concept hierarchy is +geared towards iterator traversal (hence the category names), while +requirements that address value access sneak in at various places. The +following table gives a summary of the current value access +requirements in the iterator categories. + ++------------------------+-------------------------------------------------------------------------+ +| Output Iterator | ``*i = a`` | ++------------------------+-------------------------------------------------------------------------+ +| Input Iterator | ``*i`` is convertible to ``T`` | ++------------------------+-------------------------------------------------------------------------+ +| Forward Iterator | ``*i`` is ``T&`` (or ``const T&`` once | +| | `issue 200`_ is resolved) | ++------------------------+-------------------------------------------------------------------------+ +| Random Access Iterator | ``i[n]`` is convertible to ``T`` (also ``i[n] = t`` is required for | +| | mutable iterators once `issue 299`_ is resolved) | ++------------------------+-------------------------------------------------------------------------+ + +.. _issue 200: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#200 +.. _issue 299: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#299 + + +Because iterator traversal and value access are mixed together in a +single hierarchy, many useful iterators can not be appropriately +categorized. For example, ``vector::iterator`` is almost a +random access iterator, but the return type is not ``bool&`` (see +`issue 96`_ and Herb Sutter's paper J16/99-0008 = WG21 +N1185). Therefore, the iterators of ``vector`` only meet the +requirements of input iterator and output iterator. This is so +nonintuitive that at least one implementation erroneously assigns +``random_access_iterator_tag`` as its ``iterator_category``. + +.. _issue 96: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#96 + +Another difficult-to-categorize iterator is the transform iterator, an +adaptor which applies a unary function object to the dereferenced +value of the some underlying iterator (see `transform_iterator`_). +For unary functions such as ``times``, the return type of +``operator*`` clearly needs to be the ``result_type`` of the function +object, which is typically not a reference. Because random access +iterators are required to return lvalues from ``operator*``, if you +wrap ``int*`` with a transform iterator, you do not get a random +access iterator as might be expected, but an input iterator. + +.. _`transform_iterator`: http://www.boost.org/libs/utility/transform_iterator.htm + +A third example is found in the vertex and edge iterators of the +`Boost Graph Library`_. These iterators return vertex and edge +descriptors, which are lightweight handles created on-the-fly. They +must be returned by-value. As a result, their current standard +iterator category is ``input_iterator_tag``, which means that, +strictly speaking, you could not use these iterators with algorithms +like ``min_element()``. As a temporary solution, the concept +`Multi-Pass Input Iterator`_ was introduced to describe the vertex and +edge descriptors, but as the design notes for the concept suggest, a +better solution is needed. + +.. _Boost Graph Library: http://www.boost.org/libs/graph/doc/table_of_contents.html +.. _Multi-Pass Input Iterator: http://www.boost.org/libs/utility/MultiPassInputIterator.html + +In short, there are many useful iterators that do not fit into the +current standard iterator categories. As a result, the following bad +things happen: + +- Iterators are often mis-categorized. + +- Algorithm requirements are more strict than necessary, because they + cannot separate the need for random access or bidirectional + traversal from the need for a true reference return type. + + +======================== + Impact on the Standard +======================== + +The new iterator concepts are backward-compatible with the old +iterator requirements, and old iterators are forward-compatible with +the new iterator concepts. That is to say, iterators that satisfy the +old requirements also satisfy appropriate concepts in the new system, +and iterators modeling the new concepts will automatically satisfy the +appropriate old requirements. + +.. I think we need to say something about the resolution to allow + convertibility to any of the old-style tags as a TR issue (hope it + made it). -DWA + +.. Hmm, not sure I understand. Are you talking about whether a + standards conforming input iterator is allowed to have + a tag that is not input_iterator_tag but that + is convertible to input_iterator_tag? -JGS + +The algorithms in the standard library benefit from the new iterator +concepts because the new concepts provide a more accurate way to +express their type requirements. The result is algorithms that are +usable in more situations and have fewer type requirements. The +following lists the proposed changes to the type requirements of +algorithms. + +Forward Iterator -> Forward Traversal Iterator and Readable Iterator + ``find_end, adjacent_find, search, search_n, rotate_copy, lower_bound, upper_bound, equal_range, binary_search, min_element, max_element`` + +Forward Iterator (1) -> Single Pass Iterator and Readable Iterator +Forward Iterator (2) -> Forward Traversal Iterator and Readable Iterator + ``find_first_of`` + +Forward Iterator -> Readable Iterator and Writable Iterator + ``iter_swap`` + +Forward Iterator -> Single Pass Iterator and Writable Iterator + ``fill, generate`` + +Forward Iterator -> Forward Traversal Iterator and Swappable Iterator + ``rotate`` + +Forward Iterator (1) -> Swappable Iterator and Single Pass Iterator +Forward Iterator (2) -> Swappable Iterator and Incrementable Iterator + ``swap_ranges`` + +Forward Iterator -> Forward Traversal Iterator and Readable Iterator and Writable Iterator + ``remove, remove_if, unique`` + +Forward Iterator -> Single Pass Iterator and Readable Iterator and Writable Iterator + ``replace, replace_if`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator + ``reverse`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable and Swappable Iterator + ``partition`` + +Bidirectional Iterator (1) -> Bidirectional Traversal Iterator and Readable Iterator, +Bidirectional Iterator (2) -> Bidirectional Traversal Iterator and Writable Iterator + ``copy_backwards`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator and Readable Iterator + ``next_permutation, prev_permutation`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator and Writable Iterator + ``stable_partition, inplace_merge`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator + ``reverse_copy`` + +Random Access Iterator -> Random Access Traversal Iterator and Readable and Swappable Iterator + ``random_shuffle, sort, stable_sort, partial_sort, nth_element, push_heap, pop_heap + make_heap, sort_heap`` + +Input Iterator (2) -> Incrementable Iterator and Readable Iterator + ``equal`` + +Input Iterator (2) -> Incrementable Iterator and Readable Iterator + ``transform`` + +======== + Design +======== + +The iterator requirements are be separated into two hierarchies. One +set of concepts handles the syntax and semantics of value access: + +- Readable Iterator +- Writable Iterator +- Swappable Iterator +- Readable Lvalue Iterator +- Writable Lvalue Iterator + +The refinement relationships among these iterator concepts are given +in the following diagram. + +.. image:: access.png + +The access concepts describe requirements related to ``operator*`` and +``operator->``, including the ``value_type``, ``reference``, and +``pointer`` associated types. + +The other set of concepts handles traversal: + +- Incrementable Iterator +- Single Pass Iterator +- Forward Traversal Iterator +- Bidirectional Traversal Iterator +- Random Access Traversal Iterator + +The refinement relationships for the traversal concepts are in the +following diagram. + +.. image:: traversal.png + +In addition to the iterator movement operators, such as +``operator++``, the traversal concepts also include requirements on +position comparison such as ``operator==`` and ``operator<``. The +reason for the fine grain slicing of the concepts into the +Incrementable and Single Pass is to provide concepts that are exact +matches with the original input and output iterator requirements. + +The relationship between the new iterator concepts and the old are +given in the following diagram. + +.. image:: oldeqnew.png + +Like the old iterator requirements, we provide tags for purposes of +dispatching. There are two hierarchies of tags, one for the access +concepts and one for the traversal concepts. We provide an access +mechanism for mapping iterator types to these new tags. Our design +reuses ``iterator_traits::iterator_category`` as the access +mechanism. To enable this, a pair of access and traversal tags are +combined into a single type using the following `iterator_tag` class. + +:: + + template + struct iterator_tag : /* appropriate old category or categories */ + { + typedef AccessTag access; + typedef TraversalTag traversal; + }; + +The ``iterator_tag`` class template is derived from the appropriate +iterator tag or tags from the old requirements based on the new-style +tags passed as template parameters. The algorithm for determining the +old tag or tags from the new tags picks the least-refined old concepts +that include all of the requirements of the access and traversal +concepts (that is, the closest fit), if any such category exists. For +example, a the category tag for a Readable Single Pass Iterator will +always be derived from ``input_iterator_tag``, while the category tag +for a Single Pass Iterator that is both Readable and Writable will be +derived from both ``input_iterator_tag`` and ``output_iterator_tag``. + +We also provide two helper classes that make it convenient to obtain +the access and traversal tags of an iterator. These helper classes +work both for iterators whose ``iterator_category`` is +``iterator_tag`` and also for iterators using the original iterator +categories. + +:: + + template struct access_category { typedef ... type; }; + template struct traversal_category { typedef ... type; }; + + +The most difficult design decision concerned the ``operator[]``. The +direct approach for specifying ``operator[]`` would have a return type +of ``reference``; the same as ``operator*``. However, going in this +direction would mean that an iterator satisfying the old Random Access +Iterator requirements would not necessarily be a model of Readable or +Writable Lvalue Iterator. Instead we have chosen a design that +matches the preferred resolution of `issue 299`_: ``operator[]`` is +only required to return something convertible to the ``value_type`` +(for a Readable Iterator), and is required to support assignment +``i[n] = t`` (for a Writable Iterator). + + +=============== + Proposed Text +=============== + +Addition to [lib.iterator.requirements] +======================================= + +Iterator Value Access Concepts [lib.iterator.value.access] +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +In the tables below, ``X`` is an iterator type, ``a`` is a constant +object of type ``X``, ``T`` is +``std::iterator_traits::value_type``, and ``v`` is a constant +object of type ``T``. + +.. _Readable Iterator: + +Readable Iterators [lib.readable.iterators] +------------------------------------------- + +A class or built-in type ``X`` models the *Readable Iterator* concept +for the value type ``T`` if the following expressions are valid and +respect the stated semantics. ``U`` is the type of any specified +member of type ``T``. + + +------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Readable Iterator Requirements (in addition to CopyConstructible) | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +======================================+===================================================+=================================================================+ + | ``iterator_traits::value_type`` | ``T`` | Any non-reference, non-cv-qualified type | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | ``iterator_traits::reference`` | Convertible to ``iterator_traits::value_type`` | | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | ``access_category::type`` | Convertible to ``readable_iterator_tag`` | | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | ``*a`` | ``iterator_traits::reference`` | pre: ``a`` is dereferenceable. If ``a == b`` then | + | | | ``*a`` is equivalent to ``*b`` | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | ``a->m`` | ``U&`` | pre: ``(*a).m`` is well-defined. Equivalent to ``(*a).m`` | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + + +.. _Writable Iterator: + +Writable Iterators [lib.writable.iterators] +------------------------------------------- + +A class or built-in type ``X`` models the *Writable Iterator* concept +if the following expressions are valid and respect the stated +semantics. + +.. A type ``T`` belongs to the *set of value types* of ``X`` + if, for an object ``v`` of type ``T``, ``*a = v`` is valid. + + ** This appears to be a mutual recursion which ends up meaning + nothing. Kill the assertion column? + + Separate but related question: Is a writable iterator required + to have a meaningful value_type? If not, we need to use a + different name from ``v`` in this table -DWA + ++------------------------------------------------------------------------------------------------------------------------------+ +| Writable Iterator Requirements (in addition to CopyConstructible) | ++--------------------------------------+------------------------------------------+--------------------------------------------+ +| Expression | Return Type | Assertion/Note/Precondition/Postcondition | ++======================================+==========================================+============================================+ +| ``access_category::type`` | Convertible to ``writable_iterator_tag`` | | ++--------------------------------------+------------------------------------------+--------------------------------------------+ +| ``*a = v`` | | .. ** pre: The type of ``v`` is in the set | +| | | of value types of ``X`` | ++--------------------------------------+------------------------------------------+--------------------------------------------+ + + +Swappable Iterators [lib.swappable.iterators] +--------------------------------------------- + +A class or built-in type ``X`` models the *Swappable Iterator* concept +if the following expressions are valid and respect the stated +semantics. + + +------------------------------------------------------------------------------------------------+ + | Swappable Iterator Requirements (in addition to CopyConstructible) | + +------------------------------------+-------------+---------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +====================================+=============+=============================================+ + | ``iter_swap(a, b)`` | ``void`` | post: the pointed to values are exchanged | + +------------------------------------+-------------+---------------------------------------------+ + +[*Note:* An iterator that is a model of the *Readable* and *Writable Iterator* concepts + is also a model of *Swappable Iterator*. *--end note*] + + +Readable Lvalue Iterators [lib.readable.lvalue.iterators] +--------------------------------------------------------- + +The *Readable Lvalue Iterator* concept adds the requirement that the +``reference`` type be a reference to the value type of the iterator. + + +--------------------------------------------------------------------------------------------------------------------------------------------------+ + | Readable Lvalue Iterator Requirements (in addition to Readable Iterator) | + +------------------------------------+-------------------------------------------------+-----------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +====================================+=================================================+===========================================================+ + | ``iterator_traits::reference`` | ``T&`` | ``T`` is *cv* ``iterator_traits::value_type`` where | + | | | *cv* is an optional cv-qualification | + +------------------------------------+-------------------------------------------------+-----------------------------------------------------------+ + | ``access_category::type`` | Convertible to ``readable_lvalue_iterator_tag`` | | + +------------------------------------+-------------------------------------------------+-----------------------------------------------------------+ + + +Writable Lvalue Iterators [lib.writable.lvalue.iterators] +--------------------------------------------------------- + +The *Writable Lvalue Iterator* concept adds the requirement that the +``reference`` type be a non-const reference to the value type of the +iterator. + + +------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Writable Lvalue Iterator Requirements (in addition to Readable Lvalue Iterator) | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +======================================+==================================================+============================================================+ + | ``iterator_traits::reference`` | ``iterator_traits::value_type&`` | | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | ``access_category::type`` | Convertible to ``writable_lvalue_iterator_tag`` | | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + + +Iterator Traversal Concepts [lib.iterator.traversal] +++++++++++++++++++++++++++++++++++++++++++++++++++++ + +In the tables below, ``X`` is an iterator type, ``a`` and ``b`` are +constant objects of type ``X``, ``r`` and ``s`` are mutable objects of +type ``X``, ``T`` is ``std::iterator_traits::value_type``, and +``v`` is a constant object of type ``T``. + + +Incrementable Iterators [lib.incrementable.iterators] +----------------------------------------------------- + +A class or built-in type ``X`` models the *Incrementable Iterator* +concept if the following expressions are valid and respect the stated +semantics. + + + +------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible) | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +======================================+==================================================+============================================================+ + | ``++r`` | ``X&`` | ``&r == &++r`` | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | ``r++`` | convertible to ``const X&`` | ``{ X tmp = r; ++r; return tmp; }`` | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | ``traversal_category::type`` | | Convertible to ``incrementable_iterator_tag`` | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + + +Single Pass Iterators [lib.single.pass.iterators] +------------------------------------------------- + +A class or built-in type ``X`` models the *Single Pass Iterator* +concept if the following expressions are valid and respect the stated +semantics. + + +------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality Comparable) | + +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition/Semantics | + +==================================+=========================+=========================================================================================+ + | ``++r`` | ``X&`` | pre: ``r`` is dereferenceable; post: ``r`` is dereferenceable or ``r`` is past-the-end | + +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + | ``a == b`` | convertible to ``bool`` | ``==`` is an equivalence relation over its domain | + +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + | ``a != b`` | convertible to ``bool`` | ``!(a == b)`` | + +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + | ``traversal_category::type`` | | Convertible to ``single_pass_iterator_tag`` | + +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + + +Forward Traversal Iterators [lib.forward.traversal.iterators] +------------------------------------------------------------- + +A class or built-in type ``X`` models the *Forward Traversal Iterator* +concept if the following expressions are valid and respect the stated +semantics. + + +----------------------------------------------------------------------------------------------------------------------------------+ + | Forward Traversal Iterator Requirements (in addition to Single Pass Iterator) | + +------------------------------------------+--------------+------------------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition/Semantics | + +==========================================+==============+========================================================================+ + | ``X u;`` | ``X&`` | ``note: u may have a singular value.`` | + +------------------------------------------+--------------+------------------------------------------------------------------------+ + | ``++r`` | ``X&`` | ``r == s`` and ``r`` is dereferenceable implies ``++r == ++s.`` | + +------------------------------------------+--------------+------------------------------------------------------------------------+ + | ``iterator_traits::difference_type`` | | A signed integral type representing the distance between iterators | + +------------------------------------------+--------------+------------------------------------------------------------------------+ + | ``traversal_category::type`` | | Convertible to ``forward_traversal_iterator_tag`` | + +------------------------------------------+--------------+------------------------------------------------------------------------+ + + +Bidirectional Traversal Iterators [lib.bidirectional.traversal.iterators] +------------------------------------------------------------------------- + +A class or built-in type ``X`` models the *Bidirectional Traversal +Iterator* concept if the following expressions are valid and respect +the stated semantics. + + +-------------------------------------------------------------------------------------------------------------+ + |Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal Iterator) | + +-----------------------------------------+-------------+-----------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition/Semantics | + +=========================================+=============+=====================================================+ + | ``--r`` | ``X&`` |pre: there exists ``s`` such that ``r == ++s``. | + | | |post: ``s`` is dereferenceable. ``--(++r) == r``. | + | | |``--r == --s`` implies ``r == s``. ``&r == &--r``. | + +-----------------------------------------+-------------+-----------------------------------------------------+ + |``r--`` |convertible |``{ X tmp = r; --r; return tmp; }`` | + | |to ``const | | + | |X&`` | | + +-----------------------------------------+-------------+-----------------------------------------------------+ + | ``traversal_category::type`` | | Convertible to | + | | | ``bidirectional_traversal_iterator_tag`` | + | | | | + +-----------------------------------------+-------------+-----------------------------------------------------+ + + +Random Access Traversal Iterators [lib.random.access.traversal.iterators] +------------------------------------------------------------------------- + +A class or built-in type ``X`` models the *Random Access Traversal +Iterator* concept if the following expressions are valid and respect +the stated semantics. In the table below, ``Distance`` is +``iterator_traits::difference_type`` and ``n`` represents a +constant object of type ``Distance``. + + +--------------------------------------------------------------------------------------------------------------------------------------------+ + | Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal Iterator) | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + | Expression | Return Type | Operational Semantics | Assertion/Note/Pre/Post-condition | + +================================+=======================================+==========================+========================================+ + |``r += n`` | ``X&`` |:: | | + | | | | | + | | | { | | + | | | Distance m = n; | | + | | | if (m >= 0) | | + | | | while (m--) | | + | | | ++r; | | + | | | else | | + | | | while (m++) | | + | | | --r; | | + | | | return r; | | + | | | } | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + | ``a + n``, ``n + a`` | ``X`` |``{ X tmp = a; return tmp | | + | | |+= n; }`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``r -= n`` | ``X&`` |``return r += -n`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a - n`` | ``X`` |``{ X tmp = a; return tmp | | + | | |-= n; }`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``b - a`` |``Distance`` |``a < b ? distance(a,b) : |pre: there exists a value ``n`` of | + | | |-distance(b,a)`` |``Distance`` such that ``a + n == b``. | + | | | |``b == a + (b - a)``. | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a[n]`` |convertible to T |``*(a + n)`` |pre: a is a `readable iterator`_ | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a[n] = v`` |convertible to T |``*(a + n) = v`` |pre: a is a `writable iterator`_ | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a < b`` |convertible to ``bool`` |``b - a > 0`` |``<`` is a total ordering relation | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a > b`` |convertible to ``bool`` |``b < a`` |``>`` is a total ordering relation | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a >= b`` |convertible to ``bool`` |``!(a < b)`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a <= b`` |convertible to ``bool`` |``!(a > b)`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``traversal_category::type`` | | |Convertible to | + | | | |``random_access_traversal_iterator_tag``| + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + + + +Addition to [lib.iterator.synopsis] +=================================== + +:: + + // lib.iterator.traits, traits and tags + template struct access_category; + template struct traversal_category; + + template + struct iterator_tag : /* appropriate old category or categories */ { + typedef AccessTag access; + typedef TraversalTag traversal; + }; + + struct readable_iterator_tag { }; + struct writable_iterator_tag { }; + struct swappable_iterator_tag { }; + struct readable_writable_iterator_tag + : virtual readable_iterator_tag + , virtual writable_iterator_tag + , virtual swappable_iterator_tag { }; + struct readable_lvalue_iterator_tag { }; + struct writable_lvalue_iterator_tag + : virtual public readable_writable_iterator_tag + , virtual public readable_lvalue_iterator_tag { }; + + struct incrementable_iterator_tag { }; + struct single_pass_iterator_tag : incrementable_iterator_tag { }; + struct forward_traversal_tag : single_pass_iterator_tag { }; + struct bidirectional_traversal_tag : forward_traversal_tag { }; + struct random_access_traversal_tag : bidirectional_traversal_tag { }; + + struct null_category_tag { }; + struct input_output_iterator_tag : input_iterator_tag, output_iterator_tag {}; + +Addition to [lib.iterator.traits] +================================= + +The ``iterator_tag`` class template is an iterator category tag that +encodes the access and traversal tags in addition to being compatible +with the original iterator tags. The ``iterator_tag`` class inherits +from one of the original iterator tags according to the following +pseudo-code. + +:: + + inherit-category(access-tag, traversal-tag) = + if (access-tag is convertible to readable_lvalue_iterator_tag) { + if (traversal-tag is convertible to random_access_traversal_tag) + return random_access_iterator_tag; + else if (traversal-tag is convertible to bidirectional_traversal_tag) + return bidirectional_iterator_tag; + else if (traversal-tag is convertible to forward_traversal_tag) + return forward_iterator_tag; + else if (traversal-tag is convertible to single_pass_traversal_tag) + if (access-tag is convertible to writable_iterator_tag) + return input_output_iterator_tag; + else + return input_iterator_tag; + else if (access-tag is convertible to writable_iterator_tag) + return output_iterator_tag; + else + return null_category_tag; + } else if (access-tag is convertible to readable_writable_iterator_tag + and traversal-tag is convertible to single_pass_iterator_tag) + return input_output_iterator_tag; + else if (access-tag is convertible to readable_iterator_tag + and traversal-tag is convertible to single_pass_iterator_tag) + return input_iterator_tag; + else if (access-tag is convertible to writable_iterator_tag + and traversal-tag is convertible to incrementable_iterator_tag) + return output_iterator_tag; + else + return null_category_tag; + + +The ``access_category`` and ``traversal_category`` class templates are +traits classes. For iterators whose +``iterator_traits::iterator_category`` type is ``iterator_tag``, +the ``access_category`` and ``traversal_category`` traits access the +``access`` and ``traversal`` member types within ``iterator_tag``. +For iterators whose ``iterator_traits::iterator_category`` type +is not ``iterator_tag`` and instead is a tag convertible to one of the +original tags, the appropriate traversal and access tags is deduced. +The following pseudo-code describes the algorithm. + +:: + + access-category(Iterator) = + cat = iterator_traits::iterator_category; + if (cat == iterator_tag) + return Access; + else if (cat is convertible to forward_iterator_tag) { + if (iterator_traits::reference is a const reference) + return readable_lvalue_iterator_tag; + else + return writable_lvalue_iterator_tag; + } else if (cat is convertible to input_iterator_tag) + return readable_iterator_tag; + else if (cat is convertible to output_iterator_tag) + return writable_iterator_tag; + else + return null_category_tag; + + traversal-category(Iterator) = + cat = iterator_traits::iterator_category; + if (cat == iterator_tag) + return Traversal; + else if (cat is convertible to random_access_iterator_tag) + return random_access_traversal_tag; + else if (cat is convertible to bidirectional_iterator_tag) + return bidirectional_traversal_tag; + else if (cat is convertible to forward_iterator_tag) + return forward_traversal_tag; + else if (cat is convertible to input_iterator_tag) + return single_pass_iterator_tag; + else if (cat is convertible to output_iterator_tag) + return incrementable_iterator_tag; + else + return null_category_tag; + + +The following specializations provide the access and traversal +category tags for pointer types. + +:: + + template + struct access_category + { + typedef readable_lvalue_iterator_tag type; + }; + template + struct access_category + { + typedef writable_lvalue_iterator_tag type; + }; + + template + struct traversal_category + { + typedef random_access_traversal_tag type; + }; + + + +.. + LocalWords: Abrahams Siek Witt const bool Sutter's WG int UL LI href Lvalue + LocalWords: ReadableIterator WritableIterator SwappableIterator cv pre iter + LocalWords: ConstantLvalueIterator MutableLvalueIterator CopyConstructible TR + LocalWords: ForwardTraversalIterator BidirectionalTraversalIterator lvalue + LocalWords: RandomAccessTraversalIterator dereferenceable Incrementable tmp + LocalWords: incrementable xxx min prev inplace png oldeqnew AccessTag struct + LocalWords: TraversalTag typename lvalues DWA Hmm JGS diff --git a/doc/oldeqnew.png b/doc/oldeqnew.png new file mode 100644 index 0000000000000000000000000000000000000000..30cd1598cb0b5f4cc54a8c600b7d55de7de270d5 GIT binary patch literal 33786 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../../.. $(BOOST) ; \ No newline at end of file diff --git a/example/reverse_iterator.cpp b/example/reverse_iterator.cpp new file mode 100644 index 0000000..ffe6e3d --- /dev/null +++ b/example/reverse_iterator.cpp @@ -0,0 +1,16 @@ +#include +#include +#include +#include +#include + +int main() +{ + int x[] = { 1, 2, 3, 4 }; + boost::reverse_iterator + , std::ptrdiff_t> first(x + 4), last(x); + std::copy(first, last, std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + return 0; +} diff --git a/include/boost/iterator/detail/categories.hpp b/include/boost/iterator/detail/categories.hpp new file mode 100644 index 0000000..48d1e3d --- /dev/null +++ b/include/boost/iterator/detail/categories.hpp @@ -0,0 +1,338 @@ +// (C) Copyright Thomas Witt 2002. 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_DETAIL_CATEGORIES_HPP +# define BOOST_ITERATOR_DETAIL_CATEGORIES_HPP + +# include +# include + +# include + +# include +# include + +# include +# include +# include +# include +# include +# include + +# include + +namespace boost +{ + + // faked new old-style categories needed to make new->old mapping + // work + namespace detail + { + struct null_category_tag {}; + struct input_output_iterator_tag : std::input_iterator_tag, std::output_iterator_tag {}; + } + + // + // Access Categories + // + struct readable_iterator_tag + { + typedef std::input_iterator_tag max_category; + }; + + struct writable_iterator_tag + { + typedef std::output_iterator_tag max_category; + }; + + struct swappable_iterator_tag + { + typedef detail::null_category_tag max_category; + }; + + struct readable_writable_iterator_tag + : virtual readable_iterator_tag + , virtual writable_iterator_tag + , virtual swappable_iterator_tag + { + typedef detail::input_output_iterator_tag max_category; + }; + + struct readable_lvalue_iterator_tag + : virtual readable_iterator_tag + { + typedef std::random_access_iterator_tag max_category; + }; + + struct writable_lvalue_iterator_tag + : virtual public readable_writable_iterator_tag + , virtual public readable_lvalue_iterator_tag + { + typedef std::random_access_iterator_tag max_category; + }; + + // + // Traversal Categories + // + struct incrementable_traversal_tag + { + typedef std::output_iterator_tag max_category; + }; + + struct single_pass_traversal_tag + : incrementable_traversal_tag + { + typedef detail::input_output_iterator_tag max_category; + }; + + struct forward_traversal_tag + : single_pass_traversal_tag + { + typedef std::forward_iterator_tag max_category; + }; + + struct bidirectional_traversal_tag + : forward_traversal_tag + { + typedef std::bidirectional_iterator_tag max_category; + }; + + struct random_access_traversal_tag + : bidirectional_traversal_tag + { + typedef std::random_access_iterator_tag max_category; + }; + + struct error_iterator_tag { }; + + namespace detail + { + // + // Tag detection meta functions + // + + // I bet this is defined somewhere else. Let's wait and see. + struct error_type; + +# ifndef BOOST_NO_IS_CONVERTIBLE + + // True iff T is a tag "derived" from Tag + template + struct is_tag + : mpl::or_< + is_convertible + + // Because we can't actually get forward_iterator_tag to + // derive from input_output_iterator_tag, we need this + // case. + , mpl::and_< + is_convertible + , is_convertible + > + > + {}; + + +# else + template + struct is_tag; +# endif + + // Generate specializations which will allow us to find + // null_category_tag as a minimum old-style category for new-style + // iterators which don't have an actual old-style category. We + // need that so there is a valid base class for all new-style + // iterators. +# define BOOST_OLD_ITERATOR_CATEGORY(category) \ + template <> \ + struct is_tag \ + : mpl::true_ {}; + + BOOST_OLD_ITERATOR_CATEGORY(input_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(output_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(forward_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(bidirectional_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(random_access_iterator_tag) +# undef BOOST_OLD_ITERATOR_CATEGORY + + template <> + struct is_tag + : mpl::true_ + { + }; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct is_tag : mpl::true_ + {}; + +# ifdef BOOST_NO_IS_CONVERTIBLE + // Workarounds for CWPro7 which can't detect derivation at + // compile-time. + + // Fact of life: we can only detect tag refinement relationships + // among predefined tags. + // + // Algorithm: + // is_tag(T,U) -> + // T == U + // || (exists d in derived_from(T) such that is_tag(d, U)) + // + // T == U case is handled above + + // false by default + template + struct is_tag_impl : mpl::false_ + {}; + + // The generalized template dispatches to is_tag_impl because + // is_tag and is_tag are equally specialized. + // This technique simulates making is_tag more-specialized. + template + struct is_tag + : is_tag_impl + {}; + +# define BOOST_ITERATOR_DERIVED_TAG1(base, derived) \ + BOOST_ITERATOR_DERIVED_TAG1_AUX(base, _, derived) + +# define BOOST_ITERATOR_DERIVED_TAG1_AUX(base, underscore, derived) \ + template \ + struct is_tag_impl \ + : is_tag \ + { \ + }; + + // Old-style tag relations + template + struct is_tag_impl + : mpl::or_< + is_tag + , is_tag + > + { + }; + + BOOST_ITERATOR_DERIVED_TAG1(std::output_iterator, detail::input_output_iterator) + BOOST_ITERATOR_DERIVED_TAG1(std::input_iterator, detail::input_output_iterator) + BOOST_ITERATOR_DERIVED_TAG1(detail::input_output_iterator, std::forward_iterator) + BOOST_ITERATOR_DERIVED_TAG1(std::forward_iterator, std::bidirectional_iterator) + BOOST_ITERATOR_DERIVED_TAG1(std::bidirectional_iterator, std::random_access_iterator) + + // Access tag relations + BOOST_ITERATOR_DERIVED_TAG1(readable_lvalue_iterator, writable_lvalue_iterator) + BOOST_ITERATOR_DERIVED_TAG1(swappable_iterator, readable_writable_iterator) + BOOST_ITERATOR_DERIVED_TAG1(readable_writable_iterator, writable_lvalue_iterator) + + template + struct is_tag_impl + : mpl::or_< + is_tag + , is_tag + > + { + }; + + BOOST_ITERATOR_DERIVED_TAG1(writable_iterator, readable_writable_iterator) + + // Traversal tag relations + BOOST_ITERATOR_DERIVED_TAG1(bidirectional_traversal, random_access_traversal) + BOOST_ITERATOR_DERIVED_TAG1(forward_traversal, bidirectional_traversal) + BOOST_ITERATOR_DERIVED_TAG1(single_pass_traversal, forward_traversal) + BOOST_ITERATOR_DERIVED_TAG1(incrementable_traversal, single_pass_traversal) + +# endif // BOOST_NO_IS_CONVERTIBLE workarounds + +# endif // ndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + template + struct known_tag + : mpl::apply_if, mpl::identity, Else> + {}; + + template + struct max_known_traversal_tag + : known_tag< + Tag, random_access_traversal_tag + , known_tag< + Tag, bidirectional_traversal_tag + , known_tag< + Tag, forward_traversal_tag + , known_tag< + Tag, single_pass_traversal_tag + , known_tag< + Tag, incrementable_traversal_tag + , error_iterator_tag + > + > + > + > + > + {}; + + // Doesn't cope with these odd combinations: readable+swappable, + // writable+swappable. That doesn't matter for the sake of + // new-style tag base computation, which is all it's used for + // anyway. + template + struct max_known_access_tag + : known_tag< + Tag, writable_lvalue_iterator_tag + , known_tag< + Tag, readable_lvalue_iterator_tag + , known_tag< + Tag, readable_writable_iterator_tag + , known_tag< + Tag, writable_iterator_tag + , known_tag< + Tag, readable_iterator_tag + , mpl::apply_if< + is_tag + , mpl::identity + , error_iterator_tag + > + > + > + > + > + > + {}; + + // + // Returns the minimum category type or error_type + // if T1 and T2 are unrelated. + // + // For compilers not supporting is_convertible this only + // works with the new boost return and traversal category + // types. The exact boost _types_ are required. No derived types + // will work. + // + // + template + struct minimum_category + : mpl::apply_if< + is_tag + , mpl::identity + , mpl::if_< + is_tag + , T2 + , error_type + > + > + {}; + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + // Deal with ETI + template <> struct minimum_category { typedef minimum_category type; }; +# endif + + } // namespace detail + +} // namespace boost + +#include + +#endif // BOOST_ITERATOR_DETAIL_CATEGORIES_HPP diff --git a/include/boost/iterator/detail/config_def.hpp b/include/boost/iterator/detail/config_def.hpp new file mode 100644 index 0000000..6789d4a --- /dev/null +++ b/include/boost/iterator/detail/config_def.hpp @@ -0,0 +1,104 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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. + +// no include guard multiple inclusion intended + +// +// This is a temporary workaround until the bulk of this is +// available in boost config. +// 23/02/03 thw +// + +#include // for prior +#include + +#define BOOST_ITERATOR_CONFIG_DEF // if you get an error here, you have nested config_def #inclusion. + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ + || BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) \ + || BOOST_WORKAROUND(__MWERKS__, <= 0x3000) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) +# define BOOST_NO_SFINAE // "Substitution Failure Is Not An Error not implemented" + +# if 0 // test code + template + struct bar + { + typedef int type; + }; + + template <> + struct bar + { + }; + + + template + struct foo : bar<(sizeof(T) == 1)> + { + }; + + template + char* f(int, typename foo::type = 0) { return 0; } + + template + int f(...) { return 0; } + + char* x = f(0); + int y = f(0); + + int main() + { + return 0; + } +# endif + +#endif + +#if BOOST_WORKAROUND(__MWERKS__, <=0x2407) +# define BOOST_NO_IS_CONVERTIBLE // "is_convertible doesn't work for simple types" +#endif + +#if BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(3)) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) +# define BOOST_NO_IS_CONVERTIBLE_TEMPLATE // The following program fails to compile: + +# if 0 // test code + template + struct foo + { + foo(T); + + template + foo(foo const& other) : p(other.p) { } + + T p; + }; + + bool x = boost::is_convertible, foo >::value; +# endif + +#endif + +#if BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \ + || BOOST_WORKAROUND(__MWERKS__, <= 0x2407) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) +# define BOOST_ITERATOR_NO_MPL_AUX_HAS_XXX // "MPL's has_xxx facility doesn't work" +#endif + +#if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_IS_CONVERTIBLE_TEMPLATE) +# define BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY +#endif + +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +# define BOOST_ARG_DEPENDENT_TYPENAME typename +# else +# define BOOST_ARG_DEPENDENT_TYPENAME +# endif + +// no include guard multiple inclusion intended diff --git a/include/boost/iterator/detail/config_undef.hpp b/include/boost/iterator/detail/config_undef.hpp new file mode 100644 index 0000000..f58df62 --- /dev/null +++ b/include/boost/iterator/detail/config_undef.hpp @@ -0,0 +1,26 @@ +// (C) Copyright Thomas Witt 2002. +// 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. + +// no include guard multiple inclusion intended + +// +// This is a temporary workaround until the bulk of this is +// available in boost config. +// 23/02/03 thw +// + +#undef BOOST_NO_SFINAE +#undef BOOST_NO_IS_CONVERTIBLE +#undef BOOST_NO_IS_CONVERTIBLE_TEMPLATE +#undef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY +#undef BOOST_ARG_DEPENDENT_TYPENAME + +#ifdef BOOST_ITERATOR_CONFIG_DEF +# undef BOOST_ITERATOR_CONFIG_DEF +#else +# error missing or nested #include config_def +#endif diff --git a/include/boost/iterator/detail/enable_if.hpp b/include/boost/iterator/detail/enable_if.hpp new file mode 100644 index 0000000..d939fbb --- /dev/null +++ b/include/boost/iterator/detail/enable_if.hpp @@ -0,0 +1,88 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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_ENABLE_IF_23022003THW_HPP +#define BOOST_ENABLE_IF_23022003THW_HPP + +#include +#include + +#include + +// +// Boost iterators uses its own enable_if cause we need +// special semantics for deficient compilers. +// 23/02/03 thw +// + +namespace boost +{ + + namespace detail + { + // + // Base machinery for all kinds of enable if + // + template + struct enabled + { + template + struct base + { + typedef T type; + }; + }; + + // + // For compilers that don't support "Substitution Failure Is Not An Error" + // enable_if falls back to always enabled. See comments + // on operator implementation for consequences. + // + template<> + struct enabled + { + template + struct base + { +#ifdef BOOST_NO_SFINAE + + typedef T type; + + // This way to do it would give a nice error message containing + // invalid overload, but has the big disadvantage that + // there is no reference to user code in the error message. + // + // struct invalid_overload; + // typedef invalid_overload type; + // +#endif + }; + }; + + + template + struct enable_if +# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE) + : enabled<(Cond::value)>::template base +# else + : mpl::identity +# endif + { +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + typedef Return type; +# endif + }; + + } // namespace detail + +} // namespace boost + +#include + +#endif // BOOST_ENABLE_IF_23022003THW_HPP From 471689111752d42301f8ab697719728adb667dc6 Mon Sep 17 00:00:00 2001 From: Joel de Guzman Date: Mon, 7 Jul 2003 14:26:16 +0000 Subject: [PATCH 167/265] Move from boost-sandbox [SVN r18960] --- test/Jamfile | 14 ++ test/concept_tests.cpp | 174 +++++++++++++++++ test/counting_iterator_test.cpp | 295 +++++++++++++++++++++++++++++ test/filter_iterator_test.cpp | 87 +++++++++ test/indirect_iterator_test.cpp | 253 +++++++++++++++++++++++++ test/interoperable_fail.cpp | 22 +++ test/is_convertible_fail.cpp | 11 ++ test/iterator_adaptor_cc.cpp | 40 ++++ test/iterator_adaptor_test.cpp | 261 +++++++++++++++++++++++++ test/iterator_archetype_cc.cpp | 25 +++ test/permutation_iterator_test.cpp | 101 ++++++++++ test/reverse_iterator_test.cpp | 97 ++++++++++ test/static_assert_same.hpp | 31 +++ test/transform_iterator_test.cpp | 248 ++++++++++++++++++++++++ test/unit_tests.cpp | 103 ++++++++++ 15 files changed, 1762 insertions(+) create mode 100644 test/Jamfile create mode 100644 test/concept_tests.cpp create mode 100644 test/counting_iterator_test.cpp create mode 100644 test/filter_iterator_test.cpp create mode 100644 test/indirect_iterator_test.cpp create mode 100644 test/interoperable_fail.cpp create mode 100644 test/is_convertible_fail.cpp create mode 100644 test/iterator_adaptor_cc.cpp create mode 100644 test/iterator_adaptor_test.cpp create mode 100644 test/iterator_archetype_cc.cpp create mode 100644 test/permutation_iterator_test.cpp create mode 100644 test/reverse_iterator_test.cpp create mode 100644 test/static_assert_same.hpp create mode 100644 test/transform_iterator_test.cpp create mode 100644 test/unit_tests.cpp diff --git a/test/Jamfile b/test/Jamfile new file mode 100644 index 0000000..75d3d1f --- /dev/null +++ b/test/Jamfile @@ -0,0 +1,14 @@ +SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; +include testing.jam ; +run unit_tests.cpp ; +run concept_tests.cpp ; +run iterator_adaptor_cc.cpp ; +run iterator_adaptor_test.cpp ; +compile iterator_archetype_cc.cpp ; +run transform_iterator_test.cpp ; +run indirect_iterator_test.cpp ; +run filter_iterator_test.cpp ; +run reverse_iterator_test.cpp ; +run counting_iterator_test.cpp ; +run is_convertible_fail.cpp ; # test changed to expected success, so that we catch compilation failures. +compile-fail interoperable_fail.cpp ; diff --git a/test/concept_tests.cpp b/test/concept_tests.cpp new file mode 100644 index 0000000..64d2c05 --- /dev/null +++ b/test/concept_tests.cpp @@ -0,0 +1,174 @@ +// (C) Copyright Jeremy Siek 2002. 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. + +#include +#include +#include // remove +#include +#include "static_assert_same.hpp" // remove + +struct new_iterator + : public boost::iterator< boost::iterator_tag< + boost::writable_lvalue_iterator_tag + , boost::random_access_traversal_tag>, int> +{ + int& operator*() const { return *m_x; } + new_iterator& operator++() { return *this; } + new_iterator operator++(int) { return *this; } + new_iterator& operator--() { return *this; } + new_iterator operator--(int) { return *this; } + new_iterator& operator+=(std::ptrdiff_t) { return *this; } + new_iterator operator+(std::ptrdiff_t) { return *this; } + new_iterator& operator-=(std::ptrdiff_t) { return *this; } + std::ptrdiff_t operator-(const new_iterator&) const { return 0; } + new_iterator operator-(std::ptrdiff_t) const { return *this; } + bool operator==(const new_iterator&) const { return false; } + bool operator!=(const new_iterator&) const { return false; } + bool operator<(const new_iterator&) const { return false; } + int* m_x; +}; +new_iterator operator+(std::ptrdiff_t, new_iterator x) { return x; } + +struct old_iterator + : public boost::iterator +{ + int& operator*() const { return *m_x; } + old_iterator& operator++() { return *this; } + old_iterator operator++(int) { return *this; } + old_iterator& operator--() { return *this; } + old_iterator operator--(int) { return *this; } + old_iterator& operator+=(std::ptrdiff_t) { return *this; } + old_iterator operator+(std::ptrdiff_t) { return *this; } + old_iterator& operator-=(std::ptrdiff_t) { return *this; } + old_iterator operator-(std::ptrdiff_t) const { return *this; } + std::ptrdiff_t operator-(const old_iterator&) const { return 0; } + bool operator==(const old_iterator&) const { return false; } + bool operator!=(const old_iterator&) const { return false; } + bool operator<(const old_iterator&) const { return false; } + int* m_x; +}; +old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; } + +struct my_writable_lvalue_iterator_tag +{ + operator boost::writable_lvalue_iterator_tag() const; +}; + +struct my_single_pass_traversal_tag +{ + operator boost::single_pass_traversal_tag() const; +}; + +void test_tag_convertibility() +{ + // This set of tests is by no means complete. + + // Test that this is an input/output iterator +#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + { + typedef boost::iterator_tag< + boost::writable_lvalue_iterator_tag + , boost::single_pass_traversal_tag + > tag; + + BOOST_STATIC_ASSERT(( + boost::is_convertible::value + )); + BOOST_STATIC_ASSERT(( + boost::is_convertible::value + )); + BOOST_STATIC_ASSERT(( + !boost::is_convertible::value + )); + } + + // Test that it's possible to build new sub-tags without + // derivation. Convertibility should be enough + { + typedef boost::iterator_tag< + my_writable_lvalue_iterator_tag + , my_single_pass_traversal_tag + > tag; + + BOOST_STATIC_ASSERT(( + boost::is_convertible::value + )); + BOOST_STATIC_ASSERT(( + boost::is_convertible::value + )); + BOOST_STATIC_ASSERT(( + !boost::is_convertible::value + )); + } + + // Test that a single-pass readable lvalue iterator is only an + // input iterator. Requires special case handling in + // categories.hpp + { + typedef boost::iterator_tag< + boost::readable_lvalue_iterator_tag + , boost::single_pass_traversal_tag + > tag; + BOOST_STATIC_ASSERT(( + boost::is_convertible::value + )); + BOOST_STATIC_ASSERT(( + !boost::is_convertible::value + )); + BOOST_STATIC_ASSERT(( + !boost::is_convertible::value + )); + } +#endif +} + +int +main() +{ + test_tag_convertibility(); + + typedef boost::iterator_tag< boost::writable_lvalue_iterator_tag, boost::random_access_traversal_tag > tag; + + // BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator::value)); + int test = static_assert_same::value; + test = static_assert_same::value; + + // BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator::value)); + test = static_assert_same::value; + test = static_assert_same::value; + + typedef boost::traversal_category::type traversal_category; + + // BOOST_STATIC_ASSERT(boost::detail::has_traversal::value); + BOOST_STATIC_ASSERT(boost::detail::is_new_iterator_tag::value); + + + test = static_assert_same::value; + (void)test; + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + boost::function_requires< + boost_concepts::WritableLvalueIteratorConcept >(); + boost::function_requires< + boost_concepts::RandomAccessTraversalConcept >(); + + boost::function_requires< + boost_concepts::ReadableLvalueIteratorConcept >(); + boost::function_requires< + boost_concepts::RandomAccessTraversalConcept >(); +#endif + + boost::function_requires< + boost_concepts::WritableLvalueIteratorConcept >(); + boost::function_requires< + boost_concepts::RandomAccessTraversalConcept >(); + + boost::function_requires< + boost_concepts::WritableLvalueIteratorConcept >(); + boost::function_requires< + boost_concepts::RandomAccessTraversalConcept >(); + return 0; +} diff --git a/test/counting_iterator_test.cpp b/test/counting_iterator_test.cpp new file mode 100644 index 0000000..fbfe70b --- /dev/null +++ b/test/counting_iterator_test.cpp @@ -0,0 +1,295 @@ +// (C) Copyright David Abrahams 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. +// +// See http://www.boost.org for most recent version including documentation. +// +// Revision History +// 16 Feb 2001 Added a missing const. Made the tests run (somewhat) with +// plain MSVC again. (David Abrahams) +// 11 Feb 2001 #if 0'd out use of counting_iterator on non-numeric types in +// MSVC without STLport, so that the other tests may proceed +// (David Abrahams) +// 04 Feb 2001 Added use of iterator_tests.hpp (David Abrahams) +// 28 Jan 2001 Removed not_an_iterator detritus (David Abrahams) +// 24 Jan 2001 Initial revision (David Abrahams) + +#include + +#ifdef __BORLANDC__ // Borland mis-detects our custom iterators +# pragma warn -8091 // template argument ForwardIterator passed to '...' is a output iterator +# pragma warn -8071 // Conversion may lose significant digits (due to counting_iterator += n). +#endif + +#ifdef BOOST_MSVC +# pragma warning(disable:4786) // identifier truncated in debug info +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#ifndef __BORLANDC__ +# include +#endif +#include +#include +#include +#ifndef BOOST_NO_SLIST +# include +#endif + + +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +template +struct signed_assert_nonnegative +{ + static void test(T x) { assert(x >= 0); } +}; + +template +struct unsigned_assert_nonnegative +{ + static void test(T x) {} +}; + +template +struct assert_nonnegative + : boost::mpl::if_c< + std::numeric_limits::is_signed + , signed_assert_nonnegative + , unsigned_assert_nonnegative + >::type +{ +}; +#endif + +// Special tests for RandomAccess CountingIterators. +template +void category_test( + CountingIterator start, + CountingIterator finish, + Value, + std::random_access_iterator_tag) +{ + typedef typename + boost::detail::iterator_traits::difference_type + difference_type; + difference_type distance = boost::detail::distance(start, finish); + + // Pick a random position internal to the range + difference_type offset = (unsigned)rand() % distance; + +#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + assert(offset >= 0); +#else + assert_nonnegative::test(offset); +#endif + + CountingIterator internal = start; + std::advance(internal, offset); + + // Try some binary searches on the range to show that it's ordered + assert(std::binary_search(start, finish, *internal)); + + // #including tuple crashed borland, so I had to give up on tie(). + std::pair xy( + std::equal_range(start, finish, *internal)); + CountingIterator x = xy.first, y = xy.second; + + assert(boost::detail::distance(x, y) == 1); + + // Show that values outside the range can't be found + assert(!std::binary_search(start, boost::prior(finish), *finish)); + + // Do the generic random_access_iterator_test + typedef typename CountingIterator::value_type value_type; + std::vector v; + for (value_type z = *start; !(z == *finish); ++z) + v.push_back(z); + + // Note that this test requires a that the first argument is + // dereferenceable /and/ a valid iterator prior to the first argument + boost::random_access_iterator_test(start, v.size(), v.begin()); +} + +// Special tests for bidirectional CountingIterators +template +void category_test(CountingIterator start, Value v1, std::bidirectional_iterator_tag) +{ + Value v2 = v1; + ++v2; + + // Note that this test requires a that the first argument is + // dereferenceable /and/ a valid iterator prior to the first argument + boost::bidirectional_iterator_test(start, v1, v2); +} + +template +void category_test(CountingIterator start, CountingIterator finish, Value v1, std::forward_iterator_tag) +{ + Value v2 = v1; + ++v2; + if (finish != start && finish != boost::next(start)) + boost::forward_readable_iterator_test(start, finish, v1, v2); +} + +template +void test_aux(CountingIterator start, CountingIterator finish, Value v1) +{ + typedef typename CountingIterator::iterator_category category; + typedef typename CountingIterator::value_type value_type; + + // If it's a RandomAccessIterator we can do a few delicate tests + category_test(start, finish, v1, category()); + + // Okay, brute force... + for (CountingIterator p = start + ; p != finish && boost::next(p) != finish + ; ++p) + { + assert(boost::next(*p) == *boost::next(p)); + } + + // prove that a reference can be formed to these values + typedef typename CountingIterator::value_type value; + const value* q = &*start; + (void)q; // suppress unused variable warning +} + +template +void test(Incrementable start, Incrementable finish) +{ + test_aux(boost::make_counting_iterator(start), boost::make_counting_iterator(finish), start); +} + +template +void test_integer(Integer* = 0) // default arg works around MSVC bug +{ + Integer start = 0; + Integer finish = 120; + test(start, finish); +} + +template +void test_integer3(Integer* = 0, Category* = 0, Difference* = 0) // default arg works around MSVC bug +{ + Integer start = 0; + Integer finish = 120; + typedef boost::counting_iterator iterator; + test_aux(iterator(start), iterator(finish), start); +} + +template +void test_container(Container* = 0) // default arg works around MSVC bug +{ + Container c(1 + (unsigned)rand() % 1673); + + const typename Container::iterator start = c.begin(); + + // back off by 1 to leave room for dereferenceable value at the end + typename Container::iterator finish = start; + std::advance(finish, c.size() - 1); + + test(start, finish); + + typedef typename Container::const_iterator const_iterator; + test(const_iterator(start), const_iterator(finish)); +} + +class my_int1 { +public: + my_int1() { } + my_int1(int x) : m_int(x) { } + my_int1& operator++() { ++m_int; return *this; } + bool operator==(const my_int1& x) const { return m_int == x.m_int; } +private: + int m_int; +}; + +class my_int2 { +public: + typedef void value_type; + typedef void pointer; + typedef void reference; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + my_int2() { } + my_int2(int x) : m_int(x) { } + my_int2& operator++() { ++m_int; return *this; } + my_int2& operator--() { --m_int; return *this; } + bool operator==(const my_int2& x) const { return m_int == x.m_int; } +private: + int m_int; +}; + +class my_int3 { +public: + typedef void value_type; + typedef void pointer; + typedef void reference; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; + + my_int3() { } + my_int3(int x) : m_int(x) { } + my_int3& operator++() { ++m_int; return *this; } + my_int3& operator+=(std::ptrdiff_t n) { m_int += n; return *this; } + std::ptrdiff_t operator-(const my_int3& x) const { return m_int - x.m_int; } + my_int3& operator--() { --m_int; return *this; } + bool operator==(const my_int3& x) const { return m_int == x.m_int; } + bool operator!=(const my_int3& x) const { return m_int != x.m_int; } + bool operator<(const my_int3& x) const { return m_int < x.m_int; } +private: + int m_int; +}; + +int main() +{ + // Test the built-in integer types. + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); +#if defined(BOOST_HAS_LONG_LONG) + test_integer(); + test_integer(); +#endif + + // Test user-defined type. + + test_integer3(); + test_integer(); + test_integer(); + + // Some tests on container iterators, to prove we handle a few different categories + test_container >(); + test_container >(); +# ifndef BOOST_NO_SLIST + test_container >(); +# endif + + // Also prove that we can handle raw pointers. + int array[2000]; + test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1)); + + return 0; +} diff --git a/test/filter_iterator_test.cpp b/test/filter_iterator_test.cpp new file mode 100644 index 0000000..16cd894 --- /dev/null +++ b/test/filter_iterator_test.cpp @@ -0,0 +1,87 @@ +// Copyright David Abrahams 2003. 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. + +#include +#include +#include + +#include +#include + +using boost::dummyT; + +struct one_or_four +{ + bool operator()(dummyT x) const + { + return x.foo() == 1 || x.foo() == 4; + } +}; + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost { namespace detail +{ + template<> struct iterator_traits + : ptr_iter_traits {}; +}} +#endif + +template struct undefined; + +// Test filter iterator +int main() +{ + dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), + dummyT(3), dummyT(4), dummyT(5) }; + const int N = sizeof(array)/sizeof(dummyT); + + typedef boost::filter_iterator filter_iter; + + boost::bidirectional_readable_iterator_test( + filter_iter(one_or_four(), array, array+N) + , dummyT(1), dummyT(4)); + + BOOST_STATIC_ASSERT(( + !boost::detail::is_tag< + boost::random_access_traversal_tag + , boost::traversal_category::type + >::value + )); + + //# endif + + // On compilers not supporting partial specialization, we can do more type + // deduction with deque iterators than with pointers... unless the library + // is broken ;-( + std::deque array2; + std::copy(array+0, array+N, std::back_inserter(array2)); + boost::bidirectional_readable_iterator_test( + boost::make_filter_iterator(one_or_four(), array2.begin(), array2.end()), + dummyT(1), dummyT(4)); + + boost::bidirectional_readable_iterator_test( + boost::make_filter_iterator(one_or_four(), array2.begin(), array2.end()), + dummyT(1), dummyT(4)); + + boost::bidirectional_readable_iterator_test( + boost::make_filter_iterator( + one_or_four() + , boost::make_reverse_iterator(array2.end()) + , boost::make_reverse_iterator(array2.begin()) + ), + dummyT(4), dummyT(1)); + + boost::bidirectional_readable_iterator_test( + filter_iter(array+0, array+N), + dummyT(1), dummyT(4)); + + boost::bidirectional_readable_iterator_test( + filter_iter(one_or_four(), array, array + N), + dummyT(1), dummyT(4)); + + std::cout << "test successful " << std::endl; + return 0; +} diff --git a/test/indirect_iterator_test.cpp b/test/indirect_iterator_test.cpp new file mode 100644 index 0000000..43fa4ae --- /dev/null +++ b/test/indirect_iterator_test.cpp @@ -0,0 +1,253 @@ +// (C) Copyright Jeremy Siek 1999. 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 +// 22 Nov 2002 Thomas Witt +// Added interoperability check. +// 08 Mar 2001 Jeremy Siek +// Moved test of indirect iterator into its own file. It to +// to be in iterator_adaptor_test.cpp. + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#if !defined(__SGI_STL_PORT) \ + && (defined(BOOST_MSVC_STD_ITERATOR) \ + || BOOST_WORKAROUND(_CPPLIB_VER, <= 310) \ + || BOOST_WORKAROUND(__GNUC__, <= 2)) + +// std container random-access iterators don't support mutable/const +// interoperability (but may support const/mutable interop). +# define NO_MUTABLE_CONST_STD_DEQUE_ITERATOR_INTEROPERABILITY +# define NO_MUTABLE_CONST_STD_SET_ITERATOR_INTEROPERABILITY + +#endif + +#if defined(BOOST_MSVC_STD_ITERATOR) \ +|| defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +// No working iterator_traits implementation, so we must use deque +# define RA_CONTAINER std::deque +# include + +# ifdef NO_MUTABLE_CONST_STD_DEQUE_ITERATOR_INTEROPERABILITY +# define NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY +# endif + +#else + +# define RA_CONTAINER std::vector +# include + +#endif + +struct my_iterator_tag : public std::random_access_iterator_tag { }; + +using boost::dummyT; + +typedef RA_CONTAINER storage; +typedef RA_CONTAINER pointer_ra_container; +typedef std::set iterator_set; + +template +struct indirect_iterator_pair_generator +{ + typedef boost::indirect_iterator iterator; + + typedef boost::indirect_iterator< + typename Container::iterator + , typename iterator::value_type const + > const_iterator; +}; + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost { namespace detail +{ + template<> struct iterator_traits + : ptr_iter_traits {}; + + template<> struct iterator_traits + : ptr_iter_traits {}; + + template<> struct iterator_traits + : ptr_iter_traits {}; + + template<> struct iterator_traits + : ptr_iter_traits {}; + + template<> struct iterator_traits + : ptr_iter_traits {}; + + template<> struct iterator_traits + : ptr_iter_traits {}; + + template<> struct iterator_traits + : ptr_iter_traits {}; +}} +#endif + + +void more_indirect_iterator_tests() +{ +# if 0 + storage store(1000); + std::generate(store.begin(), store.end(), rand); + + pointer_ra_container ptr_ra_container; + iterator_set iter_set; + + for (storage::iterator p = store.begin(); p != store.end(); ++p) + { + ptr_ra_container.push_back(&*p); + iter_set.insert(p); + } + + typedef indirect_iterator_pair_generator indirect_ra_container; + + indirect_ra_container::iterator db(ptr_ra_container.begin()); + indirect_ra_container::iterator de(ptr_ra_container.end()); + assert(static_cast(de - db) == store.size()); + assert(db + store.size() == de); + indirect_ra_container::const_iterator dci = db; + + assert(dci == db); + +#ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY + assert(db == dci); +#endif + + assert(dci != de); + assert(dci < de); + assert(dci <= de); + +#ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY + assert(de >= dci); + assert(de > dci); +#endif + + dci = de; + assert(dci == de); + + boost::random_access_iterator_test(db + 1, store.size() - 1, boost::next(store.begin())); + + *db = 999; + assert(store.front() == 999); + + // Borland C++ is getting very confused about the typedefs here + typedef boost::indirect_iterator indirect_set_iterator; + typedef boost::indirect_iterator< + iterator_set::iterator + , iterator_set::iterator::value_type const + > const_indirect_set_iterator; + + indirect_set_iterator sb(iter_set.begin()); + indirect_set_iterator se(iter_set.end()); + const_indirect_set_iterator sci(iter_set.begin()); + assert(sci == sb); + +# ifndef NO_MUTABLE_CONST_STD_SET_ITERATOR_INTEROPERABILITY + assert(se != sci); +# endif + + assert(sci != se); + sci = se; + assert(sci == se); + + *boost::prior(se) = 888; + assert(store.back() == 888); + assert(std::equal(sb, se, store.begin())); + + boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]); + assert(std::equal(db, de, store.begin())); +#endif +} + +int +main() +{ + dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), + dummyT(3), dummyT(4), dummyT(5) }; + const int N = sizeof(array)/sizeof(dummyT); + + typedef RA_CONTAINER > shared_t; + shared_t shared; + + // Concept checks + { + typedef boost::indirect_iterator iter_t; + + BOOST_STATIC_ASSERT( + boost::detail::has_element_type< + boost::shared_ptr + // std::iterator_traits::value_type + >::value + ); + + typedef boost::indirect_iterator< + shared_t::iterator + , boost::iterator_value::type const + > c_iter_t; + +# ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY + boost::function_requires< boost_concepts::InteroperableConcept >(); +# endif + } + + // Test indirect_iterator_generator + { + for (int jj = 0; jj < N; ++jj) + shared.push_back(boost::shared_ptr(new dummyT(jj))); + + dummyT* ptr[N]; + for (int k = 0; k < N; ++k) + ptr[k] = array + k; + + typedef boost::indirect_iterator indirect_iterator; + + typedef boost::indirect_iterator + const_indirect_iterator; + + indirect_iterator i(ptr); + boost::random_access_iterator_test(i, N, array); + + boost::random_access_iterator_test( + boost::indirect_iterator(shared.begin()) + , N, array); + + boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array); + + // check operator-> + assert((*i).m_x == i->foo()); + + const_indirect_iterator j(ptr); + boost::random_access_iterator_test(j, N, array); + + + dummyT const*const* const_ptr = ptr; + boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array); + + boost::const_nonconst_iterator_test(i, ++j); + + more_indirect_iterator_tests(); + } + std::cout << "test successful " << std::endl; + return 0; +} diff --git a/test/interoperable_fail.cpp b/test/interoperable_fail.cpp new file mode 100644 index 0000000..d3d869d --- /dev/null +++ b/test/interoperable_fail.cpp @@ -0,0 +1,22 @@ +// Copyright Thomas Witt 2003. 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. +#include +#include +#include +#include +#include + +int main() +{ + { + typedef boost::reverse_iterator::iterator> rev_iter; + typedef boost::indirect_iterator::iterator> ind_iter; + + ind_iter() == rev_iter(); + } + + return boost::exit_success; +} diff --git a/test/is_convertible_fail.cpp b/test/is_convertible_fail.cpp new file mode 100644 index 0000000..7d3c9b1 --- /dev/null +++ b/test/is_convertible_fail.cpp @@ -0,0 +1,11 @@ +#include +#include + +int main() +{ + typedef boost::reverse_iterator rev_iter1; + typedef boost::reverse_iterator rev_iter2; + + return boost::is_convertible::value + ? boost::exit_failure : boost::exit_success; +} diff --git a/test/iterator_adaptor_cc.cpp b/test/iterator_adaptor_cc.cpp new file mode 100644 index 0000000..e08eabd --- /dev/null +++ b/test/iterator_adaptor_cc.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost { namespace detail +{ + template<> struct iterator_traits + : ptr_iter_traits {}; + + template<> struct iterator_traits + : ptr_iter_traits {}; +}} +#endif + +int main() +{ + { + typedef boost::reverse_iterator rev_iter; + typedef boost::reverse_iterator c_rev_iter; + + boost::function_requires< boost_concepts::WritableLvalueIteratorConcept >(); + boost::function_requires< boost_concepts::RandomAccessTraversalConcept >(); + boost::function_requires< boost::RandomAccessIteratorConcept >(); + boost::function_requires< boost_concepts::InteroperableConcept >(); + } + { + typedef boost::reverse_iterator::iterator> rev_iter; + typedef boost::reverse_iterator::const_iterator> c_rev_iter; + + boost::function_requires< boost_concepts::ReadableLvalueIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + boost::function_requires< boost::BidirectionalIteratorConcept >(); + boost::function_requires< boost_concepts::InteroperableConcept >(); + } + + return boost::exit_success; +} diff --git a/test/iterator_adaptor_test.cpp b/test/iterator_adaptor_test.cpp new file mode 100644 index 0000000..32edd85 --- /dev/null +++ b/test/iterator_adaptor_test.cpp @@ -0,0 +1,261 @@ +// (C) Copyright Thomas Witt 2003. 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. + +// See http://www.boost.org for most recent version including documentation. + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "static_assert_same.hpp" + +struct my_iterator_tag : public std::random_access_iterator_tag { }; + +using boost::dummyT; + + +struct mult_functor { + typedef int result_type; + typedef int argument_type; + // Functors used with transform_iterator must be + // DefaultConstructible, as the transform_iterator must be + // DefaultConstructible to satisfy the requirements for + // TrivialIterator. + mult_functor() { } + mult_functor(int aa) : a(aa) { } + int operator()(int b) const { return a * b; } + int a; +}; + +template +struct select1st_ + : public std::unary_function +{ + const typename Pair::first_type& operator()(const Pair& x) const { + return x.first; + } + typename Pair::first_type& operator()(Pair& x) const { + return x.first; + } +}; + +struct one_or_four { + bool operator()(dummyT x) const { + return x.foo() == 1 || x.foo() == 4; + } +}; + +typedef std::deque storage; +typedef std::deque pointer_deque; +typedef std::set iterator_set; + +template struct foo; + +void blah(int) { } + +struct my_gen +{ + typedef int result_type; + my_gen() : n(0) { } + int operator()() { return ++n; } + int n; +}; + +template +struct ptr_iterator + : boost::iterator_adaptor< + ptr_iterator + , V* + , V + , std::random_access_iterator_tag +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + , V& +#endif + > +{ +private: + typedef boost::iterator_adaptor< + ptr_iterator + , V* + , V + , std::random_access_iterator_tag +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + , V& +#endif + > super_t; + +public: + ptr_iterator() { } + ptr_iterator(V* d) : super_t(d) { } + + template + ptr_iterator( + const ptr_iterator& x + , typename boost::enable_if_convertible::type* = 0 + ) + : super_t(x.base()) + {} +}; + +template +struct fwd_iterator + : boost::iterator_adaptor< + fwd_iterator + , boost::forward_iterator_archetype + > +{ +private: + typedef boost::iterator_adaptor< + fwd_iterator + , boost::forward_iterator_archetype + > super_t; + +public: + fwd_iterator() { } + fwd_iterator(boost::forward_iterator_archetype d) : super_t(d) { } +}; + +template +struct in_iterator + : boost::iterator_adaptor< + in_iterator + , boost::input_iterator_archetype + > +{ +private: + typedef boost::iterator_adaptor< + in_iterator + , boost::input_iterator_archetype + > super_t; + +public: + in_iterator() { } + in_iterator(boost::input_iterator_archetype d) : super_t(d) { } +}; + +template +struct constant_iterator + : boost::iterator_adaptor< + constant_iterator + , Iter + , typename std::iterator_traits::value_type const + > +{ + typedef boost::iterator_adaptor< + constant_iterator + , Iter + , typename std::iterator_traits::value_type const + > base_t; + + constant_iterator() {} + constant_iterator(Iter it) + : base_t(it) {} +}; + +int +main() +{ + dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), + dummyT(3), dummyT(4), dummyT(5) }; + const int N = sizeof(array)/sizeof(dummyT); + + // sanity check, if this doesn't pass the test is buggy + boost::random_access_iterator_test(array, N, array); + + // Test the iterator_adaptor + { + ptr_iterator i(array); + boost::random_access_iterator_test(i, N, array); + + ptr_iterator j(array); + boost::random_access_iterator_test(j, N, array); + boost::const_nonconst_iterator_test(i, ++j); + } + + int test; + // Test the iterator_traits + { + // Test computation of defaults + typedef ptr_iterator Iter1; + // don't use std::iterator_traits here to avoid VC++ problems + test = static_assert_same::value; + test = static_assert_same::value; + test = static_assert_same::value; + test = static_assert_same::value; +#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + BOOST_STATIC_ASSERT((boost::is_convertible::value)); +#endif + } + + { + // Test computation of default when the Value is const + typedef ptr_iterator Iter1; + test = static_assert_same::value; + test = static_assert_same::value; + test = static_assert_same::value; test = static_assert_same::value; + } + + { + // Test constant iterator idiom + typedef ptr_iterator BaseIter; + typedef constant_iterator Iter; + + test = static_assert_same::value; + test = static_assert_same::value; + test = static_assert_same::value; + + test = static_assert_same::value; + test = static_assert_same::value; + } + + // Test the iterator_adaptor + { + ptr_iterator i(array); + boost::random_access_iterator_test(i, N, array); + + ptr_iterator j(array); + boost::random_access_iterator_test(j, N, array); + boost::const_nonconst_iterator_test(i, ++j); + } + + // check operator-> with a forward iterator + { + boost::forward_iterator_archetype forward_iter; + + typedef fwd_iterator adaptor_type; + + adaptor_type i(forward_iter); + int zero = 0; + if (zero) // don't do this, just make sure it compiles + assert((*i).m_x == i->foo()); + } + + // check operator-> with an input iterator + { + boost::input_iterator_archetype input_iter; + typedef in_iterator adaptor_type; + adaptor_type i(input_iter); + int zero = 0; + if (zero) // don't do this, just make sure it compiles + assert((*i).m_x == i->foo()); + } + + std::cout << "test successful " << std::endl; + (void)test; + return 0; +} diff --git a/test/iterator_archetype_cc.cpp b/test/iterator_archetype_cc.cpp new file mode 100644 index 0000000..1edf5e5 --- /dev/null +++ b/test/iterator_archetype_cc.cpp @@ -0,0 +1,25 @@ +// +// Copyright Thomas Witt 2003. 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. +// +#include +#include +#include +#include + +int main() +{ + { + typedef boost::iterator_archetype iter; + + boost::function_requires< boost_concepts::WritableLvalueIteratorConcept >(); + boost::function_requires< boost_concepts::RandomAccessTraversalConcept >(); + } + return 0; // keep msvc happy +} + diff --git a/test/permutation_iterator_test.cpp b/test/permutation_iterator_test.cpp new file mode 100644 index 0000000..0b05ba2 --- /dev/null +++ b/test/permutation_iterator_test.cpp @@ -0,0 +1,101 @@ +// (C) Copyright Toon Knapen 2001. +// (C) Copyright Roland Richter 2003. +// 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. + +#include +#include + +#include + +#include +#include + +#include + + +void permutation_test() +{ + // Example taken from documentation of old permutation_iterator. + typedef std::vector< int > element_range_type; + typedef std::list< int > index_type; + + const int element_range_size = 10; + const int index_size = 4; + + element_range_type elements( element_range_size ); + for( element_range_type::iterator el_it = elements.begin(); el_it != elements.end(); ++el_it ) + { *el_it = std::distance(elements.begin(), el_it); } + + index_type indices( index_size ); + for( index_type::iterator i_it = indices.begin(); i_it != indices.end(); ++i_it ) + { *i_it = element_range_size - index_size + std::distance(indices.begin(), i_it); } + std::reverse( indices.begin(), indices.end() ); + +#ifdef BOOST_MSVC + + typedef boost::permutation_iterator< element_range_type::iterator + , index_type::iterator + , boost::use_default + , boost::use_default + , element_range_type::reference > permutation_type; + + permutation_type begin( elements.begin(), indices.begin() ); + permutation_type it = begin; + permutation_type end( elements.begin(), indices.end() ); + +#else + + typedef boost::permutation_iterator< element_range_type::iterator, index_type::iterator > permutation_type; + permutation_type begin = boost::make_permutation_iterator( elements.begin(), indices.begin() ); + permutation_type it = begin; + permutation_type end = boost::make_permutation_iterator( elements.begin(), indices.end() ); + +#endif + + BOOST_CHECK( it == begin ); + BOOST_CHECK( it != end ); + + BOOST_CHECK( std::distance( begin, end ) == index_size ); + + for( index_type::iterator i_it = indices.begin(); it != end; ++i_it, ++it ) + { + BOOST_CHECK( *it == elements[ *i_it ] ); + } + + it = begin; + for( int i = 0; i < index_size ; i+=2, it+=2 ) + { + index_type::iterator i_it = indices.begin(); std::advance( i_it, i ); + BOOST_CHECK( *it == elements[ *i_it ] ); + } + + + it = begin + (index_size); + BOOST_CHECK( it != begin ); + for( index_type::iterator i_it = --indices.end(); it-- != begin; --i_it ) + { + BOOST_CHECK( *it == elements[ *i_it ] ); + } + + it = begin + (index_size - 1); + for( int i = 0; i < index_size; i+=2, it-=2 ) + { + index_type::iterator i_it = --indices.end(); std::advance( i_it, -i ); + BOOST_CHECK( *it == elements[ *i_it ] ); + } + +} + + +int test_main(int, char *[]) +{ + permutation_test(); + + bool error_on_purpose = false; + //BOOST_CHECK( error_on_purpose ); + + return 0; +} diff --git a/test/reverse_iterator_test.cpp b/test/reverse_iterator_test.cpp new file mode 100644 index 0000000..8b3e9b6 --- /dev/null +++ b/test/reverse_iterator_test.cpp @@ -0,0 +1,97 @@ +// Copyright Thomas Witt 2003. 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. + +#include +#include +#include +#include + +using boost::dummyT; + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost +{ + namespace detail + { + template<> struct iterator_traits + : ptr_iter_traits {}; + template<> struct iterator_traits + : ptr_iter_traits {}; + } +} +#endif + +// Test reverse iterator +int main() +{ + dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), + dummyT(3), dummyT(4), dummyT(5) }; + const int N = sizeof(array)/sizeof(dummyT); + + // Test reverse_iterator_generator + { + dummyT reversed[N]; + std::copy(array, array + N, reversed); + std::reverse(reversed, reversed + N); + + typedef boost::reverse_iterator reverse_iterator; + + reverse_iterator i(reversed + N); + boost::random_access_iterator_test(i, N, array); + + boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array); + + typedef boost::reverse_iterator const_reverse_iterator; + + const_reverse_iterator j(reversed + N); + boost::random_access_iterator_test(j, N, array); + + const dummyT* const_reversed = reversed; + + boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array); + + boost::const_nonconst_iterator_test(i, ++j); + } + + // Test reverse_iterator_generator again, with traits fully deducible on all platforms + { + std::deque reversed_container; + std::reverse_copy(array, array + N, std::back_inserter(reversed_container)); + const std::deque::iterator reversed = reversed_container.begin(); + + + typedef boost::reverse_iterator< + std::deque::iterator> reverse_iterator; + typedef boost::reverse_iterator< + std::deque::const_iterator> const_reverse_iterator; + + // MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation + // (e.g. "reversed + N") is used in the constructor below. + const std::deque::iterator finish = reversed_container.end(); + reverse_iterator i(finish); + + boost::random_access_iterator_test(i, N, array); + boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array); + + const_reverse_iterator j = reverse_iterator(finish); + boost::random_access_iterator_test(j, N, array); + + const std::deque::const_iterator const_reversed = reversed; + boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array); + + // Many compilers' builtin deque iterators don't interoperate well, though + // STLport fixes that problem. +#if defined(__SGI_STL_PORT) \ + || !BOOST_WORKAROUND(__GNUC__, <= 2) \ + && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) \ + && !BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 1) + + boost::const_nonconst_iterator_test(i, ++j); + +#endif + } + return 0; +} diff --git a/test/static_assert_same.hpp b/test/static_assert_same.hpp new file mode 100644 index 0000000..3bff6bf --- /dev/null +++ b/test/static_assert_same.hpp @@ -0,0 +1,31 @@ +// Copyright David Abrahams 2003. 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 STATIC_ASSERT_SAME_DWA2003530_HPP +# define STATIC_ASSERT_SAME_DWA2003530_HPP + +# include + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct static_assert_same; + +template +struct static_assert_same +{ + enum { value = 1 }; +}; +#else +# include +# include +# include + +template +struct static_assert_same + : boost::mpl::if_,boost::mpl::true_,void>::type +{}; +#endif + +#endif // STATIC_ASSERT_SAME_DWA2003530_HPP diff --git a/test/transform_iterator_test.cpp b/test/transform_iterator_test.cpp new file mode 100644 index 0000000..fe694b5 --- /dev/null +++ b/test/transform_iterator_test.cpp @@ -0,0 +1,248 @@ +// (C) Copyright Jeremy Siek 2002. 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 +// 22 Nov 2002 Thomas Witt +// Added interoperability check. +// 28 Oct 2002 Jeremy Siek +// Updated for new iterator adaptors. +// 08 Mar 2001 Jeremy Siek +// Moved test of transform iterator into its own file. It to +// to be in iterator_adaptor_test.cpp. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost { namespace detail +{ + template<> struct iterator_traits + : ptr_iter_traits {}; + + template<> struct iterator_traits*> + : ptr_iter_traits > {}; + + template<> struct iterator_traits + : ptr_iter_traits {}; + + template<> struct iterator_traits const*> + : ptr_iter_traits, std::pair const> {}; + +}} +#endif + +struct mult_functor { + // Functors used with transform_iterator must be + // DefaultConstructible, as the transform_iterator must be + // DefaultConstructible to satisfy the requirements for + // TrivialIterator. + mult_functor() { } + mult_functor(int aa) : a(aa) { } + int operator()(int b) const { return a * b; } + int a; +}; + +struct adaptable_mult_functor + : mult_functor +{ + typedef int result_type; + typedef int argument_type; + // Functors used with transform_iterator must be + // DefaultConstructible, as the transform_iterator must be + // DefaultConstructible to satisfy the requirements for + // TrivialIterator. + adaptable_mult_functor() { } + adaptable_mult_functor(int aa) : mult_functor(aa) { } +}; + + +struct select_first +{ + typedef int& result_type; + + int& operator()(std::pair& p) const + { + return p.first; + } +}; + +struct select_second +{ + typedef int& result_type; + + int& operator()(std::pair& p) const + { + return p.second; + } +}; + +struct const_select_first +{ + typedef int const& result_type; + + int const& operator()(std::pairconst& p) const + { + return p.first; + } +}; + +struct value_select_first +{ + typedef int result_type; + + int operator()(std::pairconst& p) const + { + return p.first; + } +}; + +int mult_2(int arg) +{ + return arg*2; +} + +int +main() +{ + const int N = 10; + + // Concept checks + { + typedef boost::transform_iterator iter_t; + typedef boost::transform_iterator c_iter_t; + + boost::function_requires< boost_concepts::InteroperableConcept >(); + } + + // Test transform_iterator + { + int x[N], y[N]; + for (int k = 0; k < N; ++k) + x[k] = k; + std::copy(x, x + N, y); + + for (int k2 = 0; k2 < N; ++k2) + x[k2] = x[k2] * 2; + + typedef boost::transform_iterator iter_t; + iter_t i(y, adaptable_mult_functor(2)); + boost::input_iterator_test(i, x[0], x[1]); + boost::input_iterator_test(iter_t(&y[0], adaptable_mult_functor(2)), x[0], x[1]); + + boost::random_access_readable_iterator_test(i, N, x); + } + + // Test transform_iterator non adaptable functor + { + int x[N], y[N]; + for (int k = 0; k < N; ++k) + x[k] = k; + std::copy(x, x + N, y); + + for (int k2 = 0; k2 < N; ++k2) + x[k2] = x[k2] * 2; + + typedef boost::transform_iterator iter_t; + iter_t i(y, mult_functor(2)); + boost::input_iterator_test(i, x[0], x[1]); + boost::input_iterator_test(iter_t(&y[0], mult_functor(2)), x[0], x[1]); + + boost::random_access_readable_iterator_test(i, N, x); + } + + // Test transform_iterator default argument handling + { + { + typedef boost::transform_iterator iter_t; + BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + + { + typedef boost::transform_iterator iter_t; + BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + + { + typedef boost::transform_iterator iter_t; + BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + } + + // Test transform_iterator with function pointers + { + int x[N], y[N]; + for (int k = 0; k < N; ++k) + x[k] = k; + std::copy(x, x + N, y); + + for (int k2 = 0; k2 < N; ++k2) + x[k2] = x[k2] * 2; + + boost::input_iterator_test(boost::make_transform_iterator(y, mult_2) + , x[0] + , x[1]); + + boost::input_iterator_test(boost::make_transform_iterator(&y[0], mult_2) + , x[0] + , x[1]); + + boost::random_access_readable_iterator_test(boost::make_transform_iterator(y, mult_2) + , N + , x); + + } + + // Test transform_iterator as projection iterator + { + typedef std::pair pair_t; + + int x[N]; + int y[N]; + pair_t values[N]; + + for(int i = 0; i < N; ++i) { + + x[i] = i; + y[i] = N - (i + 1); + + } + + std::copy(x, + x + N, + boost::make_transform_iterator((pair_t*)values, select_first())); + + std::copy(y, + y + N, + boost::make_transform_iterator((pair_t*)values, select_second())); + + boost::random_access_readable_iterator_test(boost::make_transform_iterator((pair_t*)values, value_select_first()), + N, + x); + + boost::random_access_readable_iterator_test(boost::make_transform_iterator((pair_t*)values, const_select_first()), + N, + x); + + boost::constant_lvalue_iterator_test(boost::make_transform_iterator((pair_t*)values, const_select_first()), x[0]); + + boost::mutable_lvalue_iterator_test(boost::make_transform_iterator((pair_t*)values, select_first()), x[0], 17); + + } + + std::cout << "test successful " << std::endl; + return 0; +} diff --git a/test/unit_tests.cpp b/test/unit_tests.cpp new file mode 100644 index 0000000..4887357 --- /dev/null +++ b/test/unit_tests.cpp @@ -0,0 +1,103 @@ +// Copyright David Abrahams 2003. 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. +#include +#include +#include "static_assert_same.hpp" + +struct X { int a; }; + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost { namespace detail { +template<> struct iterator_traits + : ptr_iter_traits {}; +}} +#endif + +struct Xiter : boost::iterator_adaptor +{ + Xiter(); + Xiter(X* p) : boost::iterator_adaptor(p) {} +}; + +void take_xptr(X*) {} +void operator_arrow_test() +{ + // check that the operator-> result is a pointer for lvalue iterators + X x; + take_xptr(Xiter(&x).operator->()); +} + +template +struct static_assert_min_cat + : static_assert_same< + typename boost::detail::minimum_category::type, Min + > +{}; + +void category_test() +{ + using namespace boost; + using namespace boost::detail; + + BOOST_STATIC_ASSERT(( + !is_tag< + input_output_iterator_tag + , std::input_iterator_tag>::value)); + + BOOST_STATIC_ASSERT(( + !is_tag< + input_output_iterator_tag + , std::output_iterator_tag>::value)); + + BOOST_STATIC_ASSERT(( + is_tag< + std::input_iterator_tag + , input_output_iterator_tag>::value)); + + BOOST_STATIC_ASSERT(( + is_tag< + std::output_iterator_tag + , input_output_iterator_tag>::value)); + + BOOST_STATIC_ASSERT(( + is_tag< + input_output_iterator_tag + , std::forward_iterator_tag>::value)); + + int test = static_assert_min_cat< + std::input_iterator_tag,input_output_iterator_tag, std::input_iterator_tag + >::value; + + test = static_assert_min_cat< + input_output_iterator_tag,std::input_iterator_tag, std::input_iterator_tag + >::value; + + test = static_assert_min_cat< + input_output_iterator_tag,std::forward_iterator_tag, input_output_iterator_tag + >::value; + + test = static_assert_min_cat< + std::input_iterator_tag,std::forward_iterator_tag, std::input_iterator_tag + >::value; + + test = static_assert_min_cat< + std::input_iterator_tag,std::random_access_iterator_tag, std::input_iterator_tag + >::value; + + test = static_assert_min_cat< + std::output_iterator_tag,std::random_access_iterator_tag, std::output_iterator_tag + >::value; + + (void)test; +} + +int main() +{ + category_test(); + operator_arrow_test(); + return 0; +} + From 273ec4b975173a960d6dd71f102aa370c3462807 Mon Sep 17 00:00:00 2001 From: Aleksey Gurtovoy Date: Tue, 8 Jul 2003 05:10:04 +0000 Subject: [PATCH 168/265] BOOST_NO_MPL_AUX_HAS_XXX -> BOOST_MPL_NO_AUX_HAS_XXX [SVN r18974] --- include/boost/iterator/indirect_iterator.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/iterator/indirect_iterator.hpp b/include/boost/iterator/indirect_iterator.hpp index f6caa71..4e2500b 100644 --- a/include/boost/iterator/indirect_iterator.hpp +++ b/include/boost/iterator/indirect_iterator.hpp @@ -18,7 +18,7 @@ #include #include -#ifdef BOOST_NO_MPL_AUX_HAS_XXX +#ifdef BOOST_MPL_NO_AUX_HAS_XXX # include # include # include @@ -44,7 +44,7 @@ namespace boost // can be used instead with something like // boost/python/pointee.hpp to find the value_type. // -# ifndef BOOST_NO_MPL_AUX_HAS_XXX +# ifndef BOOST_MPL_NO_AUX_HAS_XXX namespace aux { BOOST_MPL_HAS_XXX_TRAIT_DEF(element_type) From 2b1fc22b61acdff2a5adc7c6c38864524607b29f Mon Sep 17 00:00:00 2001 From: Joel de Guzman Date: Thu, 10 Jul 2003 12:49:49 +0000 Subject: [PATCH 169/265] Move to Iterator Adapters from sand-box [SVN r19024] --- include/boost/iterator_adaptors.hpp | 1435 +-------------------------- 1 file changed, 6 insertions(+), 1429 deletions(-) diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 2796152..6d876e7 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -1,1436 +1,13 @@ -// (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, +// 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. -// See http://www.boost.org/libs/utility/iterator_adaptors.htm for documentation. - -// Revision History: - -// 01 Feb 2002 Jeremy Siek -// Added more comments in default_iterator_policies. -// 08 Jan 2001 David Abrahams -// Moved concept checks into a separate class, which makes MSVC -// better at dealing with them. -// 07 Jan 2001 David Abrahams -// Choose proxy for operator->() only if the reference type is not a reference. -// Updated workarounds for __MWERKS__ == 0x2406 -// 20 Dec 2001 David Abrahams -// Adjusted is_convertible workarounds for __MWERKS__ == 0x2406 -// 03 Nov 2001 Jeremy Siek -// Changed the named template parameter interface and internal. -// 04 Oct 2001 Jeremy Siek -// Changed projection_iterator to not rely on the default reference, -// working around a limitation of detail::iterator_traits. -// 04 Oct 2001 David Abrahams -// Applied indirect_iterator patch from George A. Heintzelman -// Changed name of "bind" to "select" to avoid problems with MSVC. -// 26 Sep 2001 David Abrahams -// Added borland bug fix -// 08 Mar 2001 Jeremy Siek -// Added support for optional named template parameters. -// 19 Feb 2001 David Abrahams -// Rolled back reverse_iterator_pair_generator again, as it doesn't -// save typing on a conforming compiler. -// 18 Feb 2001 David Abrahams -// Reinstated reverse_iterator_pair_generator -// 16 Feb 2001 David Abrahams -// Add an implicit conversion operator to operator_arrow_proxy -// as CW and BCC workarounds. -// 11 Feb 2001 David Abrahams -// Switch to use of BOOST_STATIC_CONSTANT where possible -// 11 Feb 2001 Jeremy Siek -// Removed workaround for older MIPSpro compiler. The workaround -// was preventing the proper functionality of the underlying -// iterator being carried forward into the iterator adaptor. -// Also added is_bidirectional enum to avoid EDG compiler error. -// 11 Feb 2001 David Abrahams -// Borland fixes up the wazoo. It finally works! -// 10 Feb 2001 David Abrahams -// Removed traits argument from iterator_adaptor<> and switched to -// explicit trait specification for maximum ease-of-use. -// Added comments to detail::iterator_defaults<> -// Began using detail::iterator_defaults<> unconditionally for code clarity -// Changed uses of `Iterator' to `Base' where non-iterators can be used. -// -// 10 Feb 2001 David Abrahams -// Rolled in supposed Borland fixes from John Maddock, but not seeing any -// improvement yet -// Changed argument order to indirect_ generator, for convenience in the -// case of input iterators (where Reference must be a value type). -// Removed derivation of filter_iterator_policies from -// default_iterator_policies, since the iterator category is likely to be -// reduced (we don't want to allow illegal operations like decrement). -// Support for a simpler filter iterator interface. -// -// 09 Feb 2001 David Abrahams -// Improved interface to indirect_ and reverse_ iterators -// Rolled back Jeremy's new constructor for now; it was causing -// problems with counting_iterator_test -// Attempted fix for Borland -// -// 09 Feb 2001 Jeremy Siek -// Added iterator constructor to allow const adaptor -// from non-const adaptee. -// Changed make_xxx to pass iterators by-value to -// get arrays converted to pointers. -// Removed InnerIterator template parameter from -// indirect_iterator_generator. -// Rearranged parameters for make_filter_iterator -// -// 07 Feb 2001 Jeremy Siek -// Removed some const iterator adaptor generators. -// Added make_xxx_iterator() helper functions for remaining -// iterator adaptors. -// Removed some traits template parameters where they -// where no longer needed thanks to detail::iterator_traits. -// Moved some of the compile-time logic into enums for -// EDG compatibility. -// -// 07 Feb 2001 David Abrahams -// 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 David Abrahams -// 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_ - -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include - -# if BOOST_WORKAROUND(__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(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(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 the member functions were defined static, but Borland - // got confused and thought they were non-const. Also, Sun C++ - // does not like static function templates. - // - // The reason some members were defined static is because there is - // not state (data members) needed by those members of the - // default_iterator_policies class. If your policies class member - // functions need to access state stored in the policies object, - // then the member functions should not be static (they can't be). - - template - void initialize(Base&) - { } - - template - typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const - { return *x.base(); } - - template - void increment(IteratorAdaptor& x) - { ++x.base(); } - - template - void decrement(IteratorAdaptor& x) - { --x.base(); } - - template - void advance(IteratorAdaptor& x, DifferenceType n) - { x.base() += n; } - - template - typename IteratorAdaptor1::difference_type - distance(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const - { return y.base() - x.base(); } - - template - bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const - { return x.base() == y.base(); } -}; - -// 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, y); -} - -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, y); -} - -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().distance(y, x) < 0; -} - -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().distance(y, x) > 0; -} - -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().distance(y, x) >= 0; -} - -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().distance(y, x) <= 0; -} -#endif - -namespace detail { - - // 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; } - // This function is needed for MWCW and BCC, which won't call operator-> - // again automatically per 13.3.1.2 para 8 - operator const T*() const { return &m_value; } - T m_value; - }; - - template - inline operator_arrow_proxy - operator_arrow(const Iter& i, std::input_iterator_tag) { - typedef typename Iter::value_type value_t; // VC++ needs this typedef - 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 operator_arrow_proxy proxy; - // Borland chokes unless it's an actual enum (!) - enum { use_proxy = !boost::is_reference::value }; - - typedef typename boost::detail::if_true<(use_proxy)>::template - then< - proxy, - // else - Pointer - >::type type; - }; - - -# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS) - - // Select default pointer and reference types for adapted non-pointer - // iterators based on the iterator and the value_type. Poor man's partial - // specialization is in use here. - template - struct iterator_defaults_select - { - template - struct traits - { - // The assumption is that iterator_traits can deduce these types - // properly as long as the iterator is not a pointer. - typedef typename boost::detail::iterator_traits::pointer pointer; - typedef typename boost::detail::iterator_traits::reference reference; - }; - }; - - // Select default pointer and reference types for adapted pointer iterators - // given a (possibly-const) value_type. - template <> - struct iterator_defaults_select - { - template - struct traits - { - typedef Value* pointer; - typedef Value& reference; - }; - }; - - // Consolidate selection of the default pointer and reference type - template - struct iterator_defaults - { - BOOST_STATIC_CONSTANT(bool, is_ptr = boost::is_pointer::value); - - typedef typename iterator_defaults_select::template traits traits; - typedef typename traits::pointer pointer; - typedef typename traits::reference reference; - }; -# else - template - struct iterator_defaults : iterator_traits - { - // Trying to factor the common is_same expression into an enum or a - // static bool constant confused Borland. - typedef typename if_true<( - ::boost::is_same::value_type>::value - )>::template then< - typename iterator_traits::pointer, - Value* - >::type pointer; - - typedef typename if_true<( - ::boost::is_same::value_type>::value - )>::template then< - typename iterator_traits::reference, - Value& - >::type reference; - - }; -# endif - - //=========================================================================== - // Specify the defaults for iterator_adaptor's template parameters - - struct default_argument { }; - // This class template is a workaround for MSVC. - struct dummy_default_gen { - template - struct select { typedef default_argument type; }; - }; - // This class template is a workaround for MSVC. - template struct default_generator { - typedef dummy_default_gen type; - }; - - struct default_value_type { - template - struct select { - typedef typename boost::detail::iterator_traits::value_type type; - }; - }; - template <> struct default_generator - { typedef default_value_type type; }; // VC++ workaround - - struct default_difference_type { - template - struct select { - typedef typename boost::detail::iterator_traits::difference_type type; - }; - }; - template <> struct default_generator - { typedef default_difference_type type; }; // VC++ workaround - - struct default_iterator_category { - template - struct select { - typedef typename boost::detail::iterator_traits::iterator_category type; - }; - }; - template <> struct default_generator - { typedef default_iterator_category type; }; // VC++ workaround - - struct default_pointer { - template - struct select { - typedef typename Traits::value_type Value; - typedef typename boost::detail::iterator_defaults::pointer - type; - }; - }; - template <> struct default_generator - { typedef default_pointer type; }; // VC++ workaround - - struct default_reference { - template - struct select { - typedef typename Traits::value_type Value; - typedef typename boost::detail::iterator_defaults::reference - type; - }; - }; - template <> struct default_generator - { typedef default_reference type; }; // VC++ workaround - -} // namespace detail - - - //=========================================================================== - // Support for named template parameters - -struct named_template_param_base { }; - -namespace detail { - struct value_type_tag { }; - struct reference_tag { }; - struct pointer_tag { }; - struct difference_type_tag { }; - struct iterator_category_tag { }; - - // avoid using std::pair because A or B might be a reference type, and g++ - // complains about forming references to references inside std::pair - template - struct cons_type { - typedef A first_type; - typedef B second_type; - }; - -} // namespace detail - -template struct value_type_is : public named_template_param_base -{ - typedef detail::cons_type type; -}; -template struct reference_is : public named_template_param_base -{ - typedef detail::cons_type type; -}; -template struct pointer_is : public named_template_param_base -{ - typedef detail::cons_type type; -}; -template struct difference_type_is - : public named_template_param_base -{ - typedef detail::cons_type type; -}; -template struct iterator_category_is - : public named_template_param_base -{ - typedef detail::cons_type type; -}; - -namespace detail { - - struct end_of_list { }; - - // Given an associative list, find the value with the matching key. - // An associative list is a list of key-value pairs. The list is - // built out of cons_type's and is terminated by end_of_list. - -# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || BOOST_WORKAROUND(__BORLANDC__, != 0) - template - struct find_param; - - struct find_param_continue { - template struct select { - typedef typename AssocList::first_type Head; - typedef typename Head::first_type Key1; - typedef typename Head::second_type Value; - typedef typename if_true<(is_same::value)>::template - then::type - >::type type; - }; - }; - struct find_param_end { - template - struct select { typedef detail::default_argument type; }; - }; - template struct find_param_helper1 - { typedef find_param_continue type; }; - template <> struct find_param_helper1 - { typedef find_param_end type; }; - - template - struct find_param { - typedef typename find_param_helper1::type select1; - typedef typename select1::template select::type type; - }; -# else - template struct find_param; - - template - struct find_param { typedef default_argument type; }; - - // Found a matching Key, return the associated Value - template - struct find_param, Rest>, Key> { - typedef Value type; - }; - - // Non-matching keys, continue the search - template - struct find_param, Rest>, Key2> { - typedef typename find_param::type type; - }; -# endif - - struct make_named_arg { - template - struct select { typedef typename Value::type type; }; - }; - struct make_key_value { - template - struct select { typedef detail::cons_type type; }; - }; - - template - struct is_named_parameter - { - enum { value = is_convertible< typename add_reference< Value >::type, add_reference< named_template_param_base >::type >::value }; - }; - -# if BOOST_WORKAROUND(__MWERKS__, <= 0x2407) // workaround for broken is_convertible implementation - template struct is_named_parameter > { enum { value = true }; }; - template struct is_named_parameter > { enum { value = true }; }; - template struct is_named_parameter > { enum { value = true }; }; - template struct is_named_parameter > { enum { value = true }; }; - template struct is_named_parameter > { enum { value = true }; }; -# endif - - template - struct make_arg { -# if BOOST_WORKAROUND(__BORLANDC__, > 0) - // Borland C++ doesn't like the extra indirection of is_named_parameter - typedef typename - if_true<(is_convertible::value)>:: - template then::type Make; -# else - enum { is_named = is_named_parameter::value }; - typedef typename if_true<(is_named)>::template - then::type Make; -# endif - typedef typename Make::template select::type type; - }; - - // Mechanism for resolving the default argument for a template parameter. - - template struct is_default { typedef type_traits::no_type type; }; - template <> struct is_default - { typedef type_traits::yes_type type; }; - - struct choose_default { - template - struct select { - typedef typename default_generator::type Gen; - typedef typename Gen::template select::type type; - }; - }; - struct choose_arg { - template - struct select { - typedef Arg type; - }; - }; - - template - struct choose_arg_or_default { typedef choose_arg type; }; - template <> struct choose_arg_or_default { - typedef choose_default type; - }; - - template - class resolve_default { - typedef typename choose_arg_or_default::type>::type - Selector; - public: - typedef typename Selector - ::template select::type type; - }; - - template - class iterator_adaptor_traits_gen - { - // Form an associative list out of the template parameters - // If the argument is a normal parameter (not named) then make_arg - // creates a key-value pair. If the argument is a named parameter, - // then make_arg extracts the key-value pair defined inside the - // named parameter. - typedef detail::cons_type< typename make_arg::type, - detail::cons_type::type, - detail::cons_type::type, - detail::cons_type::type, - detail::cons_type::type, - end_of_list> > > > > ArgList; - - // Search the list for particular parameters - typedef typename find_param::type Val; - typedef typename find_param::type Diff; - typedef typename find_param::type Cat; - typedef typename find_param::type Ptr; - typedef typename find_param::type Ref; - - typedef boost::iterator - Traits0; - - // Compute the defaults if necessary - typedef typename resolve_default::type - value_type; - // if getting default value type from iterator_traits, then it won't be const - typedef typename resolve_default::type difference_type; - typedef typename resolve_default::type iterator_category; - - typedef boost::iterator Traits1; - - // Compute the defaults for pointer and reference. This is done as a - // separate step because the defaults for pointer and reference depend - // on value_type. - typedef typename resolve_default::type - pointer; - typedef typename resolve_default::type - reference; - - public: - typedef boost::iterator::type, - difference_type, pointer, reference> type; - }; - - // This is really a partial concept check for iterators. Should it - // be moved or done differently? - template - struct validator - { - BOOST_STATIC_CONSTANT( - bool, is_input_or_output_iter - = (boost::is_convertible::value - | boost::is_convertible::value)); - - // Iterators should satisfy one of the known categories - BOOST_STATIC_ASSERT(is_input_or_output_iter); - - // Iterators >= ForwardIterator must produce real references - // as required by the C++ standard requirements in Table 74. - BOOST_STATIC_CONSTANT( - bool, forward_iter_with_real_reference - = ((!boost::is_convertible::value) - | boost::is_same::value - | boost::is_same::type&>::value)); - - BOOST_STATIC_ASSERT(forward_iter_with_real_reference); - }; - - template struct dependent - { - typedef Result type; - }; - -} // namespace detail - - - -// This macro definition is only temporary in this file -# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) -# define BOOST_ARG_DEPENDENT_TYPENAME typename -# else -# define BOOST_ARG_DEPENDENT_TYPENAME -# endif - -//============================================================================ -//iterator_adaptor - Adapts a generic piece of data as an iterator. Adaptation -// is especially easy if the data being adapted is itself an iterator -// -// Base - the base (usually iterator) type being wrapped. -// -// Policies - a set of policies determining how the resulting iterator -// works. -// -// Value - if supplied, the value_type of the resulting iterator, unless -// const. If const, a conforming compiler strips constness for the -// value_type. If not supplied, iterator_traits::value_type is used -// -// Reference - the reference type of the resulting iterator, and in -// particular, the result type of operator*(). If not supplied but -// Value is supplied, Value& is used. Otherwise -// iterator_traits::reference is used. -// -// Pointer - the pointer type of the resulting iterator, and in -// particular, the result type of operator->(). If not -// supplied but Value is supplied, Value* is used. Otherwise -// iterator_traits::pointer is used. -// -// Category - the iterator_category of the resulting iterator. If not -// supplied, iterator_traits::iterator_category is used. -// -// Distance - the difference_type of the resulting iterator. If not -// supplied, iterator_traits::difference_type is used. -template -struct iterator_adaptor : -#ifdef BOOST_RELOPS_AMBIGUITY_BUG - iterator_comparisons< - iterator_adaptor, - typename detail::iterator_adaptor_traits_gen::type - > -#else - detail::iterator_adaptor_traits_gen::type -#endif -{ - typedef iterator_adaptor self; - public: - typedef detail::iterator_adaptor_traits_gen TraitsGen; - typedef typename TraitsGen::type Traits; - - 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 Base base_type; - typedef Policies policies_type; - - private: - typedef detail::validator< - iterator_category,value_type,difference_type,pointer,reference - > concept_check; - - public: - iterator_adaptor() - { - } - - explicit - iterator_adaptor(const Base& it, const Policies& p = Policies()) - : m_iter_p(it, p) { - policies().initialize(base()); - } - - template - iterator_adaptor ( - const iterator_adaptor& src) - : m_iter_p(src.base(), src.policies()) - { - policies().initialize(base()); - } - -#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(__BORLANDC__, > 0) - // 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(*this); - } - -#if BOOST_WORKAROUND(BOOST_MSVC, > 0) -# pragma warning(push) -# pragma warning( disable : 4284 ) -#endif - - typename boost::detail::operator_arrow_result_generator::type - operator->() const - { return detail::operator_arrow(*this, iterator_category()); } - -#if BOOST_WORKAROUND(BOOST_MSVC, > 0) -# pragma warning(pop) -#endif - - template - typename detail::dependent::type operator[](diff_type n) const - { return *(*this + n); } - - self& operator++() { -#if !BOOST_WORKAROUND(__MWERKS__, < 0x2405) - policies().increment(*this); -#else - // Odd bug, MWERKS couldn't deduce the type for the member template - // Workaround by explicitly specifying the type. - policies().increment(*this); -#endif - return *this; - } - - self operator++(int) { self tmp(*this); ++*this; return tmp; } - - self& operator--() { -#if !BOOST_WORKAROUND(__MWERKS__, < 0x2405) - policies().decrement(*this); -#else - policies().decrement(*this); -#endif - return *this; - } - - self operator--(int) { self tmp(*this); --*this; return tmp; } - - self& operator+=(difference_type n) { - policies().advance(*this, n); - return *this; - } - - self& operator-=(difference_type n) { - policies().advance(*this, -n); - return *this; - } - - base_type const& base() const { return m_iter_p.first(); } - - // Moved from global scope to avoid ambiguity with the operator-() which - // subtracts iterators from one another. - self operator-(difference_type x) const - { self result(*this); return result -= x; } -private: - compressed_pair m_iter_p; - -public: // implementation details (too many compilers have trouble when these are private). - base_type& base() { return m_iter_p.first(); } - Policies& policies() { return m_iter_p.second(); } - const Policies& policies() const { return m_iter_p.second(); } -}; - -template -iterator_adaptor -operator+( - iterator_adaptor p, - Distance2 x) -{ - return p += x; -} - -template -iterator_adaptor -operator+( - Distance2 x, - iterator_adaptor p) -{ - return p += x; -} - -template -typename iterator_adaptor::difference_type -operator-( - const iterator_adaptor& x, - const iterator_adaptor& y) -{ - typedef typename iterator_adaptor::difference_type difference_type; - return x.policies().distance(y, x); -} - -#ifndef BOOST_RELOPS_AMBIGUITY_BUG -template -inline bool -operator==( - const iterator_adaptor& x, - const iterator_adaptor& y) -{ - return x.policies().equal(x, y); -} - -template -inline bool -operator<( - const iterator_adaptor& x, - const iterator_adaptor& y) -{ - return x.policies().distance(y, x) < 0; -} - -template -inline bool -operator>( - const iterator_adaptor& x, - const iterator_adaptor& y) -{ - return x.policies().distance(y, x) > 0; -} - -template -inline bool -operator>=( - const iterator_adaptor& x, - const iterator_adaptor& y) -{ - return x.policies().distance(y, x) >= 0; -} - -template -inline bool -operator<=( - const iterator_adaptor& x, - const iterator_adaptor& y) -{ - return x.policies().distance(y, x) <= 0; -} - -template -inline bool -operator!=( - const iterator_adaptor& x, - const iterator_adaptor& y) -{ - return !x.policies().equal(x, y); -} -#endif - -//============================================================================= -// 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 - typename IteratorAdaptor::reference - dereference(const IteratorAdaptor& iter) const - { return m_f(*iter.base()); } - - AdaptableUnaryFunction m_f; -}; - -template -class transform_iterator_generator -{ - typedef typename AdaptableUnaryFunction::result_type value_type; -public: - typedef iterator_adaptor, - value_type, value_type, value_type*, std::input_iterator_tag> - type; -}; - -template -inline typename transform_iterator_generator::type -make_transform_iterator( - Iterator base, - const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) -{ - typedef typename transform_iterator_generator::type result_t; - return result_t(base, f); -} - -//============================================================================= -// 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 - typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const - { return **x.base(); } -}; - -namespace detail { -# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // strangely instantiated even when unused! Maybe try a recursive template someday ;-) - template - struct traits_of_value_type { - typedef typename boost::detail::iterator_traits::value_type outer_value; - typedef typename boost::detail::iterator_traits::value_type value_type; - typedef typename boost::detail::iterator_traits::reference reference; - typedef typename boost::detail::iterator_traits::pointer pointer; - }; -# endif -} - -template ::value_type -#endif - , class Reference -#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< - OuterIterator>::reference -#else - = Value & -#endif - , class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits< - OuterIterator>::iterator_category - , class Pointer -#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< - OuterIterator>::pointer -#else - = Value* -#endif - > -struct indirect_iterator_generator -{ - typedef iterator_adaptor type; -}; - -template ::value_type -#endif - , class Reference -#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< - OuterIterator>::reference -#else - = Value & -#endif - , class ConstReference = Value const& - , class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits< - OuterIterator>::iterator_category - , class Pointer -#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< - OuterIterator>::pointer -#else - = Value* -#endif - , class ConstPointer = Value const* - > -struct indirect_iterator_pair_generator -{ - typedef typename indirect_iterator_generator::type iterator; - typedef typename indirect_iterator_generator::type const_iterator; -}; - -#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) -template -inline typename indirect_iterator_generator::type -make_indirect_iterator(OuterIterator base) -{ - typedef typename indirect_iterator_generator - ::type result_t; - return result_t(base); -} -#endif - -//============================================================================= -// Reverse Iterators Adaptor - -struct reverse_iterator_policies : public default_iterator_policies -{ - template - typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const - { return *boost::prior(x.base()); } - - template - void increment(BidirectionalIterator& x) const - { --x.base(); } - - template - void decrement(BidirectionalIterator& x) const - { ++x.base(); } - - template - void advance(BidirectionalIterator& x, DifferenceType n) const - { x.base() -= n; } - - template - typename Iterator1::difference_type distance( - const Iterator1& x, const Iterator2& y) const - { return x.base() - y.base(); } - - template - bool equal(const Iterator1& x, const Iterator2& y) const - { return x.base() == y.base(); } -}; - -template ::value_type, - class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, - class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, - class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category, - class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type - > -struct reverse_iterator_generator -{ - typedef iterator_adaptor type; -}; - -template -inline typename reverse_iterator_generator::type -make_reverse_iterator(BidirectionalIterator base) -{ - typedef typename reverse_iterator_generator::type result_t; - return result_t(base); -} - -//============================================================================= -// 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 - typename IteratorAdaptor::reference dereference(IteratorAdaptor const& iter) const { - return m_f(*iter.base()); - } - - AdaptableUnaryFunction m_f; -}; - -template -class projection_iterator_generator { - typedef typename AdaptableUnaryFunction::result_type value_type; - typedef projection_iterator_policies policies; -public: - typedef iterator_adaptor type; -}; - -template -class const_projection_iterator_generator { - typedef typename AdaptableUnaryFunction::result_type value_type; - typedef projection_iterator_policies policies; -public: - typedef iterator_adaptor type; -}; - -template -struct projection_iterator_pair_generator { - typedef typename projection_iterator_generator::type iterator; - typedef typename const_projection_iterator_generator::type const_iterator; -}; - - -template -inline typename projection_iterator_generator::type -make_projection_iterator( - Iterator iter, - const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) -{ - typedef typename projection_iterator_generator::type result_t; - return result_t(iter, f); -} - -template -inline typename const_projection_iterator_generator::type -make_const_projection_iterator( - Iterator iter, - const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) -{ - typedef typename const_projection_iterator_generator::type result_t; - return result_t(iter, f); -} - -//============================================================================= -// Filter Iterator Adaptor - -template -class filter_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) { - satisfy_predicate(x); - } - - // The Iter template argument is neccessary for compatibility with a MWCW - // bug workaround - template - void increment(IteratorAdaptor& x) { - ++x.base(); - satisfy_predicate(x.base()); - } - - template - typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const - { return *x.base(); } - - template - bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const - { return x.base() == y.base(); } - - private: - void satisfy_predicate(Iterator& iter); - Predicate m_predicate; - Iterator m_end; -}; - -template -void filter_iterator_policies::satisfy_predicate( - Iterator& iter) -{ - while (m_end != iter && !m_predicate(*iter)) - ++iter; -} - - - -namespace detail { - // A type generator returning Base if T is derived from Base, and T otherwise. - template - struct reduce_to_base_class - { - typedef typename if_true<( - ::boost::is_convertible::value - )>::template then::type type; - }; - - // "Steps down" the category of iterators below bidirectional so the category - // can be used with filter iterators. - template - struct non_bidirectional_category - { -# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) - typedef typename reduce_to_base_class< - std::forward_iterator_tag, - typename iterator_traits::iterator_category - >::type type; - private: - // For some reason, putting this assertion in filter_iterator_generator fails inexplicably under MSVC - BOOST_STATIC_CONSTANT( - bool, is_bidirectional - = (!boost::is_convertible::value)); - BOOST_STATIC_ASSERT(is_bidirectional); -# else - // is_convertible doesn't work with MWERKS - typedef typename iterator_traits::iterator_category input_category; - public: - typedef typename if_true<( - boost::is_same::value - || boost::is_same::value - )>::template then< - std::forward_iterator_tag, - input_category - >::type type; -# endif - }; -} - -template ::value_type, - class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, - class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, - class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::non_bidirectional_category::type, - class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type - > -class filter_iterator_generator { - BOOST_STATIC_CONSTANT(bool, is_bidirectional - = (boost::is_convertible::value)); -#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // I don't have any idea why this occurs, but it doesn't seem to hurt too badly. - BOOST_STATIC_ASSERT(!is_bidirectional); -#endif - typedef filter_iterator_policies policies_type; - public: - typedef iterator_adaptor type; -}; - -// This keeps MSVC happy; it doesn't like to deduce default template arguments -// for template function return types -namespace detail { - template - struct filter_generator { - typedef typename boost::filter_iterator_generator::type type; - }; -} - -template -inline typename detail::filter_generator::type -make_filter_iterator(Iterator first, Iterator last, const Predicate& p = Predicate()) -{ - typedef filter_iterator_generator Gen; - typedef filter_iterator_policies policies_t; - typedef typename Gen::type result_t; - return result_t(first, policies_t(p, last)); -} - -} // namespace boost -# undef BOOST_ARG_DEPENDENT_TYPENAME - - -#endif - +#ifndef BOOST_ITERATOR_ADAPTOR_13062003HK_HPP +#define BOOST_ITERATOR_ADAPTOR_13062003HK_HPP +#define BOOST_ITERATOR_ADAPTORS_VERSION 0x0200 +#include +#endif // BOOST_ITERATOR_ADAPTOR_13062003HK_HPP From e2a47bdbe5dfb569fe8dbb4f1fb2f1ce77f69c61 Mon Sep 17 00:00:00 2001 From: Joel de Guzman Date: Thu, 10 Jul 2003 12:52:06 +0000 Subject: [PATCH 170/265] Moved to boost/iterator [SVN r19025] --- include/boost/permutation_iterator.hpp | 74 -------------------------- 1 file changed, 74 deletions(-) delete mode 100644 include/boost/permutation_iterator.hpp diff --git a/include/boost/permutation_iterator.hpp b/include/boost/permutation_iterator.hpp deleted file mode 100644 index 8fdddb2..0000000 --- a/include/boost/permutation_iterator.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// (C) Copyright Toon Knapen 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. -// - -// See http://www.boost.org/libs/utility/permutation_iterator.htm for documentation. - -#ifndef boost_permutation_iterator_hpp -#define boost_permutation_iterator_hpp - -#include - -namespace boost { - - template < typename IndexIterator > - struct permutation_iterator_policies : public default_iterator_policies - { - permutation_iterator_policies() {} - - permutation_iterator_policies(IndexIterator order_it) - : order_it_( order_it ) - {} - - template - typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const - { return *(x.base() + *order_it_); } - - template - void increment(IteratorAdaptor&) - { ++order_it_; } - - template - void decrement(IteratorAdaptor&) - { --order_it_; } - - template - void advance(IteratorAdaptor& x, DifferenceType n) - { std::advance( order_it_, n ); } - - template - typename IteratorAdaptor1::difference_type - distance(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const - { return std::distance( x.policies().order_it_, y.policies().order_it_ ); } - - template - bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const - { return x.policies().order_it_ == y.policies().order_it_; } - - IndexIterator order_it_; - }; - - template < typename ElementIterator, typename IndexIterator > - struct permutation_iterator_generator - { - typedef boost::iterator_adaptor - < ElementIterator, - permutation_iterator_policies< IndexIterator > - > type; - }; - - template < class IndexIterator, class ElementIterator > - inline typename permutation_iterator_generator< ElementIterator, IndexIterator >::type - make_permutation_iterator(ElementIterator base, IndexIterator order) - { - typedef typename permutation_iterator_generator< ElementIterator, IndexIterator >::type result_t; - return result_t( base, order ); - } - -} // namespace boost - -#endif // boost_permutation_iterator_hpp - From a1ec9da73710ea7f0aa1da498a6ab65314787e97 Mon Sep 17 00:00:00 2001 From: Joel de Guzman Date: Thu, 10 Jul 2003 12:58:28 +0000 Subject: [PATCH 171/265] Moved to boost/iterator (new version) [SVN r19026] --- include/boost/counting_iterator.hpp | 229 ---------------------------- 1 file changed, 229 deletions(-) delete mode 100644 include/boost/counting_iterator.hpp diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp deleted file mode 100644 index 574e176..0000000 --- a/include/boost/counting_iterator.hpp +++ /dev/null @@ -1,229 +0,0 @@ -// (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. -// -// See http://www.boost.org/libs/utility/counting_iterator.htm for documentation. -// -// Supplies: -// -// template class counting_iterator_traits; -// template class counting_iterator_policies; -// -// Iterator traits and policies for adapted iterators whose dereferenced -// 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 -// typename counting_iterator_generator::type -// make_counting_iterator(Incrementable); -// -// A function which produces an adapted counting iterator over values of -// Incrementable. -// -// Revision History -// 14 Feb 2001 Removed unnecessary typedefs from counting_iterator_traits -// (Jeremy Siek) -// 11 Feb 2001 Use BOOST_STATIC_CONSTANT (Dave Abrahams) -// 11 Feb 2001 Clean up after John Maddocks's (finally effective!) Borland -// fixes (David Abrahams). -// 10 Feb 2001 Use new iterator_adaptor<> interface (David Abrahams) -// 10 Feb 2001 Rolled in supposed Borland fixes from John Maddock, but not -// seeing any improvement yet (David Abrahams) -// 09 Feb 2001 Factored out is_numeric computation. Borland still -// unhappy :( (David Abrahams) -// 08 Feb 2001 Beginning of a failed attempt to appease Borland -// (David Abrahams) -// 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 -// boost/pending/integer_range.hpp (David Abrahams) - -#ifndef BOOST_COUNTING_ITERATOR_HPP_DWA20000119 -# define BOOST_COUNTING_ITERATOR_HPP_DWA20000119 - -# include -# include -# include -# include -# include -# include -# include - -namespace boost { - -namespace detail { - - // Template class counting_iterator_traits_select -- choose an - // iterator_category and difference_type for a counting_iterator at - // compile-time based on whether or not it wraps an integer or an iterator, - // using "poor man's partial specialization". - template struct counting_iterator_traits_select; - - // Incrementable is an iterator type - template <> - struct counting_iterator_traits_select - { - template - struct traits - { - private: - typedef boost::detail::iterator_traits x; - public: - typedef typename x::iterator_category iterator_category; - typedef typename x::difference_type difference_type; - }; - }; - - // Incrementable is a numeric type - template <> - struct counting_iterator_traits_select - { - template - struct traits - { - typedef typename - boost::detail::numeric_traits::difference_type - difference_type; - typedef std::random_access_iterator_tag iterator_category; - }; - }; - - // Template class distance_policy_select -- choose a policy for computing the - // distance between counting_iterators at compile-time based on whether or not - // the iterator wraps an integer or an iterator, using "poor man's partial - // specialization". - - template struct distance_policy_select; - - // A policy for wrapped iterators - template <> - struct distance_policy_select - { - template - struct policy { - static Distance distance(Incrementable x, Incrementable y) - { return boost::detail::distance(x, y); } - }; - }; - - // A policy for wrapped numbers - template <> - struct distance_policy_select - { - template - struct policy { - static Distance distance(Incrementable x, Incrementable y) - { return numeric_distance(x, y); } - }; - }; - - // Try to detect numeric types at compile time in ways compatible with the - // limitations of the compiler and library. - template - struct is_numeric { - // For a while, this wasn't true, but we rely on it below. This is a regression assert. - BOOST_STATIC_ASSERT(::boost::is_integral::value); -# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS -# if defined(BOOST_HAS_LONG_LONG) - BOOST_STATIC_CONSTANT(bool, - value = ( - std::numeric_limits::is_specialized - | boost::is_same::value - | boost::is_same::value)); -# else - BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_specialized); -# endif -# else -# if !defined(__BORLANDC__) - BOOST_STATIC_CONSTANT(bool, value = ( - boost::is_convertible::value && boost::is_convertible::value)); -# else - BOOST_STATIC_CONSTANT(bool, value = ::boost::is_arithmetic::value); -# endif -# endif - }; - - // Compute the distance over arbitrary numeric and/or iterator types - template - Distance any_distance(Incrementable start, Incrementable finish, Distance* = 0) - { - - return distance_policy_select<( - is_numeric::value)>::template - policy::distance(start, finish); - } - -} // namespace detail - -template -struct counting_iterator_traits { - private: - typedef ::boost::detail::counting_iterator_traits_select<( - ::boost::detail::is_numeric::value - )> binder; - typedef typename binder::template traits traits; - public: - typedef typename traits::difference_type difference_type; - typedef typename traits::iterator_category iterator_category; -}; - -template -struct counting_iterator_policies : public default_iterator_policies -{ - template - typename IteratorAdaptor::reference dereference(const IteratorAdaptor& i) const - { return i.base(); } - - template - typename Iterator1::difference_type distance( - const Iterator1& x, const Iterator2& y) const - { - typedef typename Iterator1::difference_type difference_type; - return boost::detail::any_distance( - x.base(), y.base()); - } -}; - -// A type generator for counting iterators -template -struct counting_iterator_generator -{ - typedef typename boost::remove_const< - Incrementable - >::type value_type; - - typedef counting_iterator_traits traits; - - typedef iterator_adaptor< - value_type - , counting_iterator_policies - , value_type - , value_type const& - , value_type const* - , typename traits::iterator_category - , typename traits::difference_type - > type; -}; - -// Manufacture a counting iterator for an arbitrary incrementable type -template -inline typename counting_iterator_generator::type -make_counting_iterator(Incrementable x) -{ - typedef typename counting_iterator_generator::type result_t; - return result_t(x); -} - - -} // namespace boost - -#endif // BOOST_COUNTING_ITERATOR_HPP_DWA20000119 From 04301ac6e9a72b33c66486ef14696d4464b9a130 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 11 Jul 2003 22:16:52 +0000 Subject: [PATCH 172/265] Workaround some CWPro8 bugs [SVN r19072] --- include/boost/iterator/iterator_adaptor.hpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/include/boost/iterator/iterator_adaptor.hpp b/include/boost/iterator/iterator_adaptor.hpp index c29dbd9..d9a6263 100644 --- a/include/boost/iterator/iterator_adaptor.hpp +++ b/include/boost/iterator/iterator_adaptor.hpp @@ -273,25 +273,29 @@ namespace boost void advance(typename super_t::difference_type n) { +# if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) // seems to get instantiated incorrectly BOOST_STATIC_ASSERT( (detail::is_tag< - random_access_traversal_tag - , BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal + random_access_traversal_tag + , BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal >::value) ); +# endif m_iterator += n; } void increment() { ++m_iterator; } void decrement() - { + { +# if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) // seems to get instantiated incorrectly BOOST_STATIC_ASSERT( - (detail::is_tag< - bidirectional_traversal_tag - , BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal - >::value) - ); + (detail::is_tag< + bidirectional_traversal_tag + , BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal + >::value) + ); +# endif --m_iterator; } From 1d6f36e35d91b32a3d1ea88f16e60720e1460a7f Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 11 Jul 2003 22:18:58 +0000 Subject: [PATCH 173/265] Move to new iterator adaptors [SVN r19074] --- include/boost/pending/integer_range.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/pending/integer_range.hpp b/include/boost/pending/integer_range.hpp index e1b8720..81ecf4d 100644 --- a/include/boost/pending/integer_range.hpp +++ b/include/boost/pending/integer_range.hpp @@ -12,7 +12,7 @@ #define BOOST_INTEGER_RANGE_HPP_ #include -#include +#include namespace boost { @@ -21,7 +21,7 @@ namespace boost { template struct integer_range { - typedef typename counting_iterator_generator::type iterator; + typedef counting_iterator iterator; typedef iterator const_iterator; typedef IntegerType value_type; From 4c8415a99fb5fd28aaf0364896b867e63aee1eb7 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 12 Jul 2003 04:15:13 +0000 Subject: [PATCH 174/265] Get examples working, mostly. Some interface expansion for a few of the adaptors, allowing default construction of UnaryFunction and Predicate arguments when they are class types. [SVN r19081] --- include/boost/iterator/filter_iterator.hpp | 27 +++++++++++- include/boost/iterator/transform_iterator.hpp | 44 ++++++++++++++++--- test/Jamfile | 43 +++++++++++++----- 3 files changed, 94 insertions(+), 20 deletions(-) diff --git a/include/boost/iterator/filter_iterator.hpp b/include/boost/iterator/filter_iterator.hpp index ae46fba..547513f 100644 --- a/include/boost/iterator/filter_iterator.hpp +++ b/include/boost/iterator/filter_iterator.hpp @@ -56,8 +56,15 @@ namespace boost satisfy_predicate(); } - filter_iterator(Iterator x, Iterator end = Iterator()) - : super_t(x), m_predicate(), m_end(end) + // don't provide this constructor if UnaryFunction is a + // function pointer type. Too dangerous. + filter_iterator( + typename detail::enable_if< + is_class + , Iterator + >::type x + , Iterator end = Iterator()) + : super_t(x), m_predicate(), m_end(end) { satisfy_predicate(); } @@ -104,6 +111,22 @@ namespace boost return filter_iterator(f,x,end); } + template + filter_iterator + make_filter_iterator( + typename detail::enable_if< + is_class + , Iterator + >::type x + , Iterator end = Iterator() +#if BOOST_WORKAROUND(BOOST_MSVC, == 1200) + , Predicate* = 0 +#endif + ) + { + return filter_iterator(x,end); + } + } // namespace boost #endif // BOOST_FILTER_ITERATOR_23022003THW_HPP diff --git a/include/boost/iterator/transform_iterator.hpp b/include/boost/iterator/transform_iterator.hpp index 26ed994..f560116 100644 --- a/include/boost/iterator/transform_iterator.hpp +++ b/include/boost/iterator/transform_iterator.hpp @@ -14,10 +14,11 @@ #include #include #include -#include +#include #include #include #include +#include #include #include #include @@ -96,7 +97,6 @@ namespace boost , result_type > type; }; - } template @@ -115,10 +115,28 @@ namespace boost transform_iterator(Iterator const& x, UnaryFunction f) : super_t(x), m_f(f) { } + // don't provide this constructor if UnaryFunction is a + // function pointer type. Too dangerous. + transform_iterator( + // Sadly, GCC 3.2 seems to choke on the enable_if when + // UnaryFunction is a plain function pointer +#if BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(3)) \ + && BOOST_WORKAROUND(__GNUC_MINOR__, BOOST_TESTED_AT(2)) + Iterator const& x +#else + typename detail::enable_if< + is_class + , Iterator const& + >::type x +#endif + ) + : super_t(x) + {} + template transform_iterator( - transform_iterator const& t - , typename enable_if_convertible::type* = 0 + transform_iterator const& t + , typename enable_if_convertible::type* = 0 ) : super_t(t.base()), m_f(t.functor()) {} @@ -135,9 +153,23 @@ namespace boost }; template - transform_iterator make_transform_iterator(Iterator it, UnaryFunction fun) + transform_iterator + make_transform_iterator(Iterator it, UnaryFunction fun) { - return transform_iterator(it, fun); + return transform_iterator(it, fun); + } + + template + // don't provide this generator if UnaryFunction is a + // function pointer type. Too dangerous. We should probably + // find a cheaper test than is_class<> + typename detail::enable_if< + is_class + , transform_iterator + >::type + make_transform_iterator(Iterator it) + { + return transform_iterator(it, UnaryFunction()); } #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) diff --git a/test/Jamfile b/test/Jamfile index 75d3d1f..6cdcefc 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -1,14 +1,33 @@ +# Copyright David Abrahams 2003. 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. SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; include testing.jam ; -run unit_tests.cpp ; -run concept_tests.cpp ; -run iterator_adaptor_cc.cpp ; -run iterator_adaptor_test.cpp ; -compile iterator_archetype_cc.cpp ; -run transform_iterator_test.cpp ; -run indirect_iterator_test.cpp ; -run filter_iterator_test.cpp ; -run reverse_iterator_test.cpp ; -run counting_iterator_test.cpp ; -run is_convertible_fail.cpp ; # test changed to expected success, so that we catch compilation failures. -compile-fail interoperable_fail.cpp ; + +test-suite iterator + : [ run unit_tests.cpp ] + [ run concept_tests.cpp ] + [ run iterator_adaptor_cc.cpp ] + [ run iterator_adaptor_test.cpp ] + [ compile iterator_archetype_cc.cpp ] + [ run transform_iterator_test.cpp ] + [ run indirect_iterator_test.cpp ] + [ run filter_iterator_test.cpp ] + [ run reverse_iterator_test.cpp ] + [ run counting_iterator_test.cpp ] + + [ run ../../utility/iterator_adaptor_examples.cpp ] + [ run ../../utility/counting_iterator_example.cpp ] + [ run ../../utility/filter_iterator_example.cpp ] + [ run ../../utility/fun_out_iter_example.cpp ] + [ run ../../utility/indirect_iterator_example.cpp ] + [ run ../../utility/projection_iterator_example.cpp ] + [ run ../../utility/reverse_iterator_example.cpp ] + [ run ../../utility/transform_iterator_example.cpp ] + + [ run is_convertible_fail.cpp ] # test changed to expected success, so that we catch compilation failures. + + [ compile-fail interoperable_fail.cpp ] +; \ No newline at end of file From eda969d7b55ee23aac65b9fae82e2054bc9229ba Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 12 Jul 2003 10:41:38 +0000 Subject: [PATCH 175/265] add "subproject" line [SVN r19086] --- test/Jamfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/Jamfile b/test/Jamfile index 6cdcefc..f00e2cb 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -3,6 +3,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. + +subproject libs/iterator/test ; + SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; include testing.jam ; @@ -30,4 +33,4 @@ test-suite iterator [ run is_convertible_fail.cpp ] # test changed to expected success, so that we catch compilation failures. [ compile-fail interoperable_fail.cpp ] -; \ No newline at end of file +; From dfc43d81cf61d4d9b7e4475979151b550838cad1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 12 Jul 2003 16:39:19 +0000 Subject: [PATCH 176/265] Fix a couple of typos [SVN r19089] --- doc/facade-and-adaptor.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/facade-and-adaptor.rst b/doc/facade-and-adaptor.rst index 169b856..321c9e2 100644 --- a/doc/facade-and-adaptor.rst +++ b/doc/facade-and-adaptor.rst @@ -585,8 +585,8 @@ out of the overload set when the types are not interoperable.] The ``Derived`` template parameter must be a class derived from ``iterator_facade``. -The default for the ``Reference`` parameter is `Value&`` if the access -category for ``iterator_facade`` is implicitly convertible to +The default for the ``Reference`` parameter is ``Value&`` if the +access category for ``iterator_facade`` is implicitly convertible to ``writable_iterator_tag``, and ``const Value&`` otherwise. The following table describes the other requirements on the @@ -1513,7 +1513,7 @@ Class template ``function_output_iterator`` public: typedef iterator_tag< writable_iterator_tag - , incrementable_iterator_tag + , incrementable_traversal_tag > iterator_category; typedef void value_type; typedef void difference_type; From b0aef5a66d7a1fe03fbfaa04fcdae320da727275 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 12 Jul 2003 20:16:49 +0000 Subject: [PATCH 177/265] Fixup some tables. Restore the equivalence between readable single-pass iterator and input iterator by restricting the allowed return type of r++. [SVN r19091] --- doc/new-iter-concepts.rst | 352 +++++++++++++++++++++----------------- 1 file changed, 194 insertions(+), 158 deletions(-) diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index cd29dbe..9005000 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -42,17 +42,18 @@ requirements that address value access sneak in at various places. The following table gives a summary of the current value access requirements in the iterator categories. -+------------------------+-------------------------------------------------------------------------+ -| Output Iterator | ``*i = a`` | -+------------------------+-------------------------------------------------------------------------+ -| Input Iterator | ``*i`` is convertible to ``T`` | -+------------------------+-------------------------------------------------------------------------+ -| Forward Iterator | ``*i`` is ``T&`` (or ``const T&`` once | -| | `issue 200`_ is resolved) | -+------------------------+-------------------------------------------------------------------------+ -| Random Access Iterator | ``i[n]`` is convertible to ``T`` (also ``i[n] = t`` is required for | -| | mutable iterators once `issue 299`_ is resolved) | -+------------------------+-------------------------------------------------------------------------+ ++------------------------+-----------------------------------------------------+ +|Output Iterator |``*i = a`` | ++------------------------+-----------------------------------------------------+ +|Input Iterator |``*i`` is convertible to ``T`` | ++------------------------+-----------------------------------------------------+ +|Forward Iterator |``*i`` is ``T&`` (or ``const T&`` once `issue 200`_ | +| |is resolved) | ++------------------------+-----------------------------------------------------+ +|Random Access Iterator |``i[n]`` is convertible to ``T`` (also ``i[n] = t`` | +| |is required for mutable iterators once `issue 299`_ | +| |is resolved) | ++------------------------+-----------------------------------------------------+ .. _issue 200: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#200 .. _issue 299: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#299 @@ -135,29 +136,36 @@ following lists the proposed changes to the type requirements of algorithms. Forward Iterator -> Forward Traversal Iterator and Readable Iterator + ``find_end, adjacent_find, search, search_n, rotate_copy, lower_bound, upper_bound, equal_range, binary_search, min_element, max_element`` Forward Iterator (1) -> Single Pass Iterator and Readable Iterator Forward Iterator (2) -> Forward Traversal Iterator and Readable Iterator + ``find_first_of`` Forward Iterator -> Readable Iterator and Writable Iterator + ``iter_swap`` Forward Iterator -> Single Pass Iterator and Writable Iterator + ``fill, generate`` Forward Iterator -> Forward Traversal Iterator and Swappable Iterator + ``rotate`` Forward Iterator (1) -> Swappable Iterator and Single Pass Iterator Forward Iterator (2) -> Swappable Iterator and Incrementable Iterator + ``swap_ranges`` Forward Iterator -> Forward Traversal Iterator and Readable Iterator and Writable Iterator ``remove, remove_if, unique`` Forward Iterator -> Single Pass Iterator and Readable Iterator and Writable Iterator + ``replace, replace_if`` Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator @@ -168,6 +176,7 @@ Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable and Swap Bidirectional Iterator (1) -> Bidirectional Traversal Iterator and Readable Iterator, Bidirectional Iterator (2) -> Bidirectional Traversal Iterator and Writable Iterator + ``copy_backwards`` Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator and Readable Iterator @@ -313,22 +322,25 @@ for the value type ``T`` if the following expressions are valid and respect the stated semantics. ``U`` is the type of any specified member of type ``T``. - +------------------------------------------------------------------------------------------------------------------------------------------------------------+ - | Readable Iterator Requirements (in addition to CopyConstructible) | - +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ - | Expression | Return Type | Assertion/Note/Precondition/Postcondition | - +======================================+===================================================+=================================================================+ - | ``iterator_traits::value_type`` | ``T`` | Any non-reference, non-cv-qualified type | - +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ - | ``iterator_traits::reference`` | Convertible to ``iterator_traits::value_type`` | | - +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ - | ``access_category::type`` | Convertible to ``readable_iterator_tag`` | | - +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ - | ``*a`` | ``iterator_traits::reference`` | pre: ``a`` is dereferenceable. If ``a == b`` then | - | | | ``*a`` is equivalent to ``*b`` | - +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ - | ``a->m`` | ``U&`` | pre: ``(*a).m`` is well-defined. Equivalent to ``(*a).m`` | - +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + +-------------------------------------------------------------------------------------------------------------------+ + |Readable Iterator Requirements (in addition to CopyConstructible) | + +--------------------------------------+----------------------------------+-----------------------------------------+ + |Expression |Return Type |Assertion/Note/Precondition/Postcondition| + +======================================+==================================+=========================================+ + |``iterator_traits::value_type`` |``T`` |Any non-reference, non-cv-qualified type | + +--------------------------------------+----------------------------------+-----------------------------------------+ + |``iterator_traits::reference`` |Convertible to | | + | |``iterator_traits::value_type``| | + +--------------------------------------+----------------------------------+-----------------------------------------+ + |``access_category::type`` |Convertible to | | + | |``readable_iterator_tag`` | | + +--------------------------------------+----------------------------------+-----------------------------------------+ + |``*a`` |``iterator_traits::reference`` |pre: ``a`` is dereferenceable. If ``a == | + | | |b`` then ``*a`` is equivalent to ``*b`` | + +--------------------------------------+----------------------------------+-----------------------------------------+ + |``a->m`` |``U&`` |pre: ``(*a).m`` is well-defined. | + | | |Equivalent to ``(*a).m`` | + +--------------------------------------+----------------------------------+-----------------------------------------+ .. _Writable Iterator: @@ -350,16 +362,18 @@ semantics. to have a meaningful value_type? If not, we need to use a different name from ``v`` in this table -DWA -+------------------------------------------------------------------------------------------------------------------------------+ -| Writable Iterator Requirements (in addition to CopyConstructible) | -+--------------------------------------+------------------------------------------+--------------------------------------------+ -| Expression | Return Type | Assertion/Note/Precondition/Postcondition | -+======================================+==========================================+============================================+ -| ``access_category::type`` | Convertible to ``writable_iterator_tag`` | | -+--------------------------------------+------------------------------------------+--------------------------------------------+ -| ``*a = v`` | | .. ** pre: The type of ``v`` is in the set | -| | | of value types of ``X`` | -+--------------------------------------+------------------------------------------+--------------------------------------------+ + +---------------------------------------------------------------------------------------------+ + |Writable Iterator Requirements (in addition to CopyConstructible) | + +--------------------------------------+-------------------------+----------------------------+ + |Expression |Return Type |Precondition | + +======================================+=========================+============================+ + |``access_category::type`` |Convertible to | | + | |``writable_iterator_tag``| | + +--------------------------------------+-------------------------+----------------------------+ + |``*a = v`` | |.. ** pre: The type of ``v``| + | | | is in the set | + | | | of value types of ``X`` | + +--------------------------------------+-------------------------+----------------------------+ Swappable Iterators [lib.swappable.iterators] @@ -370,11 +384,11 @@ if the following expressions are valid and respect the stated semantics. +------------------------------------------------------------------------------------------------+ - | Swappable Iterator Requirements (in addition to CopyConstructible) | + |Swappable Iterator Requirements (in addition to CopyConstructible) | +------------------------------------+-------------+---------------------------------------------+ - | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + |Expression |Return Type |Postcondition | +====================================+=============+=============================================+ - | ``iter_swap(a, b)`` | ``void`` | post: the pointed to values are exchanged | + |``iter_swap(a, b)`` |``void`` |post: the pointed to values are exchanged | +------------------------------------+-------------+---------------------------------------------+ [*Note:* An iterator that is a model of the *Readable* and *Writable Iterator* concepts @@ -387,16 +401,19 @@ Readable Lvalue Iterators [lib.readable.lvalue.iterators] The *Readable Lvalue Iterator* concept adds the requirement that the ``reference`` type be a reference to the value type of the iterator. - +--------------------------------------------------------------------------------------------------------------------------------------------------+ - | Readable Lvalue Iterator Requirements (in addition to Readable Iterator) | - +------------------------------------+-------------------------------------------------+-----------------------------------------------------------+ - | Expression | Return Type | Assertion/Note/Precondition/Postcondition | - +====================================+=================================================+===========================================================+ - | ``iterator_traits::reference`` | ``T&`` | ``T`` is *cv* ``iterator_traits::value_type`` where | - | | | *cv* is an optional cv-qualification | - +------------------------------------+-------------------------------------------------+-----------------------------------------------------------+ - | ``access_category::type`` | Convertible to ``readable_lvalue_iterator_tag`` | | - +------------------------------------+-------------------------------------------------+-----------------------------------------------------------+ + +----------------------------------------------------------------------------------------------------------+ + |Readable Lvalue Iterator Requirements (in addition to Readable Iterator) | + +------------------------------------+---------------------------------+-----------------------------------+ + |Expression |Return Type |Assertion | + +====================================+=================================+===================================+ + |``iterator_traits::reference`` |``T&`` |``T`` is *cv* | + | | |``iterator_traits::value_type`` | + | | |where *cv* is an optional | + | | |cv-qualification | + +------------------------------------+---------------------------------+-----------------------------------+ + |``access_category::type`` |Convertible to | | + | |``readable_lvalue_iterator_tag`` | | + +------------------------------------+---------------------------------+-----------------------------------+ Writable Lvalue Iterators [lib.writable.lvalue.iterators] @@ -406,15 +423,17 @@ The *Writable Lvalue Iterator* concept adds the requirement that the ``reference`` type be a non-const reference to the value type of the iterator. - +------------------------------------------------------------------------------------------------------------------------------------------------------+ - | Writable Lvalue Iterator Requirements (in addition to Readable Lvalue Iterator) | - +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ - | Expression | Return Type | Assertion/Note/Precondition/Postcondition | - +======================================+==================================================+============================================================+ - | ``iterator_traits::reference`` | ``iterator_traits::value_type&`` | | - +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ - | ``access_category::type`` | Convertible to ``writable_lvalue_iterator_tag`` | | - +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + + +--------------------------------------------------------------------------------------+ + | Writable Lvalue Iterator Requirements (in addition to Readable Lvalue Iterator) | + +--------------------------------------+-----------------------------------------------+ + | Expression | Return Type | + +======================================+===============================================+ + |``iterator_traits::reference`` |``iterator_traits::value_type&`` | + +--------------------------------------+-----------------------------------------------+ + |``access_category::type`` |Convertible to ``writable_lvalue_iterator_tag``| + | | | + +--------------------------------------+-----------------------------------------------+ Iterator Traversal Concepts [lib.iterator.traversal] @@ -434,17 +453,17 @@ concept if the following expressions are valid and respect the stated semantics. - +------------------------------------------------------------------------------------------------------------------------------------------------------+ - | Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible) | - +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ - | Expression | Return Type | Assertion/Note/Precondition/Postcondition | - +======================================+==================================================+============================================================+ - | ``++r`` | ``X&`` | ``&r == &++r`` | - +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ - | ``r++`` | convertible to ``const X&`` | ``{ X tmp = r; ++r; return tmp; }`` | - +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ - | ``traversal_category::type`` | | Convertible to ``incrementable_iterator_tag`` | - +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + +-------------------------------------------------------------------------------------------------------------------------+ + |Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible) | + +--------------------------------+---------------------------------------------+------------------------------------------+ + |Expression |Return Type |Assertion/Semantics | + +================================+=============================================+==========================================+ + |``++r`` |``X&`` |``&r == &++r`` | + +--------------------------------+---------------------------------------------+------------------------------------------+ + |``r++`` |``X`` |``{ X tmp = r; ++r; return tmp; }`` | + +--------------------------------+---------------------------------------------+------------------------------------------+ + |``traversal_category::type`` |Convertible to ``incrementable_iterator_tag``| | + +--------------------------------+---------------------------------------------+------------------------------------------+ Single Pass Iterators [lib.single.pass.iterators] @@ -454,19 +473,24 @@ A class or built-in type ``X`` models the *Single Pass Iterator* concept if the following expressions are valid and respect the stated semantics. - +------------------------------------------------------------------------------------------------------------------------------------------------------+ - | Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality Comparable) | - +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ - | Expression | Return Type | Assertion/Note/Precondition/Postcondition/Semantics | - +==================================+=========================+=========================================================================================+ - | ``++r`` | ``X&`` | pre: ``r`` is dereferenceable; post: ``r`` is dereferenceable or ``r`` is past-the-end | - +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ - | ``a == b`` | convertible to ``bool`` | ``==`` is an equivalence relation over its domain | - +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ - | ``a != b`` | convertible to ``bool`` | ``!(a == b)`` | - +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ - | ``traversal_category::type`` | | Convertible to ``single_pass_iterator_tag`` | - +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + + +--------------------------------------------------------------------------------------------------------+ + |Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality Comparable) | + +----------------------------------+----------------------------+----------------------------------------+ + |Expression |Return Type |Assertion/Semantics/Pre-/Post-condition | + +==================================+============================+========================================+ + |``++r`` |``X&`` |pre: ``r`` is dereferenceable; post: | + | | |``r`` is dereferenceable or ``r`` is | + | | |past-the-end | + +----------------------------------+----------------------------+----------------------------------------+ + |``a == b`` |convertible to ``bool`` |``==`` is an equivalence relation over | + | | |its domain | + +----------------------------------+----------------------------+----------------------------------------+ + |``a != b`` |convertible to ``bool`` |``!(a == b)`` | + +----------------------------------+----------------------------+----------------------------------------+ + |``traversal_category::type`` |Convertible to | | + | |``single_pass_iterator_tag``| | + +----------------------------------+----------------------------+----------------------------------------+ Forward Traversal Iterators [lib.forward.traversal.iterators] @@ -476,19 +500,24 @@ A class or built-in type ``X`` models the *Forward Traversal Iterator* concept if the following expressions are valid and respect the stated semantics. - +----------------------------------------------------------------------------------------------------------------------------------+ - | Forward Traversal Iterator Requirements (in addition to Single Pass Iterator) | - +------------------------------------------+--------------+------------------------------------------------------------------------+ - | Expression | Return Type | Assertion/Note/Precondition/Postcondition/Semantics | - +==========================================+==============+========================================================================+ - | ``X u;`` | ``X&`` | ``note: u may have a singular value.`` | - +------------------------------------------+--------------+------------------------------------------------------------------------+ - | ``++r`` | ``X&`` | ``r == s`` and ``r`` is dereferenceable implies ``++r == ++s.`` | - +------------------------------------------+--------------+------------------------------------------------------------------------+ - | ``iterator_traits::difference_type`` | | A signed integral type representing the distance between iterators | - +------------------------------------------+--------------+------------------------------------------------------------------------+ - | ``traversal_category::type`` | | Convertible to ``forward_traversal_iterator_tag`` | - +------------------------------------------+--------------+------------------------------------------------------------------------+ + +------------------------------------------------------------------------------------------------------+ + |Forward Traversal Iterator Requirements (in addition to Single Pass Iterator) | + +---------------------------------------+-------------------------------------+------------------------+ + |Expression |Return Type |Assertion/Note | + +=======================================+=====================================+========================+ + |``X u;`` |``X&`` |``note: u may have a | + | | |singular value.`` | + +---------------------------------------+-------------------------------------+------------------------+ + |``++r`` |``X&`` |``r == s`` and ``r`` is | + | | |dereferenceable implies | + | | |``++r == ++s.`` | + +---------------------------------------+-------------------------------------+------------------------+ + |``iterator_traits::difference_type``|A signed integral type representing | | + | |the distance between iterators | | + +---------------------------------------+-------------------------------------+------------------------+ + |``traversal_category::type`` |Convertible to | | + | |``forward_traversal_iterator_tag`` | | + +---------------------------------------+-------------------------------------+------------------------+ Bidirectional Traversal Iterators [lib.bidirectional.traversal.iterators] @@ -498,23 +527,25 @@ A class or built-in type ``X`` models the *Bidirectional Traversal Iterator* concept if the following expressions are valid and respect the stated semantics. - +-------------------------------------------------------------------------------------------------------------+ - |Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal Iterator) | - +-----------------------------------------+-------------+-----------------------------------------------------+ - | Expression | Return Type | Assertion/Note/Precondition/Postcondition/Semantics | - +=========================================+=============+=====================================================+ - | ``--r`` | ``X&`` |pre: there exists ``s`` such that ``r == ++s``. | - | | |post: ``s`` is dereferenceable. ``--(++r) == r``. | - | | |``--r == --s`` implies ``r == s``. ``&r == &--r``. | - +-----------------------------------------+-------------+-----------------------------------------------------+ - |``r--`` |convertible |``{ X tmp = r; --r; return tmp; }`` | - | |to ``const | | - | |X&`` | | - +-----------------------------------------+-------------+-----------------------------------------------------+ - | ``traversal_category::type`` | | Convertible to | - | | | ``bidirectional_traversal_iterator_tag`` | - | | | | - +-----------------------------------------+-------------+-----------------------------------------------------+ + +----------------------------------------------------------------------------------------------------------------+ + |Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal Iterator) | + +-------------------------------+----------------------------------------+---------------------------------------+ + |Expression |Return Type |Assertion/Semantics/Pre-/Post-condition| + +===============================+========================================+=======================================+ + |``--r`` |``X&`` |pre: there exists ``s`` such that ``r | + | | |== ++s``. post: ``s`` is | + | | |dereferenceable. ``--(++r) == r``. | + | | |``--r == --s`` implies ``r == s``. ``&r| + | | |== &--r``. | + +-------------------------------+----------------------------------------+---------------------------------------+ + |``r--`` |convertible to ``const X&`` |``{ X tmp = r; --r; return tmp; }`` | + | | | | + | | | | + +-------------------------------+----------------------------------------+---------------------------------------+ + |``traversal_category::type``|Convertible to | | + | |``bidirectional_traversal_iterator_tag``| | + | | | | + +-------------------------------+----------------------------------------+---------------------------------------+ Random Access Traversal Iterators [lib.random.access.traversal.iterators] @@ -526,51 +557,56 @@ the stated semantics. In the table below, ``Distance`` is ``iterator_traits::difference_type`` and ``n`` represents a constant object of type ``Distance``. - +--------------------------------------------------------------------------------------------------------------------------------------------+ - | Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal Iterator) | - +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ - | Expression | Return Type | Operational Semantics | Assertion/Note/Pre/Post-condition | - +================================+=======================================+==========================+========================================+ - |``r += n`` | ``X&`` |:: | | - | | | | | - | | | { | | - | | | Distance m = n; | | - | | | if (m >= 0) | | - | | | while (m--) | | - | | | ++r; | | - | | | else | | - | | | while (m++) | | - | | | --r; | | - | | | return r; | | - | | | } | | - +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ - | ``a + n``, ``n + a`` | ``X`` |``{ X tmp = a; return tmp | | - | | |+= n; }`` | | - +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ - |``r -= n`` | ``X&`` |``return r += -n`` | | - +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ - |``a - n`` | ``X`` |``{ X tmp = a; return tmp | | - | | |-= n; }`` | | - +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ - |``b - a`` |``Distance`` |``a < b ? distance(a,b) : |pre: there exists a value ``n`` of | - | | |-distance(b,a)`` |``Distance`` such that ``a + n == b``. | - | | | |``b == a + (b - a)``. | - +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ - |``a[n]`` |convertible to T |``*(a + n)`` |pre: a is a `readable iterator`_ | - +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ - |``a[n] = v`` |convertible to T |``*(a + n) = v`` |pre: a is a `writable iterator`_ | - +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ - |``a < b`` |convertible to ``bool`` |``b - a > 0`` |``<`` is a total ordering relation | - +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ - |``a > b`` |convertible to ``bool`` |``b < a`` |``>`` is a total ordering relation | - +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ - |``a >= b`` |convertible to ``bool`` |``!(a < b)`` | | - +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ - |``a <= b`` |convertible to ``bool`` |``!(a > b)`` | | - +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ - |``traversal_category::type`` | | |Convertible to | - | | | |``random_access_traversal_iterator_tag``| - +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + +------------------------------------------------------------------------------------------------------------------------------+ + |Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal Iterator) | + +--------------------------------+----------------------------------------+----------------------+-----------------------------+ + | Expression |Return Type | Operational Semantics| Assertion/Precondition | + +================================+========================================+======================+=============================+ + |``r += n`` |``X&`` |:: | | + | | | | | + | | | { | | + | | | Distance m = n; | | + | | | if (m >= 0) | | + | | | while (m--) | | + | | | ++r; | | + | | | else | | + | | | while (m++) | | + | | | --r; | | + | | | return r; | | + | | | } | | + +--------------------------------+----------------------------------------+----------------------+-----------------------------+ + | ``a + n``, ``n + a`` |``X`` |``{ X tmp = a; return | | + | | |tmp += n; }`` | | + +--------------------------------+----------------------------------------+----------------------+-----------------------------+ + |``r -= n`` |``X&`` |``return r += -n`` | | + +--------------------------------+----------------------------------------+----------------------+-----------------------------+ + |``a - n`` |``X`` |``{ X tmp = a; return | | + | | |tmp -= n; }`` | | + +--------------------------------+----------------------------------------+----------------------+-----------------------------+ + |``b - a`` |``Distance`` |``a < b ? |pre: there exists a value | + | | |distance(a,b) : |``n`` of ``Distance`` such | + | | |-distance(b,a)`` |that ``a + n == b``. ``b == | + | | | |a + (b - a)``. | + +--------------------------------+----------------------------------------+----------------------+-----------------------------+ + |``a[n]`` |convertible to T |``*(a + n)`` |pre: a is a `readable | + | | | |iterator`_ | + +--------------------------------+----------------------------------------+----------------------+-----------------------------+ + |``a[n] = v`` |convertible to T |``*(a + n) = v`` |pre: a is a `writable | + | | | |iterator`_ | + +--------------------------------+----------------------------------------+----------------------+-----------------------------+ + |``a < b`` |convertible to ``bool`` |``b - a > 0`` |``<`` is a total ordering | + | | | |relation | + +--------------------------------+----------------------------------------+----------------------+-----------------------------+ + |``a > b`` |convertible to ``bool`` |``b < a`` |``>`` is a total ordering | + | | | |relation | + +--------------------------------+----------------------------------------+----------------------+-----------------------------+ + |``a >= b`` |convertible to ``bool`` |``!(a < b)`` | | + +--------------------------------+----------------------------------------+----------------------+-----------------------------+ + |``a <= b`` |convertible to ``bool`` |``!(a > b)`` | | + +--------------------------------+----------------------------------------+----------------------+-----------------------------+ + |``traversal_category::type`` |Convertible to | | | + | |``random_access_traversal_iterator_tag``| | | + +--------------------------------+----------------------------------------+----------------------+-----------------------------+ From f19c1c40595c9c0bf679e850cc8fea9aa8508f25 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 13 Jul 2003 01:27:38 +0000 Subject: [PATCH 178/265] Moved enable_if to boost::iterators from boost::detail to avoid conflicting with the definition in the function library. [SVN r19092] --- include/boost/iterator/detail/enable_if.hpp | 4 ++-- include/boost/iterator/filter_iterator.hpp | 4 ++-- include/boost/iterator/iterator_adaptor.hpp | 4 ++-- include/boost/iterator/transform_iterator.hpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/boost/iterator/detail/enable_if.hpp b/include/boost/iterator/detail/enable_if.hpp index d939fbb..f0a7bc7 100644 --- a/include/boost/iterator/detail/enable_if.hpp +++ b/include/boost/iterator/detail/enable_if.hpp @@ -23,7 +23,7 @@ namespace boost { - namespace detail + namespace iterators { // // Base machinery for all kinds of enable if @@ -79,7 +79,7 @@ namespace boost # endif }; - } // namespace detail + } // namespace iterators } // namespace boost diff --git a/include/boost/iterator/filter_iterator.hpp b/include/boost/iterator/filter_iterator.hpp index 547513f..5b16bb1 100644 --- a/include/boost/iterator/filter_iterator.hpp +++ b/include/boost/iterator/filter_iterator.hpp @@ -59,7 +59,7 @@ namespace boost // don't provide this constructor if UnaryFunction is a // function pointer type. Too dangerous. filter_iterator( - typename detail::enable_if< + typename iterators::enable_if< is_class , Iterator >::type x @@ -114,7 +114,7 @@ namespace boost template filter_iterator make_filter_iterator( - typename detail::enable_if< + typename iterators::enable_if< is_class , Iterator >::type x diff --git a/include/boost/iterator/iterator_adaptor.hpp b/include/boost/iterator/iterator_adaptor.hpp index d9a6263..faecc1a 100644 --- a/include/boost/iterator/iterator_adaptor.hpp +++ b/include/boost/iterator/iterator_adaptor.hpp @@ -98,7 +98,7 @@ namespace boost // of is_convertible in a few cases. template struct enable_if_convertible - : detail::enable_if< + : iterators::enable_if< mpl::or_< is_same , is_convertible @@ -111,7 +111,7 @@ namespace boost template struct enable_if_convertible - : detail::enable_if< + : iterators::enable_if< is_convertible , detail::enable_type > diff --git a/include/boost/iterator/transform_iterator.hpp b/include/boost/iterator/transform_iterator.hpp index f560116..e0ab3dd 100644 --- a/include/boost/iterator/transform_iterator.hpp +++ b/include/boost/iterator/transform_iterator.hpp @@ -124,7 +124,7 @@ namespace boost && BOOST_WORKAROUND(__GNUC_MINOR__, BOOST_TESTED_AT(2)) Iterator const& x #else - typename detail::enable_if< + typename iterators::enable_if< is_class , Iterator const& >::type x @@ -163,7 +163,7 @@ namespace boost // don't provide this generator if UnaryFunction is a // function pointer type. Too dangerous. We should probably // find a cheaper test than is_class<> - typename detail::enable_if< + typename iterators::enable_if< is_class , transform_iterator >::type From 22257870930e69a94a9d58e7e99317165d9dc363 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 13 Jul 2003 20:22:47 +0000 Subject: [PATCH 179/265] Fix detail::enable_if -> iterator::enable_if [SVN r19101] --- include/boost/iterator/iterator_facade.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index 1abe0e0..37211c2 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -47,7 +47,7 @@ namespace boost > struct enable_if_interoperable #ifndef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY - : ::boost::detail::enable_if< + : ::boost::iterator::enable_if< mpl::or_< is_convertible , is_convertible From e5eaaf6a55f2a84230174b79ccf7482ac291075c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 13 Jul 2003 21:45:33 +0000 Subject: [PATCH 180/265] Fix detail::enable_if -> iterators::enable_if (really this time) ^ [SVN r19102] --- include/boost/iterator/iterator_facade.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index 37211c2..21f99c7 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -47,7 +47,7 @@ namespace boost > struct enable_if_interoperable #ifndef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY - : ::boost::iterator::enable_if< + : ::boost::iterators::enable_if< mpl::or_< is_convertible , is_convertible From 9db269bb5b5bfdd269428a4cc3c3ca4fb1a65b2a Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 13 Jul 2003 21:50:30 +0000 Subject: [PATCH 181/265] iterator-categories.html is obsolete. [SVN r19103] --- doc/iterator-categories.html | 822 ----------------------------------- 1 file changed, 822 deletions(-) delete mode 100644 doc/iterator-categories.html diff --git a/doc/iterator-categories.html b/doc/iterator-categories.html deleted file mode 100644 index eb76523..0000000 --- a/doc/iterator-categories.html +++ /dev/null @@ -1,822 +0,0 @@ - -Improved Iterator Categories and Requirements - - - -

-
Improved Iterator Categories and Requirements

-

Introduction

The standard iterator categories and requirements are -flawed because they use a single hierarchy of requirements to address two -orthogonal issues: iterator traversal and dereference return -type. The current iterator requirement hierarchy is mainly geared -towards iterator traversal (hence the category names), while requirements that -address dereference return type sneak in at various places. The following table -gives a summary of the current dereference return type requirements in the -iterator categories. -

-

- - - - - - - - - - - - - - -
Output Iterator*i = a
Input Iterator*i is convertible to T
Forward Iterator*i is T& (or const T& once issue - 200 is resolved)
Random Access Iteratori[n] is convertible to T (which is odd because the - operational semantics say i[n] is equivalent to *(i + n) - which would have a return type of T&)
Table 1. Summary of current dereference return type - requirements.
-

Examples of useful iterators that do not ``fit''

-

Because of the mixing of iterator traversal and dereference return type, many -useful iterators can not be appropriately categorized. For example, -vector<bool>::iterator is almost a random access iterator, but -the return type is not bool& (see -issue 96 -and Herb Sutter's paper J16/99-0008 = WG21 N1185). Therefore, the -iterators only meet the requirements of input iterator and output iterator. This -is so nonintuitive that at least one implementation erroneously assigns -random_access_iterator_tag as its iterator_category. Also, -vector<bool> is not the only example of useful iterators that do -not return true references: there is the often cited example of disk-based -collections. -

Another example is a counting iterator, an iterator the returns a sequence of -integers when incremented and dereferenced (see boost::counting_iterator). -There are two ways to implement this iterator, 1) make the reference -type be a true reference (a reference to an integer data member of the counting -iterator) or 2) make the reference type be the same as the -value_type. Option 1) runs into the problems discussed in Issue -198, the reference will not be valid after the iterator is destroyed. Option -2) is therefore a better choice, but then we have a counting iterator that -cannot be a random access iterator. -

Yet another example is a transform iterator, an iterator adaptor that applies -a unary function object to the dereference value of the wrapped iterator (see boost::transform_iterator). -For unary functions such as std::times the return type of -operator* clearly needs to be the result_type of the function -object, which is typically not a reference. However, with the current iterator -requirements, if you wrap int* with a transform iterator, you do not -get a random access iterator as expected, but an input iterator. -

A fourth example is found in the vertex and edge iterators of the Boost Graph -Library. These iterators return vertex and edge descriptors, which are -lightweight handles created on-the-fly. They must be returned by-value. As a -result, their current standard iterator category is -std::input_iterator_tag, which means that, strictly speaking, you could -not use these iterators with algorithms like std::min_element(). As a -temporary solution, we introduced the concept Multi-Pass -Input Iterator to describe the vertex and edge descriptors, but as the -design notes for concept suggest, a better solution is needed. -

In short, there are many useful iterators that do not fit into the current -standard iterator categories. As a result, the following bad things happen: -

    -
  • Iterators are often miss-categorized. -
  • Algorithm requirements are more strict than necessary, because they can - not separate out the need for random-access from the need for a true reference - return type.
-

Proposal for new iterator categories and requirements

The iterator -requirements should be separated into two hierarchies. One set of concepts -handles the return type semantics: -The other set of concepts handles iterator -traversal: - - -

The current Input Iterator and Output Iterator requirements will -continue to be used as is. Note that Input Iterator implies Readable -Iterator and Output Iterator implies Writable Iterator.

- -

Note: we considered defining a Single-Pass Iterator, which could be -combined with Readable or Writable Iterator to replace the Input and -Output Iterator requirements. We rejected this idea because there are -several differences between Input and Output Iterators that make it -hard to merge them: Input Iterator requires Equality Comparable while -Output Iterator does not and Input Iterator requires Assignable while -Output Iterator does not.

- -

New category tags and traits classes

- -

The new iterator categories will require new tag classes.

- -
namespace std {
-
-  // Returns Category Tags
-  struct readable_iterator_tag { };
-  struct writable_iterator_tag { };
-  struct swappable_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 { };
-
-  // Traversal Category Tags
-  struct input_traversal_tag { };
-  struct output_traversal_tag { };
-  struct forward_traversal_tag { };
-  struct bidirectional_traversal_tag : public forward_traversal_tag { };
-  struct random_access_traversal_tag : public bidirectional_traversal_tag { };
-
-}
-
- -

Access to the return and traversal tags will be through the -following two traits classes, which have a member typedef named -type that provides the tag type. We explain the -definitions of these classes later.

- -
-  template <typename Iterator>
-  struct return_category; // contains: typedef ... type;
-
-  template <typename Iterator>
-  struct traversal_category; // contains: typedef ... type;
-
- -

We want it to be convenient for programmers to create iterators -that satisfy both the old and new iterator requirements. Therefore -the following class is provided as a way to create tags for use as the -old iterator_category typedef within -iterator_traits. - -

namespace std {
-  template <class ReturnTag, class TraversalTag>
-  struct iterator_tag : cvt_iterator_category<ReturnTag, TraversalTag>::type
-  {
-    typedef ReturnTag returns;
-    typedef TraversalTag traversal;
-  };
-
- -

The cvt_iterator_category template computes the -appropriate old iterator category based on the return and traversal -category.

- -
namespace std {
-  template <class RC, class TC>
-  struct cvt_iterator_category
-  {
-    // Pseudo-code, <= means inherits or same type
-    if (RC <= constant_lvalue_iterator_tag || RC <= mutable_lvalue_iterator_tag) {
-      if (TC <= random_access_traversal_tag)
-        typedef random_access_iterator_tag type;
-      else if (TC <= bidirectional_traversal_tag)
-        typedef bidirectional_iterator_tag type;
-      else if (TC <= forward_traversal_tag)
-        typedef forward_iterator_tag type;
-      else
-        error;
-   } else if (RC <= readable_iterator_tag && RC <= input_traversal_tag)
-     typedef input_iterator_tag type;
-   else if (RC <= writable_iterator_tag && output_traversal_tag)
-     typedef output_iterator_tag type;
-   else
-     error;
-  };
-}
-
- -

The following is an example of a new iterator class using the -iterator_tag class to create its iterator_category -member typedef.

- -
-struct my_iterator {
-  typedef std::iterator_tag<std::readable_iterator_tag, 
-    std::random_access_traversal_tag> iterator_category;
-  ...
-};
-
- -We also want old iterators to work with new algorithms, that is, -algorithms that use the new iterator categories. We facilitate this by -defining the return_category and traversal_category -in such a way as they can be used with both old and new iterators. -For old iterators, the appropriate return and traversal categories are -computed based on the old iterator category. For new iterators, the -return and traversal tags are extracted from within the -iterator_category tag. - - -
-  template <typename Iterator>
-  class return_category
-  {
-    // Pseudo-code
-    typedef iterator_traits<Iterator>::iterator_category tag;
-    typedef iterator_traits<Iterator>::value_type T;
-  public:
-    if (exists(tag::returns)) // must be a new iterator
-      typedef tag::returns type;
-    else if (tag <= forward_iterator_tag) {
-      if (is-const(T))
-        typedef constant_lvalue_iterator_tag type;
-      else
-        typedef mutable_lvalue_iterator_tag type;
-    } else if (tag <= input_iterator_tag)
-      typedef readable_iterator_tag type;
-    else if (tag <= output_iterator_tag)
-      typedef writable_iterator_tag type;
-    else
-      error;
-  };
-
-  template <typename T>
-  struct return_category<T*>
-  {
-    // Pseudo-code
-    if (is-const(T))
-      typedef boost::constant_lvalue_iterator_tag type;
-    else
-      typedef boost::mutable_lvalue_iterator_tag type;
-  };
-
-  template <typename Iterator>
-  class traversal_category
-  {
-    typedef iterator_traits<Iterator>::iterator_category tag;
-  public:
-    // Pseudo-code
-    if (exists(tag::traversal)) // must be a new iterator
-      typedef tag::traversal type;
-    else if (tag <= random_access_iterator_tag)
-      typedef random_access_traversal_tag type;
-    else if (tag <= bidirectional_iterator_tag)
-      typedef bidirectional_traversal_tag type;
-    else if (tag <= is_forward_iterator_tag)
-      typedef forward_traversal_tag type;
-    else if (tag <= input_iterator_tag)
-      typedef input_traversal_tag type;
-    else if (tag <= out_iterator_tag)
-      typedef output_traversal_tag type;
-    else
-      error;
-  };
-
-  template <typename T>
-  struct traversal_category<T*>
-  {
-    typedef random_access_traversal_tag type;
-  };
-
- -

Impact on the Standard Algorithms

- -

Many of the standard algorithms place more requirements than -necessary on their iterator parameters due to the coarseness of the -current iterator categories. By using the new iterator categories a -better fit can be achieved, thereby increasing the reusability of the -algorithms. These changes will not affect user-code, though they will -require changes by standard implementers: dispatching should be based -on the new categories, and in places return values may need to be -handled more carefully. In particular, uses of std::swap() -will need to be replaced with std::iter_swap(), and -std::iter_swap() will need to call std::swap().

- -

-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AlgorithmRequirement Change
find_endForward Iterator
-> Forward Traversal Iterator and - Readable Iterator
find_first_of
adjacent_find
search
search_n
rotate_copy
lower_bound
upper_bound
equal_range
binary_search
min_element
max_element
iter_swapForward Iterator
-> Swappable Iterator
fillForward Iterator
-> Forward Traversal Iterator and - Writable Iterator
generate
swap_rangesForward Iterator
-> Forward Traversal Iterator and - Swappable Iterator
rotate
replaceForward Iterator
-> Forward Traversal Iterator - and
Readable Iterator and Writable Iterator
replace_if
remove
remove_if
unique
reverseBidirectional Iterator
-> Bidirectional Traversal - Iterator and Swappable Iterator
partition
copy_backwardsBidirectional Iterator
-> Bidirectional Traversal Iterator and - Readable Iterator
Bidirectional Iterator
-> Bidirectional - Traversal Iterator and Writable Iterator
next_permutationBidirectional Iterator
-> Bidirectional Traversal - Iterator and
Swappable Iterator and Readable Iterator
prev_permutation
stable_partitionBidirectional Iterator
-> Bidirectional Traversal - Iterator and
Readable Iterator and Writable Iterator
inplace_merge
reverse_copyBidirectional Iterator
-> Bidirectional Traversal Iterator and - Readable Iterator
random_shuffleRandom Access Iterator
-> Random Access Traversal - Iterator and Swappable Iterator
sort
stable_sort
partial_sort
nth_element
push_heap
pop_heap
make_heap
sort_heap
Table 2. Requirement changes for standard - algorithms.
-

The New Iterator Requirements

-

Notation

- - - - - - - - - - - - - -
XThe iterator type.
TThe value type of X, i.e., - std::iterator_traits<X>::value_type.
x, yAn object of type X.
tAn object of type T.
-

-


- -

Readable Iterator

A Readable -Iterator is an iterator that dereferences to produce an rvalue that is -convertible to the value_type of the iterator. -

Associated Types

- - - - - - - - - - - - - -
Value typestd::iterator_traits<X>::value_typeThe type of the objects pointed to by the iterator.
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator. This type must be - convertible to T.
Return Categorystd::return_category<X>::typeA type convertible to std::readable_iterator_tag -
-

Refinement of

Copy -Constructible -

Valid expressions

- - - - - - - - - - - - - - - - -
NameExpressionType requirementsReturn type
Dereference*x std::iterator_traits<X>::reference
Member accessx->mT is a type with a member named m.If m is a data member, the type of m. If m - is a member function, the return type of m.
-

-


- -

Writable Iterator

A Writable -Iterator is an iterator that can be used to store a value using the -dereference-assignment expression. -

Definitions

If x is an Writable Iterator of type X, -then the expression *x = a; stores the value a into -x. Note that operator=, like other C++ functions, may be -overloaded; it may, in fact, even be a template function. In general, then, -a may be any of several different types. A type A belongs to -the set of value types of X if, for an object a of type -A, *x = a; is well-defined and does not require performing any -non-trivial conversions on a. -

Associated Types

- - - - - -
Return Categorystd::return_category<X>::typeA type convertible to std::writable_iterator_tag -
-

Refinement of

Copy -Constructible -

Valid expressions

- - - - - - - - - -
NameExpressionReturn type
Dereference assignment*x = aunspecified
-

-


- -

Swappable Iterator

A Swappable -Iterator is an iterator whose dereferenced values can be swapped. -

Note: the requirements for Swappable Iterator are dependent on the issues -surrounding std::swap() being resolved. Here we assume that the issue -will be resolved by allowing the overload of std::swap() for -user-defined types. -

Note: Readable Iterator and Writable Iterator combined implies Swappable -Iterator because of the fully templated std::swap(). However, Swappable -Iterator does not imply Readable Iterator nor Writable Iterator. -

Associated Types

- - - - - -
Return Categorystd::return_category<X>::typeA type convertible to std::swappable_iterator_tag -
-

Valid expressions

Of the two valid expressions listed below, only one -OR the other is required. If std::iter_swap() is overloaded for -X then std::swap() is not required. If -std::iter_swap() is not overloaded for X then the default -(fully templated) version is used, which will call std::swap() (this -means changing the current requirements for std::iter_swap()). -

- - - - - - - - - - - - - -
NameExpressionReturn type
Iterator Swapstd::iter_swap(x, y)void
Dereference and Swapstd::swap(*x, *y)void
-

-


- -

Constant Lvalue Iterator

A -Constant Lvalue Iterator is an iterator that dereferences to produce a const -reference to the pointed-to object, i.e., the associated reference type -is const T&. Changing the value of or destroying an iterator that -models Constant Lvalue Iterator does not invalidate pointers and references -previously obtained from that iterator. -

Refinement of

Readable -Iterator -

Associated Types

- - - - - - - - - -
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator, which must be const - T&.
Return Categorystd::return_category<X>::typeA type convertible to std::constant_lvalue_iterator_tag -
-

-


- -

Mutable Lvalue Iterator

A -Mutable Lvalue Iterator is an iterator that dereferences to produce a reference -to the pointed-to object. The associated reference type is -T&. Changing the value of or destroying an iterator that models -Mutable Lvalue Iterator does not invalidate pointers and references previously -obtained from that iterator. -

Refinement of

Readable -Iterator, Writable -Iterator, and Swappable -Iterator. -

Associated Types

- - - - - - - - - -
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator, which must be - T&.
Return Categorystd::return_category<X>::typeA type convertible to std::mutable_lvalue_iterator_tag -
-

-


- -

Forward Traversal Iterator -

The Forward Iterator is an iterator that can be incremented. Also, it is -permissible to make multiple passes through the iterator's range. -

Refinement of

Copy -Constructible, Assignable, Default -Constructible, and Equality -Comparable -

Associated types

- - - - - - - - - -
Difference Typestd::iterator_traits<X>::difference_typeA signed integral type used for representing distances between - iterators that point into the same range.
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::forward_traversal_tag -
-

Valid expressions

- - - - - - - - - - - - - - - - -
NameExpressionType requirementsReturn type
Preincrement++i X&
Postincrementi++ convertible to const X&
-

-


- -

Bidirectional Traversal -Iterator

An iterator that can be incremented and decremented. -

Refinement of

Forward -Traversal Iterator -

Associated types

- - - - - -
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::bidirectional_traversal_tag -
-

Valid expressions

- - - - - - - - - - - - - - - - -
NameExpressionType requirementsReturn type
Predecrement--i X&
Postdecrementi-- convertible to const X&
-

-


- -

Random Access Traversal -Iterator

An iterator that provides constant-time methods for moving forward -and backward in arbitrary-sized steps. -

Refinement of

Bidirectional -Traversal Iterator and Less Than -Comparable where < is a total ordering -

Associated types

- - - - - -
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::random_access_traversal_tag -
-

Valid expressions

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameExpressionType requirementsReturn type
Iterator additioni += n X&
Iterator additioni + n or n + i X
Iterator subtractioni -= n X&
Iterator subtractioni - n X
Differencei - j std::iterator_traits<X>::difference_type
Element operatori[n]X must also be a model of Readable - Iterator. std::iterator_traits<X>::reference
Element assignmenti[n] = tX must also be a model of Writable - Iterator.unspecified
-

-


- From a982c4230376346de5e5620313cde00d136fbd32 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 13 Jul 2003 22:47:15 +0000 Subject: [PATCH 182/265] Various updates and clarifications. [SVN r19106] --- doc/facade-and-adaptor.html | 2042 +++++++++++++++++++++++++++++++++++ doc/facade-and-adaptor.rst | 144 ++- doc/new-iter-concepts.html | 1133 +++++++++++++++++++ doc/new-iter-concepts.rst | 2 +- 4 files changed, 3264 insertions(+), 57 deletions(-) create mode 100755 doc/facade-and-adaptor.html create mode 100755 doc/new-iter-concepts.html diff --git a/doc/facade-and-adaptor.html b/doc/facade-and-adaptor.html new file mode 100755 index 0000000..996ea4c --- /dev/null +++ b/doc/facade-and-adaptor.html @@ -0,0 +1,2042 @@ + + + + + + +Iterator Facade and Adaptor + + + + + + + +
+

Iterator Facade and Adaptor

+ +++ + + + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2003-07-12
Number:This document is a revised version of the official N1476=03-0059
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
+ +++ + + + +
abstract:We propose a set of class templates that help programmers +build standard-conforming iterators, both from scratch and +by adapting other iterators.
+
+

Table of Contents

+ +
+
+

Motivation

+

Iterators play an important role in modern C++ programming. The +iterator is the central abstraction of the algorithms of the Standard +Library, allowing algorithms to be re-used in in a wide variety of +contexts. The C++ Standard Library contains a wide variety of useful +iterators. Every one of the standard containers comes with constant +and mutable iterators 2, and also reverse versions of those +same iterators which traverse the container in the opposite direction. +The Standard also supplies istream_iterator and +ostream_iterator for reading from and writing to streams, +insert_iterator, front_insert_iterator and +back_insert_iterator for inserting elements into containers, and +raw_storage_iterator for initializing raw memory [7].

+

Despite the many iterators supplied by the Standard Library, obvious +and useful iterators are missing, and creating new iterator types is +still a common task for C++ programmers. The literature documents +several of these, for example line_iterator [3] and Constant_iterator +[9]. The iterator abstraction is so powerful that we expect +programmers will always need to invent new iterator types.

+

Although it is easy to create iterators that almost conform to the +standard, the iterator requirements contain subtleties which can make +creating an iterator which actually conforms quite difficult. +Further, the iterator interface is rich, containing many operators +that are technically redundant and tedious to implement. To automate +the repetitive work of constructing iterators, we propose +iterator_facade, an iterator base class template which provides +the rich interface of standard iterators and delegates its +implementation to member functions of the derived class. In addition +to reducing the amount of code necessary to create an iterator, the +iterator_facade also provides compile-time error detection. +Iterator implementation mistakes that often go unnoticed are turned +into compile-time errors because the derived class implementation must +match the expectations of the iterator_facade.

+

A common pattern of iterator construction is the adaptation of one +iterator to form a new one. The functionality of an iterator is +composed of four orthogonal aspects: traversal, indirection, equality +comparison and distance measurement. Adapting an old iterator to +create a new one often saves work because one can reuse one aspect of +functionality while redefining the other. For example, the Standard +provides reverse_iterator, which adapts any Bidirectional Iterator +by inverting its direction of traversal. As with plain iterators, +iterator adaptors defined outside the Standard have become commonplace +in the literature:

+
    +
  • Checked iter[13] adds bounds-checking to an existing iterator.
  • +
  • The iterators of the View Template Library[14], which adapts +containers, are themselves adaptors over the underlying iterators.
  • +
  • Smart iterators [5] adapt an iterator's dereferencing behavior by +applying a function object to the object being referenced and +returning the result.
  • +
  • Custom iterators [4], in which a variety of adaptor types are enumerated.
  • +
  • Compound iterators [1], which access a slice out of a container of containers.
  • +
  • Several iterator adaptors from the MTL [12]. The MTL contains a +strided iterator, where each call to operator++() moves the +iterator ahead by some constant factor, and a scaled iterator, which +multiplies the dereferenced value by some constant.
  • +
+ + + + + +
[1]We use the term concept to mean a set of requirements +that a type must satisfy to be used with a particular template +parameter.
+ + + + + +
[2]The term mutable iterator refers to iterators over objects that +can be changed by assigning to the dereferenced iterator, while +constant iterator refers to iterators over objects that cannot be +modified.
+

To fulfill the need for constructing adaptors, we propose the +iterator_adaptor class template. Instantiations of +iterator_adaptor serve as a base classes for new iterators, +providing the default behavior of forwarding all operations to the +underlying iterator. The user can selectively replace these features +in the derived iterator class. This proposal also includes a number +of more specialized adaptors, such as the transform_iterator that +applies some user-specified function during the dereference of the +iterator.

+
+
+

Impact on the Standard

+

This proposal is purely an addition to the C++ standard library. +However, note that this proposal relies on the proposal for New +Iterator Concepts.

+
+
+

Design

+
+

Iterator Concepts

+

This proposal is formulated in terms of the new iterator concepts +as proposed in n1477, since user-defined and especially adapted +iterators suffer from the well known categorization problems that are +inherent to the current iterator categories.

+

This proposal does not strictly depend on proposal n1477, as there +is a direct mapping between new and old categories. This proposal +could be reformulated using this mapping if n1477 was not accepted.

+
+
+

Interoperability

+

The question of iterator interoperability is poorly addressed in the +current standard. There are currently two defect reports that are +concerned with interoperability issues.

+

Issue 179 concerns the fact that mutable container iterator types +are only required to be convertible to the corresponding constant +iterator types, but objects of these types are not required to +interoperate in comparison or subtraction expressions. This situation +is tedious in practice and out of line with the way built in types +work. This proposal implements the proposed resolution to issue +179, as most standard library implementations do nowadays. In other +words, if an iterator type A has an implicit or user defined +conversion to an iterator type B, the iterator types are interoperable +and the usual set of operators are available.

+

Issue 280 concerns the current lack of interoperability between +reverse iterator types. The proposed new reverse_iterator template +fixes the issues raised in 280. It provides the desired +interoperability without introducing unwanted overloads.

+
+
+

Iterator Facade

+

While the iterator interface is rich, there is a core subset of the +interface that is necessary for all the functionality. We have +identified the following core behaviors for iterators:

+
    +
  • dereferencing
  • +
  • incrementing
  • +
  • decrementing
  • +
  • equality comparison
  • +
  • random-access motion
  • +
  • distance measurement
  • +
+

In addition to the behaviors listed above, the core interface elements +include the associated types exposed through iterator traits: +value_type, reference, difference_type, and +iterator_category.

+

Iterator facade uses the Curiously Recurring Template Pattern (CRTP) +[Cop95] so that the user can specify the behavior of +iterator_facade in a derived class. Former designs used policy +objects to specify the behavior. The proposal does not use policy +objects for several reasons:

+
+
    +
  1. the creation and eventual copying of the policy object may create +overhead that can be avoided with the current approach.
  2. +
  3. The policy object approach does not allow for custom constructors +on the created iterator types, an essential feature if +iterator_facade should be used in other library +implementations.
  4. +
  5. Without the use of CRTP, the standard requirement that an +iterator's operator++ returns the iterator type itself means +that all iterators generated by iterator_facade would be +instantiations of iterator_facade. Cumbersome type generator +metafunctions would be needed to build new parameterized +iterators, and a separate iterator_adaptor layer would be +impossible.
  6. +
+
+
+

Usage

+

The user of iterator_facade derives his iterator class from an +instantiation of iterator_facade which takes the derived iterator +class as the first template parameter. The order of the other +template parameters to iterator_facade have been carefully chosen +to take advantage of useful defaults. For example, when defining a +constant lvalue iterator, the user can pass a const-qualified version +of the iterator's value_type as iterator_facade's Value +parameter and omit the Reference parameter which follows.

+

The derived iterator class must define member functions implementing +the iterator's core behaviors. The following table describes +expressions which are required to be valid depending on the category +of the derived iterator type. These member functions are described +briefly below and in more detail in the iterator facade +requirements.

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionEffects
i.dereference()Access the value referred to
i.equal(j)Compare for equality with j
i.increment()Advance by one position
i.decrement()Retreat by one position
i.advance(n)Advance by n positions
i.distance_to(j)Measure the distance to j
+
+ +

In addition to implementing the core interface functions, an iterator +derived from iterator_facade typically defines several +constructors. To model any of the standard iterator concepts, the +iterator must at least have a copy constructor. Also, if the iterator +type X is meant to be automatically interoperate with another +iterator type Y (as with constant and mutable iterators) then +there must be an implicit conversion from X to Y or from Y +to X (but not both), typically implemented as a conversion +constructor. Finally, if the iterator is to model Forward Traversal +Iterator or a more-refined iterator concept, a default constructor is +required.

+
+
+
+

Iterator Core Access

+

iterator_facade and the operator implementations need to be able +to access the core member functions in the derived class. Making the +core member functions public would expose an implementation detail to +the user. This proposal frees the public interface of the derived +iterator type from any implementation detail.

+

Preventing direct access to the core member functions has two +advantages. First, there is no possibility for the user to accidently +use a member function of the iterator when a member of the value_type +was intended. This has been an issue with smart pointer +implementations in the past. The second and main advantage is that +library implementers can freely exchange a hand-rolled iterator +implementation for one based on iterator_facade without fear of +breaking code that was accessing the public core member functions +directly.

+

In a naive implementation, keeping the derived class' core member +functions private would require it to grant friendship to +iterator_facade and each of the seven operators. In order to +reduce the burden of limiting access, this proposal provides +iterator_core_access, a class that acts as a gateway to the core +member functions in the derived iterator class. The author of the +derived class only needs to grant friendship to +iterator_core_access to make his core member functions available +to the library.

+ + +

iterator_core_access will be typically implemented as an empty +class containing only private static member functions which invoke the +iterator core member functions. There is, however, no need to +standardize the gateway protocol. Note that even if +iterator_core_access used public member functions it would not +open a safety loophole, as every core member function preserves the +invariants of the iterator.

+
+
+

operator[]

+

The indexing operator for a generalized iterator presents special +challenges. A random access iterator's operator[] is only +required to return something convertible to its value_type. +Requiring that it return an lvalue would rule out currently-legal +random-access iterators which hold the referenced value in a data +member (e.g. counting_iterator), because *(p+n) is a reference +into the temporary iterator p+n, which is destroyed when +operator[] returns.

+

Writable iterators built with iterator_facade implement the +semantics required by the preferred resolution to issue 299 and +adopted by proposal n1477: the result of p[n] is a proxy object +containing a copy of p+n, and p[n] = x is equivalent to *(p ++ n) = x. This approach will work properly for any random-access +iterator regardless of the other details of its implementation. A +user who knows more about the implementation of her iterator is free +to implement an operator[] which returns an lvalue in the derived +iterator class; it will hide the one supplied by iterator_facade +from clients of her iterator.

+
+
+

operator->

+

The reference type of a readable iterator (and today's input +iterator) need not in fact be a reference, so long as it is +convertible to the iterator's value_type. When the value_type +is a class, however, it must still be possible to access members +through operator->. Therefore, an iterator whose reference +type is not in fact a reference must return a proxy containing a copy +of the referenced value from its operator->.

+

This proposal does not explicitly specify the return type for +operator-> and operator[]. Instead it requires each +iterator_facade instantiation to meet the requirements of its +iterator_category.

+
+
+

Iterator Adaptor

+

The iterator_adaptor class template adapts some Base 3 +type to create a new iterator. Instantiations of iterator_adaptor +are derived from a corresponding instantiation of iterator_facade +and implement the core behaviors in terms of the Base type. In +essence, iterator_adaptor merely forwards all operations to an +instance of the Base type, which it stores as a member.

+ + + + + +
[3]The term "Base" here does not refer to a base class and is +not meant to imply the use of derivation. We have followed the lead +of the standard library, which provides a base() function to access +the underlying iterator object of a reverse_iterator adaptor.
+

The user of iterator_adaptor creates a class derived from an +instantiation of iterator_adaptor and then selectively +redefines some of the core member functions described in the table +above. The Base type need not meet the full requirements for an +iterator. It need only support the operations used by the core +interface functions of iterator_adaptor that have not been +redefined in the user's derived class.

+

Several of the template parameters of iterator_adaptor default to +use_default. This allows the user to make use of a default +parameter even when the user wants to specify a parameter later in the +parameter list. Also, the defaults for the corresponding associated +types are fairly complicated, so metaprogramming is required to +compute them, and use_default can help to simplify the +implementation. Finally, use_default is not left unspecified +because specification helps to highlight that the Reference +template parameter may not always be identical to the iterator's +reference type, and will keep users making mistakes based on that +assumption.

+
+
+

Specialized Adaptors

+

This proposal also contains several examples of specialized adaptors +which were easily implemented using iterator_adaptor:

+
    +
  • indirect_iterator, which iterates over iterators, pointers, +or smart pointers and applies an extra level of dereferencing.
  • +
  • A new reverse_iterator, which inverts the direction of a Base +iterator's motion, while allowing adapted constant and mutable +iterators to interact in the expected ways (unlike those in most +implementations of C++98).
  • +
  • transform_iterator, which applies a user-defined function object +to the underlying values when dereferenced.
  • +
  • projection_iterator, which is similar to transform_iterator +except that when dereferenced it returns a reference instead of +a value.
  • +
  • filter_iterator, which provides a view of an iterator range in +which some elements of the underlying range are skipped.
  • +
+
    +
  • counting_iterator, which adapts any incrementable type +(e.g. integers, iterators) so that incrementing/decrementing the +adapted iterator and dereferencing it produces successive values of +the Base type.
  • +
  • function_output_iterator, which makes it easier to create custom +output iterators.
  • +
+

Based on examples in the Boost library, users have generated many new +adaptors, among them a permutation adaptor which applies some +permutation to a random access iterator, and a strided adaptor, which +adapts a random access iterator by multiplying its unit of motion by a +constant factor. In addition, the Boost Graph Library (BGL) uses +iterator adaptors to adapt other graph libraries, such as LEDA [10] +and Stanford GraphBase [8], to the BGL interface (which requires C++ +Standard compliant iterators).

+
+
+
+

Proposed Text

+
+

Header <iterator_helper> synopsis [lib.iterator.helper.synopsis]

+
+struct use_default;
+
+struct iterator_core_access { /* implementation detail */ };
+
+template <
+    class Derived
+  , class Value
+  , class AccessCategory
+  , class TraversalCategory
+  , class Reference  = Value&
+  , class Difference = ptrdiff_t
+>
+class iterator_facade;
+
+template <
+    class Derived
+  , class Base
+  , class Value      = use_default
+  , class Category   = use_default
+  , class Reference  = use_default
+  , class Difference = use_default
+>
+class iterator_adaptor;
+
+template <
+    class Iterator
+  , class Value = use_default
+  , class Category = use_default
+  , class Reference = use_default
+  , class Difference = use_default
+>
+class indirect_iterator;
+
+template <class Iterator>
+class reverse_iterator;
+
+template <
+    class UnaryFunction
+  , class Iterator
+  , class Reference = use_default
+  , class Value = use_default
+>
+class transform_iterator;
+
+template <class Predicate, class Iterator>
+class filter_iterator;
+
+template <
+    class Incrementable
+  , class Category = use_default
+  , class Difference = use_default
+>
+class counting_iterator
+
+template <class UnaryFunction>
+class function_output_iterator;
+
+
+
+

Iterator facade [lib.iterator.facade]

+

iterator_facade is a base class template which implements the +interface of standard iterators in terms of a few core functions +and associated types, to be supplied by a derived iterator class.

+
+

Class template iterator_facade

+
+template <
+    class Derived
+  , class Value
+  , class AccessCategory
+  , class TraversalCategory
+  , class Reference  = /* see below */
+  , class Difference = ptrdiff_t
+>
+class iterator_facade {
+public:
+    typedef remove_cv<Value>::type value_type;
+    typedef Reference reference;
+    typedef /* see description of operator-> */ pointer;
+    typedef Difference difference_type;
+    typedef iterator_tag<AccessCategory, TraversalCategory> iterator_category;
+
+    reference operator*() const;
+    /* see below */ operator->() const;
+    /* see below */ operator[](difference_type n) const;
+    Derived& operator++();
+    Derived operator++(int);
+    Derived& operator--();
+    Derived operator--(int);
+    Derived& operator+=(difference_type n);
+    Derived& operator-=(difference_type n);
+    Derived operator-(difference_type n) const;
+};
+
+// Comparison operators
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type // exposition
+operator ==(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator !=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator <(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+           iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator <=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator >(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+           iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator >=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator >=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+// Iterator difference
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator -(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+           iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+// Iterator addition
+template <class Derived, class V, class AC, class TC, class R, class D>
+Derived operator+ (iterator_facade<Derived, V, AC, TC, R, D> const&,
+                   typename Derived::difference_type n)
+
+

[Note: The enable_if_interoperable template used above is for exposition +purposes. The member operators should be only be in an overload set +provided the derived types Dr1 and Dr2 are interoperable, by +which we mean they are convertible to each other. The +enable_if_interoperable approach uses SFINAE to take the operators +out of the overload set when the types are not interoperable.]

+ +
+
+

iterator_facade requirements

+

The Derived template parameter must be a class derived from +iterator_facade.

+

The default for the Reference parameter is Value& if the +access category for iterator_facade is implicitly convertible to +writable_iterator_tag, and const Value& otherwise.

+

The following table describes the other requirements on the +Derived parameter. Depending on the resulting iterator's +iterator_category, a subset of the expressions listed in the table +are required to be valid. The operations in the first column must be +accessible to member functions of class iterator_core_access.

+

In the table below, X is the derived iterator type, a is an +object of type X, b and c are objects of type const X, +n is an object of X::difference_type, y is a constant +object of a single pass iterator type interoperable with X, and z +is a constant object of a random access traversal iterator type +interoperable with X.

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionReturn TypeAssertion/NoteRequired to implement +Iterator Concept(s)
c.dereference()X::reference Readable Iterator, Writable +Iterator
c.equal(b)convertible to booltrue iff b and c are +equivalent.Single Pass Iterator
c.equal(y)convertible to booltrue iff c and y refer to the +same position. Implements c == y +and c != y.Single Pass Iterator
a.advance(n)unused Random Access Traversal +Iterator
a.increment()unused Incrementable Iterator
a.decrement()unused Bidirectional Traversal +Iterator
c.distance_to(b)convertible to +X::difference_typeequivalent to distance(c, b)Random Access Traversal +Iterator
c.distance_to(z)convertible to +X::difference_typeequivalent to distance(c, z). +Implements c - z, c < z, c +<= z, c > z, and c >= c.Random Access Traversal +Iterator
+ +
+
+

iterator_facade operations

+

The operations in this section are described in terms of operations on +the core interface of Derived which may be inaccessible +(i.e. private). The implementation should access these operations +through member functions of class iterator_core_access.

+

reference operator*() const;

+ +++ + + + +
Returns:static_cast<Derived const*>(this)->dereference()
+

operator->() const; (see below)

+ +++ + + + +
Returns:

If X::reference is a reference type, returns an object +of type X::pointer equal to:

+
+&static_cast<Derived const*>(this)->dereference()
+
+

Otherwise returns an object of unspecified type such that, given an +object a of type X, a->m is equivalent to (w = *a, +w.m) for some temporary object w of type X::value_type.

+

The type X::pointer is Value* if the access category for +X is implicitly convertible to writable_iterator_tag, and +Value const* otherwise.

+
+

unspecified operator[](difference_type n) const;

+ +++ + + + +
Returns:an object convertible to X::reference and holding a copy +p of a+n such that, for a constant object v of type +X::value_type, X::reference(a[n] = v) is equivalent +to p = v.
+

Derived& operator++();

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->increment();
+return *this;
+
+
+ +

Derived operator++(int);

+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+++*this;
+return tmp;
+
+
+

Derived& operator--();

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->decrement();
+return *this;
+
+
+

Derived operator--(int);

+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+--*this;
+return tmp;
+
+
+

Derived& operator+=(difference_type n);

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->advance(n);
+return *this;
+
+
+

Derived& operator-=(difference_type n);

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->advance(-n);
+return *this;
+
+
+

Derived operator-(difference_type n) const;

+ +++ + + + + + +
Effects:Derived tmp(static_cast<Derived const*>(this)); +return tmp -= n;
Returns:static_cast<Derived const*>(this)->advance(-n);
+
+
+
+

Iterator adaptor [lib.iterator.adaptor]

+

The iterator_adaptor is a base class template derived from an +instantiation of iterator_facade. The core interface functions +expected by iterator_facade are implemented in terms of the +iterator_adaptor's Base template parameter. A class derived +from iterator_adaptor typically redefines some of the core +interface functions to adapt the behavior of the Base type. +Whether the derived class models any of the standard iterator concepts +depends on the operations supported by the Base type and which +core interface functions of iterator_facade are redefined in the +Derived class.

+
+

Class template iterator_adaptor

+
+template <
+    class Derived
+  , class Base
+  , class Value      = use_default
+  , class Category   = use_default
+  , class Reference  = use_default
+  , class Difference = use_default
+>
+class iterator_adaptor 
+  : public iterator_facade<Derived, /* see details ...*/>
+{
+    friend class iterator_core_access;
+ public:
+    iterator_adaptor();
+    explicit iterator_adaptor(Base iter);
+    Base base() const;
+ protected:
+    Base const& base_reference() const;
+    Base& base_reference();
+ private: // Core iterator interface for iterator_facade.  
+    typename iterator_adaptor::reference dereference() const;
+
+    template <
+    class OtherDerived, class OtherIterator, class V, class C, class R, class D
+    >   
+    bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
+
+    void advance(typename iterator_adaptor::difference_type n);
+    void increment();
+    void decrement();
+
+    template <
+        class OtherDerived, class OtherIterator, class V, class C, class R, class D
+    >   
+    typename iterator_adaptor::difference_type distance_to(
+        iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
+
+ private:
+    Base m_iterator;
+};
+
+
+
+

iterator_adaptor requirements

+

The Derived template parameter must be a derived class of +iterator_adaptor. The Base type must implement the expressions +involving m_iterator in the specifications of those private member +functions of iterator_adaptor that are not redefined by the +Derived class and that are needed to model the concept +corresponding to the chosen Category according to the requirements +of iterator_facade. The rest of the template parameters specify +the types for the member typedefs in iterator_facade. The +following pseudo-code specifies the traits types for +iterator_adaptor.

+
+if (Value == use_default)
+    value_type = iterator_traits<Base>::value_type;
+else 
+    value_type = remove_cv<Value>::type;
+
+if (Reference == use_default) {
+    if (Value == use_default)
+        reference = iterator_traits<Base>::reference;
+    else 
+        reference = Value&;
+} else
+    reference = Reference;
+
+if (Distance == use_default)
+    difference_type = iterator_traits<Base>::difference_type;
+else
+    difference_type = Distance;
+
+if (Category == use_default)
+    iterator_category = iterator_tag< 
+        access_category< 
+            iterator< iterator_traits<Base>::iterator_category,
+                      Value,
+                      Distance,
+                      Value*,
+                      Reference > >,
+        traversal_category<
+            iterator< iterator_traits<Base>::iterator_category,
+                      Value,
+                      Distance,
+                      Value*,
+                      Reference > >
+else
+    iterator_category = Category;
+
+ +
+
+

iterator_adaptor public operations

+

iterator_adaptor();

+ +++ + + + + + +
Requires:The Base type must be Default Constructible.
Returns:An instance of iterator_adaptor with +m_iterator default constructed.
+

explicit iterator_adaptor(Base iter);

+ +++ + + + +
Returns:An instance of iterator_adaptor with +m_iterator copy constructed from iter.
+

Base base() const;

+ +++ + + + +
Returns:m_iterator
+
+
+

iterator_adaptor protected member functions

+

Base const& base_reference() const;

+ +++ + + + +
Returns:A const reference to m_iterator.
+

Base& base_reference();

+ +++ + + + +
Returns:A non-const reference to m_iterator.
+
+
+

iterator_adaptor private member functions

+

typename iterator_adaptor::reference dereference() const;

+ +++ + + + +
Returns:*m_iterator
+
+template <
+class OtherDerived, class OtherIterator, class V, class C, class R, class D
+>   
+bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
+
+ +++ + + + +
Returns:m_iterator == x.base()
+

void advance(typename iterator_adaptor::difference_type n);

+ +++ + + + +
Effects:m_iterator += n;
+

void increment();

+ +++ + + + +
Effects:++m_iterator;
+

void decrement();

+ +++ + + + +
Effects:--m_iterator;
+
+template <
+    class OtherDerived, class OtherIterator, class V, class C, class R, class D
+>   
+typename iterator_adaptor::difference_type distance_to(
+    iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
+
+ +++ + + + +
Returns:y.base() - m_iterator
+
+
+
+

Specialized adaptors [lib.iterator.special.adaptors]

+ +

[Note: The enable_if_convertible<X,Y>::type expression used in +this section is for exposition purposes. The converting constructors +for specialized adaptors should be only be in an overload set provided +that an object of type X is implicitly convertible to an object of +type Y. The enable_if_convertible approach uses SFINAE to +take the constructor out of the overload set when the types are not +implicitly convertible.]

+
+

Indirect iterator

+

The indirect iterator adapts an iterator by applying an extra +dereference inside of operator*(). For example, this iterator +adaptor makes it possible to view a container of pointers +(e.g. list<foo*>) as if it were a container of the pointed-to type +(e.g. list<foo>) .

+ +
+

Class template indirect_iterator

+
+template <
+    class Iterator
+  , class Value = use_default
+  , class Category = use_default
+  , class Reference = use_default
+  , class Difference = use_default
+>
+class indirect_iterator
+  : public iterator_adaptor</* see discussion */>
+{
+    friend class iterator_core_access;
+ public:
+    indirect_iterator();
+    indirect_iterator(Iterator x);
+    template <
+        class Iterator2, class Value2, class Category2
+      , class Reference2, class Difference2
+    >
+    indirect_iterator(
+        indirect_iterator<
+             Iterator2, Value2, Category2, Reference2, Difference2
+        > const& y
+      , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition
+    );
+private: // as-if specification
+    typename indirect_iterator::reference dereference() const
+    {
+        return **this->base();
+    }
+};
+
+
+
+

indirect_iterator requirements

+

The value_type of the Iterator template parameter should +itself be dereferenceable. The return type of the operator* for +the value_type must be the same type as the Reference template +parameter. The Value template parameter will be the value_type +for the indirect_iterator, unless Value is const. If Value +is const X, then value_type will be non- const X. The +default for Value is

+
+iterator_traits< iterator_traits<Iterator>::value_type >::value_type
+
+

If the default is used for Value, then there must be a valid +specialization of iterator_traits for the value type of the base +iterator.

+

The Reference parameter will be the reference type of the +indirect_iterator. The default is Value&.

+

The Category parameter is the iterator_category type for the +indirect_iterator. The default is +iterator_traits<Iterator>::iterator_category.

+

The indirect iterator will model the most refined standard traversal +concept that is modeled by the Iterator type. The indirect +iterator will model the most refined standard access concept that is +modeled by the value type of Iterator.

+
+
+

indirect_iterator operations

+

indirect_iterator();

+ +++ + + + + + +
Requires:Iterator must be Default Constructible.
Returns:An instance of indirect_iterator with +a default constructed base object.
+

indirect_iterator(Iterator x);

+ +++ + + + +
Returns:An instance of indirect_iterator with +the iterator_adaptor subobject copy constructed from x.
+
+template <
+    class Iterator2, class Value2, class Category2
+  , class Reference2, class Difference2
+>
+indirect_iterator(
+    indirect_iterator<
+         Iterator2, Value2, Category2, Reference2, Difference2
+    > const& y
+  , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition
+);
+
+ +++ + + + + + +
Requires:Iterator2 is implicitly convertible to Iterator.
Returns:An instance of indirect_iterator that is a copy of y.
+
+
+
+

Reverse iterator

+ +

The reverse iterator adaptor flips the direction of a base iterator's +motion. Invoking operator++() moves the base iterator backward and +invoking operator--() moves the base iterator forward.

+
+

Class template reverse_iterator

+
+template <class Iterator>
+class reverse_iterator :
+  public iterator_adaptor< reverse_iterator<Iterator>, Iterator >
+{
+  friend class iterator_core_access;
+public:
+  reverse_iterator() {}
+  explicit reverse_iterator(Iterator x) ;
+
+  template<class OtherIterator>
+  reverse_iterator(
+      reverse_iterator<OtherIterator> const& r
+    , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+  );
+
+private: // as-if specification
+  typename reverse_iterator::reference dereference() const { return *prior(this->base()); }
+
+  void increment() { --this->base_reference(); }
+  void decrement() { ++this->base_reference(); }
+
+  void advance(typename reverse_iterator::difference_type n)
+  {
+      this->base_reference() += -n;
+  }
+
+  template <class OtherIterator>
+  typename reverse_iterator::difference_type
+  distance_to(reverse_iterator<OtherIterator> const& y) const
+  {
+      return this->base_reference() - y.base();
+  }
+
+};
+
+
+
+

reverse_iterator requirements

+

The base Iterator must be a model of Bidirectional Traversal +Iterator. The resulting reverse_iterator will be a model of the +most refined standard traversal and access concepts that are modeled +by Iterator.

+

reverse_iterator();

+ +++ + + + + + +
Requires:Iterator must be Default Constructible.
Returns:An instance of reverse_iterator with a +default constructed base object.
+

explicit reverse_iterator(Iterator x);

+ +++ + + + +
Returns:An instance of reverse_iterator with a +base object copy constructed from x.
+
+template<class OtherIterator>
+reverse_iterator(
+    reverse_iterator<OtherIterator> const& r
+  , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+);
+
+ +++ + + + + + +
Requires:OtherIterator is implicitly convertible to Iterator.
Returns:An instance of reverse_iterator that is a copy of r.
+
+
+
+

Transform iterator

+

The transform iterator adapts an iterator by applying some function +object to the result of dereferencing the iterator. In other words, +the operator* of the transform iterator first dereferences the +base iterator, passes the result of this to the function object, and +then returns the result.

+
+

Class template transform_iterator

+
+template <class AdaptableUnaryFunction,
+          class Iterator, 
+          class Reference = use_default, 
+          class Value = use_default>
+class transform_iterator
+  : public iterator_adaptor</* see discussion */>
+{
+  friend class iterator_core_access;
+public:
+  transform_iterator();
+  transform_iterator(Iterator const& x, AdaptableUnaryFunction f);
+
+  template<class OtherIterator, class R2, class V2>
+  transform_iterator(
+        transform_iterator<AdaptableUnaryFunction, OtherIterator, R2, V2> const& t
+      , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+  );
+
+  AdaptableUnaryFunction functor() const;
+private:
+  typename transform_iterator::value_type dereference() const;
+  AdaptableUnaryFunction m_f;
+};
+
+
+
+

transform_iterator requirements

+

The type AdaptableUnaryFunction must be Assignable, Copy +Constructible, and the expression f(x) must be valid where f +is an object of type AdaptableUnaryFunction, x is an object of +type AdaptableUnaryFunction::argument_type, and where the type of +f(x) must be AdaptableUnaryFunction::result_type.

+

The type Iterator must at least model Readable Iterator. The +resulting transform_iterator models the most refined of the +following options that is also modeled by Iterator.

+
+
    +
  • Writable Lvalue Iterator if the result_type of the +AdaptableUnaryFunction is a non-const reference.
  • +
  • Readable Lvalue Iterator if the result_type is a const +reference.
  • +
  • Readable Iterator otherwise.
  • +
+
+

The transform_iterator models the most refined standard traversal +concept that is modeled by Iterator.

+

The value_type of transform_iterator is +remove_reference<result_type>::type. The reference type is +result_type.

+
+
+

transform_iterator public operations

+

transform_iterator();

+ +++ + + + +
Returns:An instance of transform_iterator with m_f +and m_iterator default constructed.
+

transform_iterator(Iterator const& x, AdaptableUnaryFunction f);

+ +++ + + + +
Returns:An instance of transform_iterator with m_f +initialized to f and m_iterator initialized to x.
+
+template<class OtherIterator, class R2, class V2>
+transform_iterator(
+      transform_iterator<AdaptableUnaryFunction, OtherIterator, R2, V2> const& t
+    , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+);
+
+ +++ + + + + + +
Returns:An instance of transform_iterator that is a copy of t.
Requires:OtherIterator is implicitly convertible to Iterator.
+

AdaptableUnaryFunction functor() const;

+ +++ + + + +
Returns:m_f
+
+
+

transform_iterator private operations

+

typename transform_iterator::value_type dereference() const;

+ +++ + + + +
Returns:m_f(transform_iterator::dereference());
+
+
+
+

Filter iterator

+

The filter iterator adaptor creates a view of an iterator range in +which some elements of the range are skipped over. A predicate +function object controls which elements are skipped. When the +predicate is applied to an element, if it returns true then the +element is retained and if it returns false then the element is +skipped over. When skipping over elements, it is necessary for the +filter adaptor to know when to stop so as to avoid going past the end +of the underlying range. Therefore the constructor of the filter +iterator takes two iterator parameters: the position for the filtered +iterator and the end of the range.

+
+

Class template filter_iterator

+
+template <class Predicate, class Iterator>
+class filter_iterator
+    : public iterator_adaptor<
+          filter_iterator<Predicate, Iterator>, Iterator
+        , use_default
+        , /* see details */
+      >
+{
+ public:
+    filter_iterator();
+    filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());
+    filter_iterator(Iterator x, Iterator end = Iterator());
+    template<class OtherIterator>
+    filter_iterator(
+        filter_iterator<Predicate, OtherIterator> const& t
+        , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+        );
+    Predicate predicate() const;
+    Iterator end() const;
+
+ private: // as-if specification
+    void increment()
+    {
+        ++(this->base_reference());
+        satisfy_predicate();
+    }
+
+    void satisfy_predicate()
+    {
+        while (this->base() != this->m_end && !this->m_predicate(*this->base()))
+            ++(this->base_reference());
+    }
+
+    Predicate m_predicate;
+    Iterator m_end;
+};
+
+
+
+
+

filter_iterator requirements

+

The base Iterator parameter must be a model of Readable Iterator +and Single Pass Iterator. The resulting filter_iterator will be a +model of Forward Traversal Iterator if Iterator is, otherwise the +filter_iterator will be a model of Single Pass Iterator. The +access category of the filter_iterator will be the most refined +standard access category that is modeled by Iterator.

+ +

The Predicate must be Assignable, Copy Constructible, and the +expression p(x) must be valid where p is an object of type +Predicate, x is an object of type +iterator_traits<Iterator>::value_type, and where the type of +p(x) must be convertible to bool.

+
+
+

filter_iterator operations

+

filter_iterator();

+ +++ + + + + + +
Requires:Predicate and Iterator must be Default Constructible.
Returns:a filter_iterator whose +predicate is a default constructed Predicate and +whose end is a default constructed Iterator.
+

filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());

+ +++ + + + +
Returns:A filter_iterator at position x that filters according +to predicate f and that will not increment past end.
+

filter_iterator(Iterator x, Iterator end = Iterator());

+ +++ + + + + + +
Requires:Predicate must be Default Constructible.
Returns:A filter_iterator at position x that filters +according to a default constructed Predicate +and that will not increment past end.
+
+template <class OtherIterator>
+filter_iterator(
+    filter_iterator<Predicate, OtherIterator> const& t
+    , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+    );``
+
+ +++ + + + + + +
Requires:OtherIterator is implicitly convertible to Iterator.
Returns:A copy of iterator t.
+

Predicate predicate() const;

+ +++ + + + +
Returns:A copy of the predicate object used to construct *this.
+

Iterator end() const;

+ +++ + + + +
Returns:The object end used to construct *this.
+
+
+

Counting iterator

+

The counting iterator adaptor implements dereference by returning a +reference to the base object. The other operations are implemented by +the base m_iterator, as per the inheritance from +iterator_adaptor.

+
+

Class template counting_iterator

+
+template <class Incrementable, class Category = use_default, class Difference = use_default>
+class counting_iterator
+  : public iterator_adaptor<
+        counting_iterator<Incrementable, Category, Difference>
+      , Incrementable
+      , Incrementable
+      , /* see details for category */
+      , Incrementable const&
+      , Incrementable const*
+      , /* distance = Difference or a signed integral type */>
+{
+    friend class iterator_core_access;
+ public:
+    counting_iterator();
+    counting_iterator(counting_iterator const& rhs);
+    counting_iterator(Incrementable x);
+ private:
+    typename counting_iterator::reference dereference() const
+    {
+        return this->base_reference();
+    }
+  };
+
+
+
[Note: implementers are encouraged to provide an implementation of
+
distance_to and a difference_type that avoids overflows in +the cases when the Incrementable type is a numeric type.]
+
+
+
+
+

counting_iterator requirements

+

The Incrementable type must be Default Constructible, Copy +Constructible, and Assignable. The default distance is +an implementation defined signed integegral type.

+

The resulting counting_iterator models Readable Lvalue Iterator.

+

Furthermore, if you wish to create a counting iterator that is a Forward +Traversal Iterator, then the following expressions must be valid:

+
+Incrementable i, j;
+++i         // pre-increment
+i == j      // operator equal
+
+

If you wish to create a counting iterator that is a +Bidirectional Traversal Iterator, then pre-decrement is also required:

+
+--i
+
+

If you wish to create a counting iterator that is a Random Access +Traversal Iterator, then these additional expressions are also +required:

+
+counting_iterator::difference_type n;
+i += n
+n = i - j
+i < j
+
+
+
+

counting_iterator operations

+

counting_iterator();

+ +++ + + + +
Returns:A default constructed instance of counting_iterator.
+

counting_iterator(counting_iterator const& rhs);

+ +++ + + + +
Returns:An instance of counting_iterator that is a copy of rhs.
+

counting_iterator(Incrementable x);

+ +++ + + + +
Returns:An instance of counting_iterator with its base +object copy constructed from x.
+
+
+

Function output iterator

+

The function output iterator adaptor makes it easier to create custom +output iterators. The adaptor takes a unary function and creates a +model of Output Iterator. Each item assigned to the output iterator is +passed as an argument to the unary function. The motivation for this +iterator is that creating a conforming output iterator is non-trivial, +particularly because the proper implementation usually requires a +proxy object.

+
+

Class template function_output_iterator

+
+template <class UnaryFunction>
+class function_output_iterator {
+public:
+  typedef iterator_tag<
+        writable_iterator_tag
+      , incrementable_traversal_tag
+  > iterator_category;
+  typedef void                value_type;
+  typedef void                difference_type;
+  typedef void                pointer;
+  typedef void                reference;
+
+  explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());
+
+  struct output_proxy {
+    output_proxy(UnaryFunction& f);
+    template <class T> output_proxy& operator=(const T& value);
+  };
+  output_proxy operator*();
+  function_output_iterator& operator++();
+  function_output_iterator& operator++(int);
+};
+
+
+
+
+

function_output_iterator requirements

+

The UnaryFunction must be Assignable, Copy Constructible, and the +expression f(x) must be valid, where f is an object of type +UnaryFunction and x is an object of a type accepted by f. +The resulting function_output_iterator is a model of the Writable +and Incrementable Iterator concepts.

+
+
+

function_output_iterator operations

+

explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());

+ +++ + + + +
Returns:An instance of function_output_iterator with +f stored as a data member.
+

output_proxy operator*();

+ +++ + + + +
Returns:An instance of output_proxy constructed with +a copy of the unary function f.
+

function_output_iterator& operator++();

+ +++ + + + +
Returns:*this
+

function_output_iterator& operator++(int);

+ +++ + + + +
Returns:*this
+
+
+

function_output_iterator::output_proxy operations

+

output_proxy(UnaryFunction& f);

+ +++ + + + +
Returns:An instance of output_proxy with f stored as +a data member.
+

template <class T> output_proxy& operator=(const T& value);

+ +++ + + + +
Effects:
+m_f(value); 
+return *this; 
+
+
+ + ++ + + +
[Cop95][Coplien, 1995] Coplien, J., Curiously Recurring Template +Patterns, C++ Report, February 1995, pp. 24-27.
+ +
+
+
+
+ + + + diff --git a/doc/facade-and-adaptor.rst b/doc/facade-and-adaptor.rst index 321c9e2..3c71e97 100644 --- a/doc/facade-and-adaptor.rst +++ b/doc/facade-and-adaptor.rst @@ -8,7 +8,7 @@ Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:Number: N1476=03-0059 +:Number: **This document is a revised version of the official** N1476=03-0059 :copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com @@ -202,28 +202,40 @@ objects for several reasons: iterators, and a separate ``iterator_adaptor`` layer would be impossible. +Usage +----- + The user of ``iterator_facade`` derives his iterator class from an -instantiation of ``iterator_facade`` and defines member functions -implementing the core behaviors. The following table describes +instantiation of ``iterator_facade`` which takes the derived iterator +class as the first template parameter. The order of the other +template parameters to ``iterator_facade`` have been carefully chosen +to take advantage of useful defaults. For example, when defining a +constant lvalue iterator, the user can pass a const-qualified version +of the iterator's ``value_type`` as ``iterator_facade``\ 's ``Value`` +parameter and omit the ``Reference`` parameter which follows. + +The derived iterator class must define member functions implementing +the iterator's core behaviors. The following table describes expressions which are required to be valid depending on the category of the derived iterator type. These member functions are described -briefly below and in more detail in the `iterator facade requirements`_. +briefly below and in more detail in the `iterator facade +requirements`_. - +----------------------------------------+-------------------------------------------+ - | Expression | Effects | - +========================================+===========================================+ - | ``i.dereference()`` | Access the value referred to | - +----------------------------------------+-------------------------------------------+ - | ``i.equal(j)`` | Compare for equality with ``j`` | - +----------------------------------------+-------------------------------------------+ - | ``i.increment()`` | Advance by one position | - +----------------------------------------+-------------------------------------------+ - | ``i.decrement()`` | Retreat by one position | - +----------------------------------------+-------------------------------------------+ - | ``i.advance(n)`` | Advance by ``n`` positions | - +----------------------------------------+-------------------------------------------+ - | ``i.distance_to(j)`` | Measure the distance to ``j`` | - +----------------------------------------+-------------------------------------------+ + +------------------------+-------------------------------+ + |Expression |Effects | + +========================+===============================+ + |``i.dereference()`` |Access the value referred to | + +------------------------+-------------------------------+ + |``i.equal(j)`` |Compare for equality with ``j``| + +------------------------+-------------------------------+ + |``i.increment()`` |Advance by one position | + +------------------------+-------------------------------+ + |``i.decrement()`` |Retreat by one position | + +------------------------+-------------------------------+ + |``i.advance(n)`` |Advance by ``n`` positions | + +------------------------+-------------------------------+ + |``i.distance_to(j)`` |Measure the distance to ``j`` | + +------------------------+-------------------------------+ .. Should we add a comment that a zero overhead implementation of iterator_facade is possible with proper inlining? @@ -236,8 +248,9 @@ type ``X`` is meant to be automatically interoperate with another iterator type ``Y`` (as with constant and mutable iterators) then there must be an implicit conversion from ``X`` to ``Y`` or from ``Y`` to ``X`` (but not both), typically implemented as a conversion -constructor. Also, if the iterator is to model Forward Traversal -Iterator, a default constructor is required. +constructor. Finally, if the iterator is to model Forward Traversal +Iterator or a more-refined iterator concept, a default constructor is +required. @@ -306,6 +319,8 @@ from clients of her iterator. .. _issue 299: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#299 +.. _`operator arrow`: + ``operator->`` ============== @@ -355,7 +370,7 @@ implementation. Finally, ``use_default`` is not left unspecified because specification helps to highlight that the ``Reference`` template parameter may not always be identical to the iterator's ``reference`` type, and will keep users making mistakes based on that -assumtion. +assumption. Specialized Adaptors ==================== @@ -480,27 +495,27 @@ and associated types, to be supplied by a derived iterator class. Class template ``iterator_facade`` ---------------------------------- -:: +.. parsed-literal:: template < class Derived , class Value , class AccessCategory , class TraversalCategory - , class Reference = /* see below */ + , class Reference = /* see below__ \*/ , class Difference = ptrdiff_t > class iterator_facade { public: typedef remove_cv::type value_type; typedef Reference reference; - typedef /* see description of operator-> */ pointer; + typedef /* see `description of operator->`__ \*/ pointer; typedef Difference difference_type; typedef iterator_tag iterator_category; - reference operator*() const; - /* see below */ operator->() const; - /* impl defined */ operator[](difference_type n) const; + reference operator\*() const; + /* see below__ \*/ operator->() const; + /* see below__ \*/ operator[](difference_type n) const; Derived& operator++(); Derived operator++(int); Derived& operator--(); @@ -566,6 +581,14 @@ Class template ``iterator_facade`` typename Derived::difference_type n) +__ `iterator facade requirements`_ + +__ `operator arrow`_ + +__ `operator arrow`_ + +__ brackets_ + [*Note:* The ``enable_if_interoperable`` template used above is for exposition purposes. The member operators should be only be in an overload set provided the derived types ``Dr1`` and ``Dr2`` are interoperable, by @@ -602,30 +625,35 @@ object of a single pass iterator type interoperable with X, and ``z`` is a constant object of a random access traversal iterator type interoperable with ``X``. -+----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ -| Expression | Return Type | Assertion/Note/Precondition/Postcondition | Required to implement Iterator Concept(s) | -| | | | | -+========================================+========================================+=================================================+===========================================+ -| ``c.dereference()`` | ``X::reference`` | | Readable Iterator, Writable Iterator | -+----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ -| ``c.equal(b)`` | convertible to bool |true iff ``b`` and ``c`` are equivalent. | Single Pass Iterator | -+----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ -| ``c.equal(y)`` | convertible to bool |true iff ``c`` and ``y`` refer to the same | Single Pass Iterator | -| | |position. Implements ``c == y`` and ``c != y``. | | -+----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ -| ``a.advance(n)`` | unused | | Random Access Traversal Iterator | -+----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ -| ``a.increment()`` | unused | | Incrementable Iterator | -+----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ -| ``a.decrement()`` | unused | | Bidirectional Traversal Iterator | -+----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ -| ``c.distance_to(b)`` | convertible to X::difference_type | equivalent to ``distance(c, b)`` | Random Access Traversal Iterator | -+----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ -| ``c.distance_to(z)`` | convertible to X::difference_type |equivalent to ``distance(c, z)``. Implements ``c| Random Access Traversal Iterator | -| | |- z``, ``c < z``, ``c <= z``, ``c > z``, and ``c | | -| | |>= c``. | | -+----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ - ++--------------------+-------------------+-------------------------------------+---------------------------+ +|Expression |Return Type |Assertion/Note |Required to implement | +| | | |Iterator Concept(s) | ++====================+===================+=====================================+===========================+ +|``c.dereference()`` |``X::reference`` | |Readable Iterator, Writable| +| | | |Iterator | ++--------------------+-------------------+-------------------------------------+---------------------------+ +|``c.equal(b)`` |convertible to bool|true iff ``b`` and ``c`` are |Single Pass Iterator | +| | |equivalent. | | ++--------------------+-------------------+-------------------------------------+---------------------------+ +|``c.equal(y)`` |convertible to bool|true iff ``c`` and ``y`` refer to the|Single Pass Iterator | +| | |same position. Implements ``c == y``| | +| | |and ``c != y``. | | ++--------------------+-------------------+-------------------------------------+---------------------------+ +|``a.advance(n)`` |unused | |Random Access Traversal | +| | | |Iterator | ++--------------------+-------------------+-------------------------------------+---------------------------+ +|``a.increment()`` |unused | |Incrementable Iterator | ++--------------------+-------------------+-------------------------------------+---------------------------+ +|``a.decrement()`` |unused | |Bidirectional Traversal | +| | | |Iterator | ++--------------------+-------------------+-------------------------------------+---------------------------+ +|``c.distance_to(b)``|convertible to |equivalent to ``distance(c, b)`` |Random Access Traversal | +| |X::difference_type | |Iterator | ++--------------------+-------------------+-------------------------------------+---------------------------+ +|``c.distance_to(z)``|convertible to |equivalent to ``distance(c, z)``. |Random Access Traversal | +| |X::difference_type |Implements ``c - z``, ``c < z``, ``c |Iterator | +| | |<= z``, ``c > z``, and ``c >= c``. | | ++--------------------+-------------------+-------------------------------------+---------------------------+ .. We should explain more about how the functions in the interface of iterator_facade @@ -644,7 +672,9 @@ through member functions of class ``iterator_core_access``. :Returns: ``static_cast(this)->dereference()`` -*see below* ``operator->() const;`` +``operator->() const;`` (see below__) + +__ `operator arrow`_ :Returns: If ``X::reference`` is a reference type, returns an object of type ``X::pointer`` equal to:: @@ -660,6 +690,8 @@ through member functions of class ``iterator_core_access``. ``Value const*`` otherwise. +.. _brackets: + *unspecified* ``operator[](difference_type n) const;`` :Returns: an object convertible to ``X::reference`` and holding a copy @@ -765,7 +797,7 @@ core interface functions of ``iterator_facade`` are redefined in the Class template ``iterator_adaptor`` ----------------------------------- -:: +.. parsed-literal:: template < class Derived @@ -776,7 +808,7 @@ Class template ``iterator_adaptor`` , class Difference = use_default > class iterator_adaptor - : public iterator_facade + : public iterator_facade { friend class iterator_core_access; public: @@ -808,7 +840,7 @@ Class template ``iterator_adaptor`` Base m_iterator; }; - +__ : ``iterator_adaptor`` requirements --------------------------------- diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html new file mode 100755 index 0000000..765a733 --- /dev/null +++ b/doc/new-iter-concepts.html @@ -0,0 +1,1133 @@ + + + + + + +New Iterator Concepts + + + + + + + +
+

New Iterator Concepts

+ +++ + + + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems Lab, University of Hanover Institute for Transport Railway Operation and Construction
Date:2003-07-12
Number:This document is a revised version of the official N1477=03-0060
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
+ +++ + + + +
Abstract:We propose a new system of iterator concepts that treat +access and positioning independently. This allows the +concepts to more closely match the requirements +of algorithms and provides better categorizations +of iterators that are used in practice. This proposal +is a revision of paper n1297.
+ +
+

Motivation

+

The standard iterator categories and requirements are flawed because +they use a single hierarchy of concepts to address two orthogonal +issues: iterator traversal and value access. As a result, many +algorithms with requirements expressed in terms of the iterator +categories are too strict. Also, many real-world iterators can not be +accurately categorized. A proxy-based iterator with random-access +traversal, for example, may only legally have a category of "input +iterator", so generic algorithms are unable to take advantage of its +random-access capabilities. The current iterator concept hierarchy is +geared towards iterator traversal (hence the category names), while +requirements that address value access sneak in at various places. The +following table gives a summary of the current value access +requirements in the iterator categories.

+ ++++ + + + + + + + + + + + + + + +
Output Iterator*i = a
Input Iterator*i is convertible to T
Forward Iterator*i is T& (or const T& once issue 200 +is resolved)
Random Access Iteratori[n] is convertible to T (also i[n] = t +is required for mutable iterators once issue 299 +is resolved)
+

Because iterator traversal and value access are mixed together in a +single hierarchy, many useful iterators can not be appropriately +categorized. For example, vector<bool>::iterator is almost a +random access iterator, but the return type is not bool& (see +issue 96 and Herb Sutter's paper J16/99-0008 = WG21 +N1185). Therefore, the iterators of vector<bool> only meet the +requirements of input iterator and output iterator. This is so +nonintuitive that at least one implementation erroneously assigns +random_access_iterator_tag as its iterator_category.

+

Another difficult-to-categorize iterator is the transform iterator, an +adaptor which applies a unary function object to the dereferenced +value of the some underlying iterator (see transform_iterator). +For unary functions such as times, the return type of +operator* clearly needs to be the result_type of the function +object, which is typically not a reference. Because random access +iterators are required to return lvalues from operator*, if you +wrap int* with a transform iterator, you do not get a random +access iterator as might be expected, but an input iterator.

+

A third example is found in the vertex and edge iterators of the +Boost Graph Library. These iterators return vertex and edge +descriptors, which are lightweight handles created on-the-fly. They +must be returned by-value. As a result, their current standard +iterator category is input_iterator_tag, which means that, +strictly speaking, you could not use these iterators with algorithms +like min_element(). As a temporary solution, the concept +Multi-Pass Input Iterator was introduced to describe the vertex and +edge descriptors, but as the design notes for the concept suggest, a +better solution is needed.

+

In short, there are many useful iterators that do not fit into the +current standard iterator categories. As a result, the following bad +things happen:

+
    +
  • Iterators are often mis-categorized.
  • +
  • Algorithm requirements are more strict than necessary, because they +cannot separate the need for random access or bidirectional +traversal from the need for a true reference return type.
  • +
+
+
+

Impact on the Standard

+

The new iterator concepts are backward-compatible with the old +iterator requirements, and old iterators are forward-compatible with +the new iterator concepts. That is to say, iterators that satisfy the +old requirements also satisfy appropriate concepts in the new system, +and iterators modeling the new concepts will automatically satisfy the +appropriate old requirements.

+ + +

The algorithms in the standard library benefit from the new iterator +concepts because the new concepts provide a more accurate way to +express their type requirements. The result is algorithms that are +usable in more situations and have fewer type requirements. The +following lists the proposed changes to the type requirements of +algorithms.

+

Forward Iterator -> Forward Traversal Iterator and Readable Iterator

+
+find_end, adjacent_find, search, search_n, rotate_copy, lower_bound, upper_bound, equal_range, binary_search, min_element, max_element
+

Forward Iterator (1) -> Single Pass Iterator and Readable Iterator +Forward Iterator (2) -> Forward Traversal Iterator and Readable Iterator

+
+find_first_of
+

Forward Iterator -> Readable Iterator and Writable Iterator

+
+iter_swap
+

Forward Iterator -> Single Pass Iterator and Writable Iterator

+
+fill, generate
+

Forward Iterator -> Forward Traversal Iterator and Swappable Iterator

+
+rotate
+

Forward Iterator (1) -> Swappable Iterator and Single Pass Iterator +Forward Iterator (2) -> Swappable Iterator and Incrementable Iterator

+
+swap_ranges
+
+
Forward Iterator -> Forward Traversal Iterator and Readable Iterator and Writable Iterator
+
remove, remove_if, unique
+
+

Forward Iterator -> Single Pass Iterator and Readable Iterator and Writable Iterator

+
+replace, replace_if
+
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator
+
reverse
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable and Swappable Iterator
+
partition
+
+

Bidirectional Iterator (1) -> Bidirectional Traversal Iterator and Readable Iterator, +Bidirectional Iterator (2) -> Bidirectional Traversal Iterator and Writable Iterator

+
+copy_backwards
+
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator and Readable Iterator
+
next_permutation, prev_permutation
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator and Writable Iterator
+
stable_partition, inplace_merge
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator
+
reverse_copy
+
Random Access Iterator -> Random Access Traversal Iterator and Readable and Swappable Iterator
+
random_shuffle, sort, stable_sort, partial_sort, nth_element, push_heap, pop_heap +make_heap, sort_heap
+
Input Iterator (2) -> Incrementable Iterator and Readable Iterator
+
equal
+
Input Iterator (2) -> Incrementable Iterator and Readable Iterator
+
transform
+
+
+
+

Design

+

The iterator requirements are be separated into two hierarchies. One +set of concepts handles the syntax and semantics of value access:

+
    +
  • Readable Iterator
  • +
  • Writable Iterator
  • +
  • Swappable Iterator
  • +
  • Readable Lvalue Iterator
  • +
  • Writable Lvalue Iterator
  • +
+

The refinement relationships among these iterator concepts are given +in the following diagram.

+

access.png

+

The access concepts describe requirements related to operator* and +operator->, including the value_type, reference, and +pointer associated types.

+

The other set of concepts handles traversal:

+
    +
  • Incrementable Iterator
  • +
  • Single Pass Iterator
  • +
  • Forward Traversal Iterator
  • +
  • Bidirectional Traversal Iterator
  • +
  • Random Access Traversal Iterator
  • +
+

The refinement relationships for the traversal concepts are in the +following diagram.

+

traversal.png

+

In addition to the iterator movement operators, such as +operator++, the traversal concepts also include requirements on +position comparison such as operator== and operator<. The +reason for the fine grain slicing of the concepts into the +Incrementable and Single Pass is to provide concepts that are exact +matches with the original input and output iterator requirements.

+

The relationship between the new iterator concepts and the old are +given in the following diagram.

+

oldeqnew.png

+

Like the old iterator requirements, we provide tags for purposes of +dispatching. There are two hierarchies of tags, one for the access +concepts and one for the traversal concepts. We provide an access +mechanism for mapping iterator types to these new tags. Our design +reuses iterator_traits<Iter>::iterator_category as the access +mechanism. To enable this, a pair of access and traversal tags are +combined into a single type using the following iterator_tag class.

+
+template <class AccessTag, class TraversalTag>
+struct iterator_tag : /* appropriate old category or categories */
+{
+  typedef AccessTag access;
+  typedef TraversalTag traversal;
+};
+
+

The iterator_tag class template is derived from the appropriate +iterator tag or tags from the old requirements based on the new-style +tags passed as template parameters. The algorithm for determining the +old tag or tags from the new tags picks the least-refined old concepts +that include all of the requirements of the access and traversal +concepts (that is, the closest fit), if any such category exists. For +example, a the category tag for a Readable Single Pass Iterator will +always be derived from input_iterator_tag, while the category tag +for a Single Pass Iterator that is both Readable and Writable will be +derived from both input_iterator_tag and output_iterator_tag.

+

We also provide two helper classes that make it convenient to obtain +the access and traversal tags of an iterator. These helper classes +work both for iterators whose iterator_category is +iterator_tag and also for iterators using the original iterator +categories.

+
+template <class Iterator> struct access_category { typedef ... type; };
+template <class Iterator> struct traversal_category { typedef ... type; };
+
+

The most difficult design decision concerned the operator[]. The +direct approach for specifying operator[] would have a return type +of reference; the same as operator*. However, going in this +direction would mean that an iterator satisfying the old Random Access +Iterator requirements would not necessarily be a model of Readable or +Writable Lvalue Iterator. Instead we have chosen a design that +matches the preferred resolution of issue 299: operator[] is +only required to return something convertible to the value_type +(for a Readable Iterator), and is required to support assignment +i[n] = t (for a Writable Iterator).

+
+
+

Proposed Text

+
+

Addition to [lib.iterator.requirements]

+
+

Iterator Value Access Concepts [lib.iterator.value.access]

+

In the tables below, X is an iterator type, a is a constant +object of type X, T is +std::iterator_traits<X>::value_type, and v is a constant +object of type T.

+
+

Readable Iterators [lib.readable.iterators]

+

A class or built-in type X models the Readable Iterator concept +for the value type T if the following expressions are valid and +respect the stated semantics. U is the type of any specified +member of type T.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Readable Iterator Requirements (in addition to CopyConstructible)
ExpressionReturn TypeAssertion/Note/Precondition/Postcondition
iterator_traits<X>::value_typeTAny non-reference, non-cv-qualified type
iterator_traits<X>::referenceConvertible to +iterator_traits<X>::value_type 
access_category<X>::typeConvertible to +readable_iterator_tag 
*aiterator_traits<X>::referencepre: a is dereferenceable. If a == +b then *a is equivalent to *b
a->mU&pre: (*a).m is well-defined. +Equivalent to (*a).m
+
+
+
+

Writable Iterators [lib.writable.iterators]

+

A class or built-in type X models the Writable Iterator concept +if the following expressions are valid and respect the stated +semantics.

+ +
+
+

Swappable Iterators [lib.swappable.iterators]

+

A class or built-in type X models the Swappable Iterator concept +if the following expressions are valid and respect the stated +semantics.

+
+ +++++ + + + + + + + + + + + + + + +
Swappable Iterator Requirements (in addition to CopyConstructible)
ExpressionReturn TypePostcondition
iter_swap(a, b)voidpost: the pointed to values are exchanged
+
+
+
[Note: An iterator that is a model of the Readable and Writable Iterator concepts
+
is also a model of Swappable Iterator. --end note]
+
+
+
+

Readable Lvalue Iterators [lib.readable.lvalue.iterators]

+

The Readable Lvalue Iterator concept adds the requirement that the +reference type be a reference to the value type of the iterator.

+
+ +++++ + + + + + + + + + + + + + + + + + + +
Readable Lvalue Iterator Requirements (in addition to Readable Iterator)
ExpressionReturn TypeAssertion
iterator_traits<X>::referenceT&T is cv +iterator_traits<X>::value_type +where cv is an optional +cv-qualification
access_category<X>::typeConvertible to +readable_lvalue_iterator_tag 
+
+
+
+

Writable Lvalue Iterators [lib.writable.lvalue.iterators]

+

The Writable Lvalue Iterator concept adds the requirement that the +reference type be a non-const reference to the value type of the +iterator.

+
+ ++++ + + + + + + + + + + + + + + + +
Writable Lvalue Iterator Requirements (in addition to Readable Lvalue Iterator)
ExpressionReturn Type
iterator_traits<X>::referenceiterator_traits<X>::value_type&
access_category<X>::typeConvertible to writable_lvalue_iterator_tag
+
+
+
+
+

Iterator Traversal Concepts [lib.iterator.traversal]

+

In the tables below, X is an iterator type, a and b are +constant objects of type X, r and s are mutable objects of +type X, T is std::iterator_traits<X>::value_type, and +v is a constant object of type T.

+
+

Incrementable Iterators [lib.incrementable.iterators]

+

A class or built-in type X models the Incrementable Iterator +concept if the following expressions are valid and respect the stated +semantics.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + +
Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible)
ExpressionReturn TypeAssertion/Semantics
++rX&&r == &++r
r++X{ X tmp = r; ++r; return tmp; }
traversal_category<X>::typeConvertible to incrementable_iterator_tag 
+
+
+
+

Single Pass Iterators [lib.single.pass.iterators]

+

A class or built-in type X models the Single Pass Iterator +concept if the following expressions are valid and respect the stated +semantics.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality Comparable)
ExpressionReturn TypeAssertion/Semantics/Pre-/Post-condition
++rX&pre: r is dereferenceable; post: +r is dereferenceable or r is +past-the-end
a == bconvertible to bool== is an equivalence relation over +its domain
a != bconvertible to bool!(a == b)
traversal_category<X>::typeConvertible to +single_pass_iterator_tag 
+
+
+
+

Forward Traversal Iterators [lib.forward.traversal.iterators]

+

A class or built-in type X models the Forward Traversal Iterator +concept if the following expressions are valid and respect the stated +semantics.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Forward Traversal Iterator Requirements (in addition to Single Pass Iterator)
ExpressionReturn TypeAssertion/Note
X u;X&note: u may have a +singular value.
++rX&r == s and r is +dereferenceable implies +++r == ++s.
iterator_traits<X>::difference_typeA signed integral type representing +the distance between iterators 
traversal_category<X>::typeConvertible to +forward_traversal_iterator_tag 
+
+
+
+

Bidirectional Traversal Iterators [lib.bidirectional.traversal.iterators]

+

A class or built-in type X models the Bidirectional Traversal +Iterator concept if the following expressions are valid and respect +the stated semantics.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + +
Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal Iterator)
ExpressionReturn TypeAssertion/Semantics/Pre-/Post-condition
--rX&pre: there exists s such that r +== ++s. post: s is +dereferenceable. --(++r) == r. +--r == --s implies r == s. &r +== &--r.
r--convertible to const X&{ X tmp = r; --r; return tmp; }
traversal_category<X>::typeConvertible to +bidirectional_traversal_iterator_tag 
+
+
+
+

Random Access Traversal Iterators [lib.random.access.traversal.iterators]

+

A class or built-in type X models the Random Access Traversal +Iterator concept if the following expressions are valid and respect +the stated semantics. In the table below, Distance is +iterator_traits<X>::difference_type and n represents a +constant object of type Distance.

+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal Iterator)
ExpressionReturn TypeOperational SemanticsAssertion/Precondition
r += nX&
+{
+  Distance m = n;
+  if (m >= 0)
+    while (m--)
+      ++r;
+  else
+    while (m++)
+      --r;
+  return r;
+}
+
+
 
a + n, n + aX{ X tmp = a; return +tmp += n; } 
r -= nX&return r += -n 
a - nX{ X tmp = a; return +tmp -= n; } 
b - aDistancea < b ? +distance(a,b) : +-distance(b,a)pre: there exists a value +n of Distance such +that a + n == b. b == +a + (b - a).
a[n]convertible to T*(a + n)pre: a is a readable +iterator
a[n] = vconvertible to T*(a + n) = vpre: a is a writable +iterator
a < bconvertible to boolb - a > 0< is a total ordering +relation
a > bconvertible to boolb < a> is a total ordering +relation
a >= bconvertible to bool!(a < b) 
a <= bconvertible to bool!(a > b) 
traversal_category<X>::typeConvertible to +random_access_traversal_iterator_tag  
+
+
+
+
+
+

Addition to [lib.iterator.synopsis]

+
+// lib.iterator.traits, traits and tags
+template <class Iterator> struct access_category;
+template <class Iterator> struct traversal_category;
+
+template <class AccessTag, class TraversalTag>
+struct iterator_tag : /* appropriate old category or categories */ {
+  typedef AccessTag access;
+  typedef TraversalTag traversal;
+};
+
+struct readable_iterator_tag { };
+struct writable_iterator_tag { };
+struct swappable_iterator_tag { };
+struct readable_writable_iterator_tag
+  : virtual readable_iterator_tag
+  , virtual writable_iterator_tag
+  , virtual swappable_iterator_tag { };
+struct readable_lvalue_iterator_tag { };
+struct writable_lvalue_iterator_tag
+  : virtual public readable_writable_iterator_tag
+  , virtual public readable_lvalue_iterator_tag { };
+
+struct incrementable_iterator_tag { };
+struct single_pass_iterator_tag : incrementable_iterator_tag { };
+struct forward_traversal_tag : single_pass_iterator_tag { };
+struct bidirectional_traversal_tag : forward_traversal_tag { };
+struct random_access_traversal_tag : bidirectional_traversal_tag { };
+
+struct null_category_tag { };
+struct input_output_iterator_tag : input_iterator_tag, output_iterator_tag {};
+
+
+
+

Addition to [lib.iterator.traits]

+

The iterator_tag class template is an iterator category tag that +encodes the access and traversal tags in addition to being compatible +with the original iterator tags. The iterator_tag class inherits +from one of the original iterator tags according to the following +pseudo-code.

+
+inherit-category(access-tag, traversal-tag) =
+     if (access-tag is convertible to readable_lvalue_iterator_tag) {
+         if (traversal-tag is convertible to random_access_traversal_tag)
+             return random_access_iterator_tag;
+         else if (traversal-tag is convertible to bidirectional_traversal_tag)
+             return bidirectional_iterator_tag;
+         else if (traversal-tag is convertible to forward_traversal_tag)
+             return forward_iterator_tag;
+         else if (traversal-tag is convertible to single_pass_traversal_tag)
+             if (access-tag is convertible to writable_iterator_tag)
+                 return input_output_iterator_tag;
+             else
+                 return input_iterator_tag;
+         else if (access-tag is convertible to writable_iterator_tag)
+             return output_iterator_tag;
+         else
+             return null_category_tag;
+     } else if (access-tag is convertible to readable_writable_iterator_tag
+                and traversal-tag is convertible to single_pass_iterator_tag)
+         return input_output_iterator_tag;
+     else if (access-tag is convertible to readable_iterator_tag
+              and traversal-tag is convertible to single_pass_iterator_tag)
+         return input_iterator_tag;
+     else if (access-tag is convertible to writable_iterator_tag
+              and traversal-tag is convertible to incrementable_iterator_tag)
+         return output_iterator_tag;
+     else
+         return null_category_tag;
+
+

The access_category and traversal_category class templates are +traits classes. For iterators whose +iterator_traits<Iter>::iterator_category type is iterator_tag, +the access_category and traversal_category traits access the +access and traversal member types within iterator_tag. +For iterators whose iterator_traits<Iter>::iterator_category type +is not iterator_tag and instead is a tag convertible to one of the +original tags, the appropriate traversal and access tags is deduced. +The following pseudo-code describes the algorithm.

+
+access-category(Iterator) =
+    cat = iterator_traits<Iterator>::iterator_category;
+    if (cat == iterator_tag<Access,Traversal>)
+        return Access;
+    else if (cat is convertible to forward_iterator_tag) {
+        if (iterator_traits<Iterator>::reference is a const reference)
+            return readable_lvalue_iterator_tag;
+        else
+            return writable_lvalue_iterator_tag;
+    } else if (cat is convertible to input_iterator_tag)
+        return readable_iterator_tag;
+    else if (cat is convertible to output_iterator_tag)
+        return writable_iterator_tag;
+    else
+        return null_category_tag;
+
+traversal-category(Iterator) =
+    cat = iterator_traits<Iterator>::iterator_category;
+    if (cat == iterator_tag<Access,Traversal>)
+        return Traversal;
+    else if (cat is convertible to random_access_iterator_tag)
+        return random_access_traversal_tag;
+    else if (cat is convertible to bidirectional_iterator_tag)
+        return bidirectional_traversal_tag;
+    else if (cat is convertible to forward_iterator_tag)
+        return forward_traversal_tag;
+    else if (cat is convertible to input_iterator_tag)
+        return single_pass_iterator_tag;
+    else if (cat is convertible to output_iterator_tag)
+        return incrementable_iterator_tag;
+    else
+        return null_category_tag;
+
+

The following specializations provide the access and traversal +category tags for pointer types.

+
+template <typename T>
+struct access_category<const T*>
+{
+  typedef readable_lvalue_iterator_tag type;
+};
+template <typename T>
+struct access_category<T*>
+{
+  typedef writable_lvalue_iterator_tag type;
+};
+
+template <typename T>
+struct traversal_category<T*>
+{
+  typedef random_access_traversal_tag type;
+};
+
+ +
+
+
+ + + + diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 9005000..be1b357 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -6,7 +6,7 @@ :Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de :organization: `Boost Consulting`_, Indiana University `Open Systems Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:Number: N1477=03-0060 +:Number: **This document is a revised version of the official** N1477=03-0060 :copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com From 57a40c8cd2cf3d69a78a4293583bb1b93ef96e26 Mon Sep 17 00:00:00 2001 From: Thomas Witt Date: Mon, 14 Jul 2003 13:13:49 +0000 Subject: [PATCH 183/265] Added arg dependent workaround for msvc < 7.1 [SVN r19110] --- include/boost/iterator/iterator_facade.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index 21f99c7..5683cca 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -362,7 +362,7 @@ namespace boost , class Value , class AccessCategory , class TraversalCategory - , class Reference = typename detail::const_qualified_ref::type + , class Reference = BOOST_ARG_DEPENDENT_TYPENAME detail::const_qualified_ref::type , class Difference = std::ptrdiff_t > class iterator_facade From 42e873e10c8d80dc990f939b760a1a9f5d5366a4 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 14 Jul 2003 16:22:10 +0000 Subject: [PATCH 184/265] various bugfixes. filter_/transform_iterator were misusing enable_if in a non-template context , and iterator_facade needed a forward declaration for full conformance. [SVN r19112] --- include/boost/iterator/filter_iterator.hpp | 12 ++++------ include/boost/iterator/iterator_facade.hpp | 8 ++++++- include/boost/iterator/transform_iterator.hpp | 22 +++++-------------- 3 files changed, 17 insertions(+), 25 deletions(-) diff --git a/include/boost/iterator/filter_iterator.hpp b/include/boost/iterator/filter_iterator.hpp index 5b16bb1..059afc5 100644 --- a/include/boost/iterator/filter_iterator.hpp +++ b/include/boost/iterator/filter_iterator.hpp @@ -56,16 +56,12 @@ namespace boost satisfy_predicate(); } - // don't provide this constructor if UnaryFunction is a - // function pointer type. Too dangerous. - filter_iterator( - typename iterators::enable_if< - is_class - , Iterator - >::type x - , Iterator end = Iterator()) + filter_iterator(Iterator x, Iterator end = Iterator()) : super_t(x), m_predicate(), m_end(end) { + // Don't allow use of this constructor if Predicate is a + // function pointer type, since it will be 0. + BOOST_STATIC_ASSERT(is_class::value); satisfy_predicate(); } diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index 5683cca..774323e 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -28,7 +28,13 @@ namespace boost { + // This forward declaration is required for the friend declaration + // in iterator_core_access + template class iterator_facade; + // Used as a default template argument internally, merely to + // indicate "use the default", this can also be passed by users + // explicitly in order to specify that the default should be used. struct use_default; namespace detail @@ -362,7 +368,7 @@ namespace boost , class Value , class AccessCategory , class TraversalCategory - , class Reference = BOOST_ARG_DEPENDENT_TYPENAME detail::const_qualified_ref::type + , class Reference = BOOST_DEDUCED_TYPENAME detail::const_qualified_ref::type , class Difference = std::ptrdiff_t > class iterator_facade diff --git a/include/boost/iterator/transform_iterator.hpp b/include/boost/iterator/transform_iterator.hpp index e0ab3dd..47ea9ac 100644 --- a/include/boost/iterator/transform_iterator.hpp +++ b/include/boost/iterator/transform_iterator.hpp @@ -115,23 +115,13 @@ namespace boost transform_iterator(Iterator const& x, UnaryFunction f) : super_t(x), m_f(f) { } - // don't provide this constructor if UnaryFunction is a - // function pointer type. Too dangerous. - transform_iterator( - // Sadly, GCC 3.2 seems to choke on the enable_if when - // UnaryFunction is a plain function pointer -#if BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(3)) \ - && BOOST_WORKAROUND(__GNUC_MINOR__, BOOST_TESTED_AT(2)) - Iterator const& x -#else - typename iterators::enable_if< - is_class - , Iterator const& - >::type x -#endif - ) + transform_iterator(Iterator const& x) : super_t(x) - {} + { + // don't provide this constructor if UnaryFunction is a + // function pointer type, since it will be 0. Too dangerous. + BOOST_STATIC_ASSERT(is_class::value); + } template transform_iterator( From e4447b8e83c9bef1a744ce4ee6cfe3b6033da0f7 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 14 Jul 2003 21:31:44 +0000 Subject: [PATCH 185/265] Bug fix for code not being exercised currently. [SVN r19118] --- include/boost/iterator/iterator_concepts.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/iterator/iterator_concepts.hpp b/include/boost/iterator/iterator_concepts.hpp index fe5b433..31dd265 100644 --- a/include/boost/iterator/iterator_concepts.hpp +++ b/include/boost/iterator/iterator_concepts.hpp @@ -269,7 +269,7 @@ namespace detail template static void constraints(Iterator1 const& i1, Iterator2 const& i2) { - Operations(i1, i2); + Operations::constraints(i1, i2); i1 == i2; i1 != i2; From 52c0d22cffca8f9a261e3640c968fdcb54cd9a97 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 14 Jul 2003 23:05:57 +0000 Subject: [PATCH 186/265] Bugfixes and workarounds [SVN r19121] --- include/boost/iterator/filter_iterator.hpp | 4 ++++ include/boost/iterator/transform_iterator.hpp | 6 +++++- test/transform_iterator_test.cpp | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/boost/iterator/filter_iterator.hpp b/include/boost/iterator/filter_iterator.hpp index 059afc5..390dc8e 100644 --- a/include/boost/iterator/filter_iterator.hpp +++ b/include/boost/iterator/filter_iterator.hpp @@ -59,9 +59,13 @@ namespace boost filter_iterator(Iterator x, Iterator end = Iterator()) : super_t(x), m_predicate(), m_end(end) { + // Pro8 is a little too aggressive about instantiating the + // body of this function. +#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) // Don't allow use of this constructor if Predicate is a // function pointer type, since it will be 0. BOOST_STATIC_ASSERT(is_class::value); +#endif satisfy_predicate(); } diff --git a/include/boost/iterator/transform_iterator.hpp b/include/boost/iterator/transform_iterator.hpp index 47ea9ac..f281b82 100644 --- a/include/boost/iterator/transform_iterator.hpp +++ b/include/boost/iterator/transform_iterator.hpp @@ -115,12 +115,16 @@ namespace boost transform_iterator(Iterator const& x, UnaryFunction f) : super_t(x), m_f(f) { } - transform_iterator(Iterator const& x) + explicit transform_iterator(Iterator const& x) : super_t(x) { + // Pro8 is a little too aggressive about instantiating the + // body of this function. +#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) // don't provide this constructor if UnaryFunction is a // function pointer type, since it will be 0. Too dangerous. BOOST_STATIC_ASSERT(is_class::value); +#endif } template diff --git a/test/transform_iterator_test.cpp b/test/transform_iterator_test.cpp index fe694b5..8eb5121 100644 --- a/test/transform_iterator_test.cpp +++ b/test/transform_iterator_test.cpp @@ -39,6 +39,10 @@ namespace boost { namespace detail template<> struct iterator_traits const*> : ptr_iter_traits, std::pair const> {}; + template<> struct function_object_result + { + typedef int type; + }; }} #endif From 8a51271e3bc9bd3698ad72f9fbbb9b8910f2981b Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Wed, 16 Jul 2003 10:36:53 +0000 Subject: [PATCH 187/265] deque libcomo workaround [SVN r19143] --- test/reverse_iterator_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/reverse_iterator_test.cpp b/test/reverse_iterator_test.cpp index 8b3e9b6..0137d97 100644 --- a/test/reverse_iterator_test.cpp +++ b/test/reverse_iterator_test.cpp @@ -87,6 +87,7 @@ int main() #if defined(__SGI_STL_PORT) \ || !BOOST_WORKAROUND(__GNUC__, <= 2) \ && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) \ + && !BOOST_WORKAROUND(__LIBCOMO_VERSION__, BOOST_TESTED_AT(29)) \ && !BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 1) boost::const_nonconst_iterator_test(i, ++j); From 3fe0d4b5322e6476b5dd0a0f09f707549ed932b2 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 16 Jul 2003 19:35:46 +0000 Subject: [PATCH 188/265] * Use boost::referent<> metafunction for detecting the value type of indirect_iterator. * Change the order of tests in the Jamfile so expected failures come last, accounting for some recent Boost.Build change I suppose. [SVN r19158] --- include/boost/iterator/indirect_iterator.hpp | 77 ++++++++++++++------ test/Jamfile | 15 +++- 2 files changed, 65 insertions(+), 27 deletions(-) diff --git a/include/boost/iterator/indirect_iterator.hpp b/include/boost/iterator/indirect_iterator.hpp index 4e2500b..0839072 100644 --- a/include/boost/iterator/indirect_iterator.hpp +++ b/include/boost/iterator/indirect_iterator.hpp @@ -14,7 +14,12 @@ #include +#include + #include +#include +#include +#include #include #include @@ -32,6 +37,9 @@ namespace boost template struct indirect_iterator; + template + struct referent; + namespace detail { struct unspecified {}; @@ -79,9 +87,10 @@ namespace boost : mpl::true_ {}; # endif - // Metafunction returning the nested element_type typedef + // Metafunction accessing the nested ::element_type template - struct smart_pointer_value : remove_const + struct element_type + : mpl::identity {}; template @@ -110,37 +119,45 @@ namespace boost struct not_int : not_int_impl::template apply {}; + + template + struct class_has_element_type + : mpl::and_< + is_class + , has_element_type + > + {}; + // If the Value parameter is unspecified, we use this metafunction // to deduce the default types - template - struct indirect_base + template + struct default_indirect_value { - typedef typename iterator_value::type dereferenceable; - - typedef mpl::and_< - is_class - , has_element_type - > is_smart_ptr; - - typedef typename mpl::apply_if< - is_smart_ptr - , smart_pointer_value - , iterator_value - >::type value_type; + typedef typename remove_cv< + typename referent::type + >::type referent_t; typedef typename mpl::if_< mpl::or_< - is_smart_ptr - , iterator_is_mutable + class_has_element_type + , iterator_is_mutable > - , value_type - , value_type const - >::type cv_value_type; - + , referent_t + , referent_t const + >::type type; + }; + + template + struct indirect_base + { + typedef typename iterator_traits::value_type dereferenceable; + typedef iterator_adaptor< indirect_iterator , Iter - , cv_value_type + , typename ia_dflt_help< + Value, default_indirect_value + >::type , Category , Reference , Difference @@ -151,6 +168,20 @@ namespace boost struct indirect_base {}; } // namespace detail + // User-specializable metafunction which returns the referent of a + // dereferenceable type. The default implementation returns + // Dereferenceable::element_type if such a member exists (thus + // handling the boost smart pointers and auto_ptr), and + // iterator_traits::value_type otherwise. + template + struct referent + : mpl::apply_if< + detail::class_has_element_type + , detail::element_type + , iterator_value + > + {}; + template < class Iterator , class Value = use_default diff --git a/test/Jamfile b/test/Jamfile index f00e2cb..a4672aa 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -10,7 +10,17 @@ SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; include testing.jam ; test-suite iterator - : [ run unit_tests.cpp ] + : + # These first two tests will run last, and are expected to fail + # for many less-capable compilers. + + [ compile-fail interoperable_fail.cpp ] + # test uses expected success, so that we catch unrelated + # compilation problems. + [ run is_convertible_fail.cpp ] + + # These tests should work for just about everything. + [ run unit_tests.cpp ] [ run concept_tests.cpp ] [ run iterator_adaptor_cc.cpp ] [ run iterator_adaptor_test.cpp ] @@ -30,7 +40,4 @@ test-suite iterator [ run ../../utility/reverse_iterator_example.cpp ] [ run ../../utility/transform_iterator_example.cpp ] - [ run is_convertible_fail.cpp ] # test changed to expected success, so that we catch compilation failures. - - [ compile-fail interoperable_fail.cpp ] ; From ed8c60c20b2f76ca6e0d6cd9faf40ea94756e11e Mon Sep 17 00:00:00 2001 From: Thomas Witt Date: Sun, 20 Jul 2003 19:18:40 +0000 Subject: [PATCH 189/265] Improved category handling in iterator_adaptor. [SVN r19231] --- include/boost/iterator/detail/categories.hpp | 19 ++++++++++++ include/boost/iterator/filter_iterator.hpp | 25 +++++----------- include/boost/iterator/iterator_adaptor.hpp | 29 +++++++++++++++---- include/boost/iterator/transform_iterator.hpp | 5 +--- test/iterator_adaptor_test.cpp | 20 +++++++++++++ test/unit_tests.cpp | 19 ++++++++++++ 6 files changed, 90 insertions(+), 27 deletions(-) diff --git a/include/boost/iterator/detail/categories.hpp b/include/boost/iterator/detail/categories.hpp index 48d1e3d..2e53fb6 100644 --- a/include/boost/iterator/detail/categories.hpp +++ b/include/boost/iterator/detail/categories.hpp @@ -329,6 +329,25 @@ namespace boost template <> struct minimum_category { typedef minimum_category type; }; # endif + // + // Tag classification for use in iterator_adaptor + // + template + struct is_access_tag + : mpl::or_< + is_tag + , mpl::or_< + is_tag + , is_tag + > + > + {}; + + template + struct is_traversal_tag + : is_tag + {}; + } // namespace detail } // namespace boost diff --git a/include/boost/iterator/filter_iterator.hpp b/include/boost/iterator/filter_iterator.hpp index 390dc8e..cd490dc 100644 --- a/include/boost/iterator/filter_iterator.hpp +++ b/include/boost/iterator/filter_iterator.hpp @@ -15,34 +15,25 @@ namespace boost { - namespace detail - { - template - struct filter_iterator_category - { - typedef iterator_tag< - typename access_category::type - , typename minimum_category< - bidirectional_traversal_tag - , typename traversal_category::type - >::type - > type; - }; - - } // namespace detail template class filter_iterator : public iterator_adaptor< filter_iterator, Iterator , use_default - , typename detail::filter_iterator_category::type + , typename detail::minimum_category< + bidirectional_traversal_tag + , typename traversal_category::type + >::type > { typedef iterator_adaptor< filter_iterator, Iterator , use_default - , typename detail::filter_iterator_category::type + , typename detail::minimum_category< + bidirectional_traversal_tag + , typename traversal_category::type + >::type > super_t; friend class iterator_core_access; diff --git a/include/boost/iterator/iterator_adaptor.hpp b/include/boost/iterator/iterator_adaptor.hpp index faecc1a..af14283 100644 --- a/include/boost/iterator/iterator_adaptor.hpp +++ b/include/boost/iterator/iterator_adaptor.hpp @@ -148,9 +148,18 @@ namespace boost > struct iterator_adaptor_base { - private: // intermediate results - typedef typename detail::ia_dflt_help< - Category, BOOST_ITERATOR_CATEGORY + private: // intermediate results + + typedef typename mpl::apply_if< + mpl::or_< + is_same + , mpl::or_< + is_access_tag + , is_traversal_tag + > + > + , BOOST_ITERATOR_CATEGORY + , mpl::identity >::type category; typedef typename detail::ia_dflt_help< @@ -170,9 +179,17 @@ namespace boost Value, iterator_value >::type - , typename access_category_tag::type - - , typename traversal_category_tag::type + , typename mpl::apply_if< + is_access_tag + , mpl::identity + , access_category_tag + >::type + + , typename mpl::apply_if< + is_traversal_tag + , mpl::identity + , traversal_category_tag + >::type , reference diff --git a/include/boost/iterator/transform_iterator.hpp b/include/boost/iterator/transform_iterator.hpp index f281b82..cb41f07 100644 --- a/include/boost/iterator/transform_iterator.hpp +++ b/include/boost/iterator/transform_iterator.hpp @@ -90,10 +90,7 @@ namespace boost transform_iterator , Iterator , cv_value_type - , iterator_tag< - access_category - , typename traversal_category::type - > + , access_category , result_type > type; }; diff --git a/test/iterator_adaptor_test.cpp b/test/iterator_adaptor_test.cpp index 32edd85..5c471d7 100644 --- a/test/iterator_adaptor_test.cpp +++ b/test/iterator_adaptor_test.cpp @@ -112,6 +112,17 @@ public: {} }; +// Non-functional iterator for category modification checking +template +struct modify_category + : boost::iterator_adaptor< + modify_category + , Iter + , boost::use_default + , Category + > +{}; + template struct fwd_iterator : boost::iterator_adaptor< @@ -221,6 +232,15 @@ main() test = static_assert_same::value; test = static_assert_same::value; + + // Test category modification + typedef modify_category ReadableIter; + test = static_assert_same::value; + + typedef modify_category IncrementableIter; + test = static_assert_same::value; + test = static_assert_same::value; + } // Test the iterator_adaptor diff --git a/test/unit_tests.cpp b/test/unit_tests.cpp index 4887357..622d9a7 100644 --- a/test/unit_tests.cpp +++ b/test/unit_tests.cpp @@ -91,6 +91,25 @@ void category_test() std::output_iterator_tag,std::random_access_iterator_tag, std::output_iterator_tag >::value; + BOOST_STATIC_ASSERT((is_traversal_tag< incrementable_traversal_tag >::value)); + BOOST_STATIC_ASSERT((is_traversal_tag< single_pass_traversal_tag >::value)); + BOOST_STATIC_ASSERT((is_traversal_tag< forward_traversal_tag >::value)); + BOOST_STATIC_ASSERT((is_traversal_tag< bidirectional_traversal_tag >::value)); + BOOST_STATIC_ASSERT((is_traversal_tag< random_access_traversal_tag >::value)); + + BOOST_STATIC_ASSERT((!is_traversal_tag< std::input_iterator_tag >::value)); + BOOST_STATIC_ASSERT((!is_traversal_tag< readable_iterator_tag >::value)); + + BOOST_STATIC_ASSERT((is_access_tag< readable_iterator_tag >::value)); + BOOST_STATIC_ASSERT((is_access_tag< writable_iterator_tag >::value)); + BOOST_STATIC_ASSERT((is_access_tag< swappable_iterator_tag >::value)); + BOOST_STATIC_ASSERT((is_access_tag< readable_writable_iterator_tag >::value)); + BOOST_STATIC_ASSERT((is_access_tag< readable_lvalue_iterator_tag >::value)); + BOOST_STATIC_ASSERT((is_access_tag< writable_lvalue_iterator_tag >::value)); + + BOOST_STATIC_ASSERT((!is_access_tag< std::input_iterator_tag >::value)); + BOOST_STATIC_ASSERT((!is_access_tag< incrementable_traversal_tag >::value)); + (void)test; } From afa92675a200cb489eaf4e78788a8018fd766ecd Mon Sep 17 00:00:00 2001 From: Thomas Witt Date: Tue, 22 Jul 2003 07:56:08 +0000 Subject: [PATCH 190/265] Fixed struct/class mixup in indirect_iterator declaration. [SVN r19249] --- include/boost/iterator/indirect_iterator.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/iterator/indirect_iterator.hpp b/include/boost/iterator/indirect_iterator.hpp index 0839072..59babdf 100644 --- a/include/boost/iterator/indirect_iterator.hpp +++ b/include/boost/iterator/indirect_iterator.hpp @@ -35,7 +35,7 @@ namespace boost { template - struct indirect_iterator; + class indirect_iterator; template struct referent; From 87f93ec5219f70cb9e1f84bf3df2d36834581360 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 29 Jul 2003 16:11:14 +0000 Subject: [PATCH 191/265] initial commit [SVN r19345] --- doc/index.rst | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100755 doc/index.rst diff --git a/doc/index.rst b/doc/index.rst new file mode 100755 index 0000000..4760219 --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,214 @@ ++++++++++++++++++++++++++++++++++++++++++++++++++ + The Boost Iterator Library |(logo)|__ ++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. |(logo)| image:: ../../../c++boost.gif + +__ ../../../index.htm + +:Authors: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organizations: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, University of Hanover `Institute for Transport + Railway Operation and Construction`_ +:date: $Date$ +:copyright: Copyright Dave Abrahams, Jeremy Siek, Thomas Witt 2003. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:Abstract: The Boost Iterator Library is a system of concepts_ which + extend the C++ standard iterator definition and a framework + of components for building iterators based on these + extended concepts. The extended iterator concepts have + been carefully designed so that new-style iterators will be + compatible with old-style algorithms, though algorithms may + need to be updated if they want to take full advantage of + the new-style iterators. Several components of this + library have been proposed for the C++ standard technical + report. The components of the Boost Iterator Library + replace the older Boost Iterator Adaptor Library. + +.. _concepts: ../../more/generic_programming.html + +.. contents:: **Table of Contents** + +===================== + New-Style Iterators +===================== + +The iterator categories defined in C++98 are extremely limiting +because they bind together two orthogonal concepts: traversal and +element access. For example, because a random access iterator is +required to return a reference (and not a proxy) when dereferenced, it +is impossible to capture the capabilities of +``vector::iterator`` using the C++98 categories. The infamous +"``vector`` is not a container, and its iterators aren't random +access iterators", debacle about which Herb Sutter wrote two papers +for the standards comittee (n1185_ and n1211_), and a `Guru of the +Week`__. New-style iterators go well beyond patching up +``vector``, though. There are lots of other iterators already +in use which can't be adequately represented by the existing concepts. +For details about the new iterator concepts, see our + +.. _n1185: http://www.gotw.ca/publications/N1185.pdf +.. _n1211: http://www.gotw.ca/publications/N1211.pdf +__ http://www.gotw.ca/gotw/050.htm + + + `Standard Proposal For New-Style Iterators`__ + +__ new-iter-concepts.html + +============================= + Iterator Facade and Adaptor +============================= + +Writing standard-conforming iterators is tricky. In order to ease the +implementation of new iterators, the iterator library provides the +|facade|_ class template, which implements many useful +defaults and compile-time checks designed to help the author iterator +ensure that his iterator is correct. It is common to define a new +iterator which behaves like another iterator, but modifies some aspect +of its behavior. For that purpose, the library supplies the +|adaptor|_ class template, which is specially designed to +take advantage of as much of the underlying iterator's behavior as +possible. + +.. |facade| replace:: ``iterator_facade`` +.. _facade: iterator_facade.html +.. |adaptor| replace:: ``iterator_adaptor`` +.. _adaptor: iterator_adaptor.html + +Both |facade|_ and |adaptor|_ as well as many of +the `specialized adaptors`_ mentioned below have been proposed for +standardization; see our + + `Standard Proposal For Iterator Facade and Adaptor`__ + +for more details. + +__ facade-and-adaptor.html + +====================== + Specialized Adaptors +====================== + +The iterator library supplies a useful suite of standard-conforming +iterator templates based on the Boost `iterator facade and adaptor`_. + +* |counting|_: an iterator over a sequence of consecutive values. + Implements a "lazy sequence" + +* |filter|_: an iterator over the subset of elements of some + sequence which satisfy a given predicate + +* |indirect|_: an iterator over the objects *pointed-to* by the + elements of some sequence. + +* |permutation|_: an iterator over the elements of some random-access + sequence, rearranged according to some sequence of integer indices. + +* |reverse|_: an iterator which traverses the elements of some + bidirectional sequence in reverse. Corrects many of the + shortcomings of C++98's ``std::reverse_iterator``. + +* |transform|_: an iterator over elements which are the result of + applying some functional transformation to the elements of an + underlying sequence. This component also replaces the old + ``projection_iterator_adaptor``. + +.. |counting| replace:: ``counting_iterator`` +.. _counting: counting_iterator.html + +.. |filter| replace:: ``filter_iterator`` +.. _filter: filter_iterator.html + +.. |indirect| replace:: ``indirect_iterator`` +.. _indirect: indirect_iterator.html + +.. |permutation| replace:: ``permutation_iterator`` +.. _permutation: permutation_iterator.html + +.. |reverse| replace:: ``reverse_iterator`` +.. _reverse: reverse_iterator.html + +.. |transform| replace:: ``transform_iterator`` +.. _transform: transform_iterator.html + +==================== + Iterator Utilities +==================== + +Traits +------ + +* |iterator_traits|_: Provides MPL_\ -compatible metafunctions which + retrieve an iterator's traits. Also corrects for the deficiencies + of broken implementations of ``std::iterator_traits``. + +* |interoperable|_: Provides an MPL_\ -compatible metafunction for + testing iterator interoperability + +.. |iterator_traits| replace:: ``iterator_traits.hpp`` +.. _iterator_traits: iterator_traits.html + +.. |interoperable| replace:: ``interoperable.hpp`` +.. _interoperable: interoperable.html + +.. _MPL: ../../mpl/doc/index.html + +Testing and Concept Checking +---------------------------- + +* |iterator_archetypes|_: Add summary here + +* |iterator_concepts|_: Add summary + +.. |iterator_archetypes| replace:: ``iterator_archetypes.hpp`` +.. _iterator_archetypes: iterator_archetypes.html + +.. |iterator_concepts| replace:: ``iterator_concepts.hpp`` +.. _iterator_concepts: iterator_concepts.html + + +======================================================= + Upgrading from the old Boost Iterator Adaptor Library +======================================================= + +Turn your policy class into the body of the iterator + +Use transform_iterator with a true reference type for +projection_iterator. + +========= + History +========= + +In 2000 Dave Abrahams was writing an iterator for a container of +pointers, which would access the pointed-to elements when +dereferenced. Naturally, being a library writer, he decided to +generalize the idea and the Boost Iterator Adaptor library was born. +Dave was inspired by some writings of Andrei Alexandrescu and chose a +policy based design (though he probably didn't capture Andrei's idea +very well - there was only one policy class for all the iterator's +orthogonal properties). Soon Jeremy Siek realized he would need the +library and they worked together to produce a "Boostified" version, +which was reviewed and accepted into the library. They wrote a paper +and made several important revisions of the code. + +Eventually, several shortcomings of the older library began to make +the need for a rewrite apparent. Dave and Jeremy started working at +the Santa Cruz C++ committee meeting in 2002, and had quickly +generated a working prototype. Thomas Witt expressed interest and +became the voice of compile-time checking for the project... + +.. + LocalWords: Abrahams Siek Witt const bool Sutter's WG int UL LI href Lvalue + LocalWords: ReadableIterator WritableIterator SwappableIterator cv pre iter + LocalWords: ConstantLvalueIterator MutableLvalueIterator CopyConstructible TR + LocalWords: ForwardTraversalIterator BidirectionalTraversalIterator lvalue + LocalWords: RandomAccessTraversalIterator dereferenceable Incrementable tmp + LocalWords: incrementable xxx min prev inplace png oldeqnew AccessTag struct + LocalWords: TraversalTag typename lvalues DWA Hmm JGS From bd3312cdf2d700fb6617290dc544ff0806f3dee2 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 29 Jul 2003 21:20:39 +0000 Subject: [PATCH 192/265] Add empty :alt: field for the logo so it doesn't produce document title text [SVN r19347] --- doc/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/index.rst b/doc/index.rst index 4760219..5ae063e 100755 --- a/doc/index.rst +++ b/doc/index.rst @@ -3,6 +3,7 @@ +++++++++++++++++++++++++++++++++++++++++++++++++ .. |(logo)| image:: ../../../c++boost.gif + :alt: __ ../../../index.htm From 3ab9da6a9991042eb185b2cd69ac211fe8051308 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 29 Jul 2003 22:24:57 +0000 Subject: [PATCH 193/265] Added dividers [SVN r19348] --- doc/index.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/index.rst b/doc/index.rst index 5ae063e..c8ea881 100755 --- a/doc/index.rst +++ b/doc/index.rst @@ -7,6 +7,10 @@ __ ../../../index.htm + +------------------------------------- + + :Authors: David Abrahams, Jeremy Siek, Thomas Witt :Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de :organizations: `Boost Consulting`_, Indiana University `Open Systems @@ -35,6 +39,10 @@ __ ../../../index.htm .. contents:: **Table of Contents** + +------------------------------------- + + ===================== New-Style Iterators ===================== From 508696a1692ccb8e0cb2d199f42d24a1e4d71d8d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 29 Jul 2003 22:25:39 +0000 Subject: [PATCH 194/265] initial commit [SVN r19349] --- doc/index.html | 185 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100755 doc/index.html diff --git a/doc/index.html b/doc/index.html new file mode 100755 index 0000000..7d3058b --- /dev/null +++ b/doc/index.html @@ -0,0 +1,185 @@ + + + + + + +The Boost Iterator Library + + + + + + + + From 19977c757fea709e28871effaeae0fe7c5d8a48e Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Tue, 5 Aug 2003 16:36:51 +0000 Subject: [PATCH 195/265] factored iterator facade stuff into several files [SVN r19464] --- doc/facade-and-adaptor.html | 789 +++++-------------------------- doc/facade-and-adaptor.rst | 496 +------------------ doc/index.html | 22 +- doc/index.rst | 10 +- doc/iterator_adaptor.rst | 18 + doc/iterator_adaptor_body.rst | 32 ++ doc/iterator_facade.rst | 33 ++ doc/iterator_facade_abstract.rst | 4 + doc/iterator_facade_body.rst | 180 +++++++ doc/iterator_facade_ref.rst | 284 +++++++++++ doc/new-iter-concepts.html | 205 +------- 11 files changed, 703 insertions(+), 1370 deletions(-) create mode 100644 doc/iterator_adaptor.rst create mode 100644 doc/iterator_adaptor_body.rst create mode 100644 doc/iterator_facade.rst create mode 100644 doc/iterator_facade_abstract.rst create mode 100644 doc/iterator_facade_body.rst create mode 100644 doc/iterator_facade_ref.rst diff --git a/doc/facade-and-adaptor.html b/doc/facade-and-adaptor.html index 996ea4c..ca810a4 100755 --- a/doc/facade-and-adaptor.html +++ b/doc/facade-and-adaptor.html @@ -3,204 +3,13 @@ - + Iterator Facade and Adaptor - + - +
@@ -218,7 +27,7 @@ ul.auto-toc { Lab, University of Hanover Institute for Transport Railway Operation and Construction Date: -2003-07-12 +2003-07-13 Number:This document is a revised version of the official N1476=03-0059 Copyright: @@ -238,76 +47,74 @@ by adapting other iterators.

Table of Contents

-

Motivation

+

Motivation

Iterators play an important role in modern C++ programming. The iterator is the central abstraction of the algorithms of the Standard Library, allowing algorithms to be re-used in in a wide variety of @@ -400,15 +207,15 @@ applies some user-specified function during the dereference of the iterator.

-

Impact on the Standard

+

Impact on the Standard

This proposal is purely an addition to the C++ standard library. However, note that this proposal relies on the proposal for New Iterator Concepts.

-

Design

+

Design

-

Iterator Concepts

+

Iterator Concepts

This proposal is formulated in terms of the new iterator concepts as proposed in n1477, since user-defined and especially adapted iterators suffer from the well known categorization problems that are @@ -418,7 +225,7 @@ is a direct mapping between new and old categories. This proposal could be reformulated using this mapping if n1477 was not accepted.

-

Interoperability

+

Interoperability

The question of iterator interoperability is poorly addressed in the current standard. There are currently two defect reports that are concerned with interoperability issues.

@@ -438,7 +245,7 @@ fixes the issues raised in 280. It provides the desired interoperability without introducing unwanted overloads.

-

Iterator Facade

+

Iterator Facade

While the iterator interface is rich, there is a core subset of the interface that is necessary for all the functionality. We have identified the following core behaviors for iterators:

@@ -457,7 +264,7 @@ include the associated types exposed through iterator traits:

Iterator facade uses the Curiously Recurring Template Pattern (CRTP) [Cop95] so that the user can specify the behavior of iterator_facade in a derived class. Former designs used policy -objects to specify the behavior. The proposal does not use policy +objects to specify the behavior. iterator_facade does not use policy objects for several reasons:

    @@ -477,7 +284,7 @@ impossible.
-

Usage

+

Usage

The user of iterator_facade derives his iterator class from an instantiation of iterator_facade which takes the derived iterator class as the first template parameter. The order of the other @@ -490,8 +297,8 @@ parameter and omit the Referenceiterator facade -requirements.

+briefly below and in more detail in the iterator facade +requirements.

@@ -539,14 +346,13 @@ constructor. Finally, if the iterator is to model Forward Traversal Iterator or a more-refined iterator concept, a default constructor is required.

-
-

Iterator Core Access

+

Iterator Core Access

iterator_facade and the operator implementations need to be able to access the core member functions in the derived class. Making the core member functions public would expose an implementation detail to -the user. This proposal frees the public interface of the derived -iterator type from any implementation detail.

+the user. The design used here ensures that implementation details do +not appear in the public interface of the derived iterator type.

Preventing direct access to the core member functions has two advantages. First, there is no possibility for the user to accidently use a member function of the iterator when a member of the value_type @@ -559,12 +365,11 @@ directly.

In a naive implementation, keeping the derived class' core member functions private would require it to grant friendship to iterator_facade and each of the seven operators. In order to -reduce the burden of limiting access, this proposal provides -iterator_core_access, a class that acts as a gateway to the core -member functions in the derived iterator class. The author of the -derived class only needs to grant friendship to -iterator_core_access to make his core member functions available -to the library.

+reduce the burden of limiting access, iterator_core_access is +provided, a class that acts as a gateway to the core member functions +in the derived iterator class. The author of the derived class only +needs to grant friendship to iterator_core_access to make his core +member functions available to the library.

iterator_core_access will be typically implemented as an empty @@ -576,13 +381,13 @@ open a safety loophole, as every core member function preserves the invariants of the iterator.

-

operator[]

+

operator[]

The indexing operator for a generalized iterator presents special challenges. A random access iterator's operator[] is only required to return something convertible to its value_type. Requiring that it return an lvalue would rule out currently-legal random-access iterators which hold the referenced value in a data -member (e.g. counting_iterator), because *(p+n) is a reference +member (e.g. counting_iterator), because *(p+n) is a reference into the temporary iterator p+n, which is destroyed when operator[] returns.

Writable iterators built with iterator_facade implement the @@ -596,8 +401,8 @@ to implement an operator[] whi iterator class; it will hide the one supplied by iterator_facade from clients of her iterator.

-
-

operator->

+
+

operator->

The reference type of a readable iterator (and today's input iterator) need not in fact be a reference, so long as it is convertible to the iterator's value_type. When the value_type @@ -605,14 +410,22 @@ is a class, however, it must still be possible to access members through operator->. Therefore, an iterator whose reference type is not in fact a reference must return a proxy containing a copy of the referenced value from its operator->.

-

This proposal does not explicitly specify the return type for -operator-> and operator[]. Instead it requires each -iterator_facade instantiation to meet the requirements of its -iterator_category.

+

The return type for operator-> and operator[] is not +explicitly specified. Instead it requires each iterator_facade +instantiation to meet the requirements of its iterator_category.

+
+ ++ + + +
[Cop95][Coplien, 1995] Coplien, J., Curiously Recurring Template +Patterns, C++ Report, February 1995, pp. 24-27.
+
-

Iterator Adaptor

-

The iterator_adaptor class template adapts some Base 3 +

Iterator Adaptor

+

The iterator_adaptor class template adapts some Base 3 type to create a new iterator. Instantiations of iterator_adaptor are derived from a corresponding instantiation of iterator_facade and implement the core behaviors in terms of the Base type. In @@ -621,7 +434,7 @@ instance of the Base type, whi - @@ -647,7 +460,7 @@ template parameter may not always be identical to the iterator's assumption.

-

Specialized Adaptors

+

Specialized Adaptors

This proposal also contains several examples of specialized adaptors which were easily implemented using iterator_adaptor:

    @@ -684,9 +497,9 @@ Standard compliant iterators).

-

Proposed Text

+

Proposed Text

-

Iterator facade [lib.iterator.facade]

-

iterator_facade is a base class template which implements the -interface of standard iterators in terms of a few core functions -and associated types, to be supplied by a derived iterator class.

+

Iterator facade [lib.iterator.facade]

+

..include:: iterator_facade_abstract.rst

-

Class template iterator_facade

-
-template <
-    class Derived
-  , class Value
-  , class AccessCategory
-  , class TraversalCategory
-  , class Reference  = /* see below */
-  , class Difference = ptrdiff_t
->
-class iterator_facade {
-public:
-    typedef remove_cv<Value>::type value_type;
-    typedef Reference reference;
-    typedef /* see description of operator-> */ pointer;
-    typedef Difference difference_type;
-    typedef iterator_tag<AccessCategory, TraversalCategory> iterator_category;
-
-    reference operator*() const;
-    /* see below */ operator->() const;
-    /* see below */ operator[](difference_type n) const;
-    Derived& operator++();
-    Derived operator++(int);
-    Derived& operator--();
-    Derived operator--(int);
-    Derived& operator+=(difference_type n);
-    Derived& operator-=(difference_type n);
-    Derived operator-(difference_type n) const;
-};
-
-// Comparison operators
-template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
-          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
-typename enable_if_interoperable<Dr1, Dr2, bool>::type // exposition
-operator ==(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
-            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
-
-template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
-          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
-typename enable_if_interoperable<Dr1, Dr2, bool>::type
-operator !=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
-            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
-
-template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
-          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
-typename enable_if_interoperable<Dr1, Dr2, bool>::type
-operator <(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
-           iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
-
-template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
-          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
-typename enable_if_interoperable<Dr1, Dr2, bool>::type
-operator <=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
-            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
-
-template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
-          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
-typename enable_if_interoperable<Dr1, Dr2, bool>::type
-operator >(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
-           iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
-
-template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
-          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
-typename enable_if_interoperable<Dr1, Dr2, bool>::type
-operator >=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
-            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
-
-template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
-          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
-typename enable_if_interoperable<Dr1, Dr2, bool>::type
-operator >=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
-            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
-
-// Iterator difference
-template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
-          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
-typename enable_if_interoperable<Dr1, Dr2, bool>::type
-operator -(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
-           iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
-
-// Iterator addition
-template <class Derived, class V, class AC, class TC, class R, class D>
-Derived operator+ (iterator_facade<Derived, V, AC, TC, R, D> const&,
-                   typename Derived::difference_type n)
-
-

[Note: The enable_if_interoperable template used above is for exposition -purposes. The member operators should be only be in an overload set -provided the derived types Dr1 and Dr2 are interoperable, by -which we mean they are convertible to each other. The -enable_if_interoperable approach uses SFINAE to take the operators -out of the overload set when the types are not interoperable.]

- -
-
-

iterator_facade requirements

-

The Derived template parameter must be a class derived from -iterator_facade.

-

The default for the Reference parameter is Value& if the -access category for iterator_facade is implicitly convertible to -writable_iterator_tag, and const Value& otherwise.

-

The following table describes the other requirements on the -Derived parameter. Depending on the resulting iterator's -iterator_category, a subset of the expressions listed in the table -are required to be valid. The operations in the first column must be -accessible to member functions of class iterator_core_access.

-

In the table below, X is the derived iterator type, a is an -object of type X, b and c are objects of type const X, -n is an object of X::difference_type, y is a constant -object of a single pass iterator type interoperable with X, and z -is a constant object of a random access traversal iterator type -interoperable with X.

-
[3]The term "Base" here does not refer to a base class and is +
[3]The term "Base" here does not refer to a base class and is not meant to imply the use of derivation. We have followed the lead of the standard library, which provides a base() function to access the underlying iterator object of a reverse_iterator adaptor.
------ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ExpressionReturn TypeAssertion/NoteRequired to implement -Iterator Concept(s)
c.dereference()X::reference Readable Iterator, Writable -Iterator
c.equal(b)convertible to booltrue iff b and c are -equivalent.Single Pass Iterator
c.equal(y)convertible to booltrue iff c and y refer to the -same position. Implements c == y -and c != y.Single Pass Iterator
a.advance(n)unused Random Access Traversal -Iterator
a.increment()unused Incrementable Iterator
a.decrement()unused Bidirectional Traversal -Iterator
c.distance_to(b)convertible to -X::difference_typeequivalent to distance(c, b)Random Access Traversal -Iterator
c.distance_to(z)convertible to -X::difference_typeequivalent to distance(c, z). -Implements c - z, c < z, c -<= z, c > z, and c >= c.Random Access Traversal -Iterator
- -

-
-

iterator_facade operations

-

The operations in this section are described in terms of operations on -the core interface of Derived which may be inaccessible -(i.e. private). The implementation should access these operations -through member functions of class iterator_core_access.

-

reference operator*() const;

- --- - - - -
Returns:static_cast<Derived const*>(this)->dereference()
-

operator->() const; (see below)

- --- - - - -
Returns:

If X::reference is a reference type, returns an object -of type X::pointer equal to:

-
-&static_cast<Derived const*>(this)->dereference()
-
-

Otherwise returns an object of unspecified type such that, given an -object a of type X, a->m is equivalent to (w = *a, -w.m) for some temporary object w of type X::value_type.

-

The type X::pointer is Value* if the access category for -X is implicitly convertible to writable_iterator_tag, and -Value const* otherwise.

-
-

unspecified operator[](difference_type n) const;

- --- - - - -
Returns:an object convertible to X::reference and holding a copy -p of a+n such that, for a constant object v of type -X::value_type, X::reference(a[n] = v) is equivalent -to p = v.
-

Derived& operator++();

- --- - - - -
Effects:
-static_cast<Derived*>(this)->increment();
-return *this;
-
-
- -

Derived operator++(int);

- --- - - - -
Effects:
-Derived tmp(static_cast<Derived const*>(this));
-++*this;
-return tmp;
-
-
-

Derived& operator--();

- --- - - - -
Effects:
-static_cast<Derived*>(this)->decrement();
-return *this;
-
-
-

Derived operator--(int);

- --- - - - -
Effects:
-Derived tmp(static_cast<Derived const*>(this));
---*this;
-return tmp;
-
-
-

Derived& operator+=(difference_type n);

- --- - - - -
Effects:
-static_cast<Derived*>(this)->advance(n);
-return *this;
-
-
-

Derived& operator-=(difference_type n);

- --- - - - -
Effects:
-static_cast<Derived*>(this)->advance(-n);
-return *this;
-
-
-

Derived operator-(difference_type n) const;

- --- - - - - - -
Effects:Derived tmp(static_cast<Derived const*>(this)); -return tmp -= n;
Returns:static_cast<Derived const*>(this)->advance(-n);
+

Class template iterator_facade

+

..include:: iterator_facade_ref.rst

-

Iterator adaptor [lib.iterator.adaptor]

+

Iterator adaptor [lib.iterator.adaptor]

The iterator_adaptor is a base class template derived from an instantiation of iterator_facade. The core interface functions expected by iterator_facade are implemented in terms of the @@ -1097,7 +580,7 @@ depends on the operations supported by the iterator_facade are redefined in the Derived class.

-

Class template iterator_adaptor

+

Class template iterator_adaptor

 template <
     class Derived
@@ -1142,7 +625,7 @@ class iterator_adaptor
 
-

iterator_adaptor requirements

+

iterator_adaptor requirements

The Derived template parameter must be a derived class of iterator_adaptor. The Base type must implement the expressions involving m_iterator in the specifications of those private member @@ -1196,7 +679,7 @@ else iterator_category = Category; -->

-

iterator_adaptor public operations

+

iterator_adaptor public operations

iterator_adaptor();

@@ -1230,7 +713,7 @@ else
-

iterator_adaptor protected member functions

+

iterator_adaptor protected member functions

Base const& base_reference() const;

@@ -1251,7 +734,7 @@ else
-

iterator_adaptor private member functions

+

iterator_adaptor private member functions

typename iterator_adaptor::reference dereference() const;

@@ -1320,7 +803,7 @@ typename iterator_adaptor::difference_type distance_to(
-

Specialized adaptors [lib.iterator.special.adaptors]

+

Specialized adaptors [lib.iterator.special.adaptors]

[Note: The enable_if_convertible<X,Y>::type expression used in @@ -1331,7 +814,7 @@ type Y. The -

Indirect iterator

+

Indirect iterator

The indirect iterator adapts an iterator by applying an extra dereference inside of operator*(). For example, this iterator adaptor makes it possible to view a container of pointers @@ -1340,7 +823,7 @@ adaptor makes it possible to view a container of pointers

-

Class template indirect_iterator

+

Class template indirect_iterator

 template <
     class Iterator
@@ -1375,7 +858,7 @@ private: // as-if specification
 
-

indirect_iterator requirements

+

indirect_iterator requirements

The value_type of the Iterator template parameter should itself be dereferenceable. The return type of the operator* for the value_type must be the same type as the Reference template @@ -1400,7 +883,7 @@ iterator will model the most refined standard access concept that is modeled by the value type of Iterator.

@@ -1448,13 +931,13 @@ indirect_iterator(
-

Reverse iterator

+

Reverse iterator

The reverse iterator adaptor flips the direction of a base iterator's motion. Invoking operator++() moves the base iterator backward and invoking operator--() moves the base iterator forward.

-

Class template reverse_iterator

+

Class template reverse_iterator

 template <class Iterator>
 class reverse_iterator :
@@ -1493,7 +976,7 @@ private: // as-if specification
 
-

reverse_iterator requirements

+

reverse_iterator requirements

The base Iterator must be a model of Bidirectional Traversal Iterator. The resulting reverse_iterator will be a model of the most refined standard traversal and access concepts that are modeled @@ -1540,14 +1023,14 @@ reverse_iterator(

-

Transform iterator

+

Transform iterator

The transform iterator adapts an iterator by applying some function object to the result of dereferencing the iterator. In other words, the operator* of the transform iterator first dereferences the base iterator, passes the result of this to the function object, and then returns the result.

-

Class template transform_iterator

+

Class template transform_iterator

 template <class AdaptableUnaryFunction,
           class Iterator, 
@@ -1575,7 +1058,7 @@ private:
 
-

transform_iterator requirements

+

transform_iterator requirements

The type AdaptableUnaryFunction must be Assignable, Copy Constructible, and the expression f(x) must be valid where f is an object of type AdaptableUnaryFunction, x is an object of @@ -1600,7 +1083,7 @@ concept that is modeled by Iterator result_type.

@@ -1649,7 +1132,7 @@ transform_iterator(
-

transform_iterator private operations

+

transform_iterator private operations

typename transform_iterator::value_type dereference() const;

@@ -1662,7 +1145,7 @@ transform_iterator(
-

Filter iterator

+

Filter iterator

The filter iterator adaptor creates a view of an iterator range in which some elements of the range are skipped over. A predicate function object controls which elements are skipped. When the @@ -1674,7 +1157,7 @@ of the underlying range. Therefore the constructor of the filter iterator takes two iterator parameters: the position for the filtered iterator and the end of the range.

-

Class template filter_iterator

+

Class template filter_iterator

 template <class Predicate, class Iterator>
 class filter_iterator
@@ -1716,7 +1199,7 @@ class filter_iterator
 
-

filter_iterator requirements

+

filter_iterator requirements

The base Iterator parameter must be a model of Readable Iterator and Single Pass Iterator. The resulting filter_iterator will be a model of Forward Traversal Iterator if Iterator is, otherwise the @@ -1732,7 +1215,7 @@ expression p(x) must be valid p(x) must be convertible to bool.

@@ -1805,14 +1288,14 @@ filter_iterator(
-
-

Counting iterator

+
+

Counting iterator

The counting iterator adaptor implements dereference by returning a reference to the base object. The other operations are implemented by the base m_iterator, as per the inheritance from iterator_adaptor.

-

Class template counting_iterator

+

Class template counting_iterator

 template <class Incrementable, class Category = use_default, class Difference = use_default>
 class counting_iterator
@@ -1845,7 +1328,7 @@ the cases when the Incrementable
 
-

counting_iterator requirements

+

counting_iterator requirements

The Incrementable type must be Default Constructible, Copy Constructible, and Assignable. The default distance is an implementation defined signed integegral type.

@@ -1873,7 +1356,7 @@ i < j
-

counting_iterator operations

+

counting_iterator operations

counting_iterator();

@@ -1904,7 +1387,7 @@ object copy constructed from x
-

Function output iterator

+

Function output iterator

The function output iterator adaptor makes it easier to create custom output iterators. The adaptor takes a unary function and creates a model of Output Iterator. Each item assigned to the output iterator is @@ -1913,7 +1396,7 @@ iterator is that creating a conforming output iterator is non-trivial, particularly because the proper implementation usually requires a proxy object.

-

Class template function_output_iterator

+

Class template function_output_iterator

 template <class UnaryFunction>
 class function_output_iterator {
@@ -1941,7 +1424,7 @@ public:
 
-

function_output_iterator requirements

+

function_output_iterator requirements

The UnaryFunction must be Assignable, Copy Constructible, and the expression f(x) must be valid, where f is an object of type UnaryFunction and x is an object of a type accepted by f. @@ -1949,7 +1432,7 @@ The resulting function_output_iterator

-

function_output_iterator operations

+

function_output_iterator operations

explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());

@@ -1990,7 +1473,7 @@ a copy of the unary function f
-

function_output_iterator::output_proxy operations

+

function_output_iterator::output_proxy operations

output_proxy(UnaryFunction& f);

@@ -2014,14 +1497,6 @@ return *this;
- - -- - - -
[Cop95][Coplien, 1995] Coplien, J., Curiously Recurring Template -Patterns, C++ Report, February 1995, pp. 24-27.
- - diff --git a/doc/facade-and-adaptor.rst b/doc/facade-and-adaptor.rst index 3c71e97..886124c 100644 --- a/doc/facade-and-adaptor.rst +++ b/doc/facade-and-adaptor.rst @@ -164,213 +164,12 @@ interoperability without introducing unwanted overloads. Iterator Facade =============== -While the iterator interface is rich, there is a core subset of the -interface that is necessary for all the functionality. We have -identified the following core behaviors for iterators: - -* dereferencing -* incrementing -* decrementing -* equality comparison -* random-access motion -* distance measurement - -In addition to the behaviors listed above, the core interface elements -include the associated types exposed through iterator traits: -``value_type``, ``reference``, ``difference_type``, and -``iterator_category``. - -Iterator facade uses the Curiously Recurring Template Pattern (CRTP) -[Cop95]_ so that the user can specify the behavior of -``iterator_facade`` in a derived class. Former designs used policy -objects to specify the behavior. The proposal does not use policy -objects for several reasons: - - 1. the creation and eventual copying of the policy object may create - overhead that can be avoided with the current approach. - - 2. The policy object approach does not allow for custom constructors - on the created iterator types, an essential feature if - ``iterator_facade`` should be used in other library - implementations. - - 3. Without the use of CRTP, the standard requirement that an - iterator's ``operator++`` returns the iterator type itself means - that all iterators generated by ``iterator_facade`` would be - instantiations of ``iterator_facade``. Cumbersome type generator - metafunctions would be needed to build new parameterized - iterators, and a separate ``iterator_adaptor`` layer would be - impossible. - -Usage ------ - -The user of ``iterator_facade`` derives his iterator class from an -instantiation of ``iterator_facade`` which takes the derived iterator -class as the first template parameter. The order of the other -template parameters to ``iterator_facade`` have been carefully chosen -to take advantage of useful defaults. For example, when defining a -constant lvalue iterator, the user can pass a const-qualified version -of the iterator's ``value_type`` as ``iterator_facade``\ 's ``Value`` -parameter and omit the ``Reference`` parameter which follows. - -The derived iterator class must define member functions implementing -the iterator's core behaviors. The following table describes -expressions which are required to be valid depending on the category -of the derived iterator type. These member functions are described -briefly below and in more detail in the `iterator facade -requirements`_. - - +------------------------+-------------------------------+ - |Expression |Effects | - +========================+===============================+ - |``i.dereference()`` |Access the value referred to | - +------------------------+-------------------------------+ - |``i.equal(j)`` |Compare for equality with ``j``| - +------------------------+-------------------------------+ - |``i.increment()`` |Advance by one position | - +------------------------+-------------------------------+ - |``i.decrement()`` |Retreat by one position | - +------------------------+-------------------------------+ - |``i.advance(n)`` |Advance by ``n`` positions | - +------------------------+-------------------------------+ - |``i.distance_to(j)`` |Measure the distance to ``j`` | - +------------------------+-------------------------------+ - -.. Should we add a comment that a zero overhead implementation of iterator_facade - is possible with proper inlining? - -In addition to implementing the core interface functions, an iterator -derived from ``iterator_facade`` typically defines several -constructors. To model any of the standard iterator concepts, the -iterator must at least have a copy constructor. Also, if the iterator -type ``X`` is meant to be automatically interoperate with another -iterator type ``Y`` (as with constant and mutable iterators) then -there must be an implicit conversion from ``X`` to ``Y`` or from ``Y`` -to ``X`` (but not both), typically implemented as a conversion -constructor. Finally, if the iterator is to model Forward Traversal -Iterator or a more-refined iterator concept, a default constructor is -required. - - - -Iterator Core Access -==================== - -``iterator_facade`` and the operator implementations need to be able -to access the core member functions in the derived class. Making the -core member functions public would expose an implementation detail to -the user. This proposal frees the public interface of the derived -iterator type from any implementation detail. - -Preventing direct access to the core member functions has two -advantages. First, there is no possibility for the user to accidently -use a member function of the iterator when a member of the value_type -was intended. This has been an issue with smart pointer -implementations in the past. The second and main advantage is that -library implementers can freely exchange a hand-rolled iterator -implementation for one based on ``iterator_facade`` without fear of -breaking code that was accessing the public core member functions -directly. - -In a naive implementation, keeping the derived class' core member -functions private would require it to grant friendship to -``iterator_facade`` and each of the seven operators. In order to -reduce the burden of limiting access, this proposal provides -``iterator_core_access``, a class that acts as a gateway to the core -member functions in the derived iterator class. The author of the -derived class only needs to grant friendship to -``iterator_core_access`` to make his core member functions available -to the library. - -.. This is no long uptodate -thw -.. Yes it is; I made sure of it! -DWA - -``iterator_core_access`` will be typically implemented as an empty -class containing only private static member functions which invoke the -iterator core member functions. There is, however, no need to -standardize the gateway protocol. Note that even if -``iterator_core_access`` used public member functions it would not -open a safety loophole, as every core member function preserves the -invariants of the iterator. - -``operator[]`` -================ - -The indexing operator for a generalized iterator presents special -challenges. A random access iterator's ``operator[]`` is only -required to return something convertible to its ``value_type``. -Requiring that it return an lvalue would rule out currently-legal -random-access iterators which hold the referenced value in a data -member (e.g. `counting_iterator`_), because ``*(p+n)`` is a reference -into the temporary iterator ``p+n``, which is destroyed when -``operator[]`` returns. - -Writable iterators built with ``iterator_facade`` implement the -semantics required by the preferred resolution to `issue 299`_ and -adopted by proposal `n1477`_: the result of ``p[n]`` is a proxy object -containing a copy of ``p+n``, and ``p[n] = x`` is equivalent to ``*(p -+ n) = x``. This approach will work properly for any random-access -iterator regardless of the other details of its implementation. A -user who knows more about the implementation of her iterator is free -to implement an ``operator[]`` which returns an lvalue in the derived -iterator class; it will hide the one supplied by ``iterator_facade`` -from clients of her iterator. - -.. _issue 299: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#299 - -.. _`operator arrow`: - -``operator->`` -============== - -The ``reference`` type of a readable iterator (and today's input -iterator) need not in fact be a reference, so long as it is -convertible to the iterator's ``value_type``. When the ``value_type`` -is a class, however, it must still be possible to access members -through ``operator->``. Therefore, an iterator whose ``reference`` -type is not in fact a reference must return a proxy containing a copy -of the referenced value from its ``operator->``. - -This proposal does not explicitly specify the return type for -``operator->`` and ``operator[]``. Instead it requires each -``iterator_facade`` instantiation to meet the requirements of its -``iterator_category``. +.. include:: iterator_facade_body.rst Iterator Adaptor ================ -The ``iterator_adaptor`` class template adapts some ``Base`` [#base]_ -type to create a new iterator. Instantiations of ``iterator_adaptor`` -are derived from a corresponding instantiation of ``iterator_facade`` -and implement the core behaviors in terms of the ``Base`` type. In -essence, ``iterator_adaptor`` merely forwards all operations to an -instance of the ``Base`` type, which it stores as a member. - -.. [#base] The term "Base" here does not refer to a base class and is - not meant to imply the use of derivation. We have followed the lead - of the standard library, which provides a base() function to access - the underlying iterator object of a ``reverse_iterator`` adaptor. - -The user of ``iterator_adaptor`` creates a class derived from an -instantiation of ``iterator_adaptor`` and then selectively -redefines some of the core member functions described in the table -above. The ``Base`` type need not meet the full requirements for an -iterator. It need only support the operations used by the core -interface functions of ``iterator_adaptor`` that have not been -redefined in the user's derived class. - -Several of the template parameters of ``iterator_adaptor`` default to -``use_default``. This allows the user to make use of a default -parameter even when the user wants to specify a parameter later in the -parameter list. Also, the defaults for the corresponding associated -types are fairly complicated, so metaprogramming is required to -compute them, and ``use_default`` can help to simplify the -implementation. Finally, ``use_default`` is not left unspecified -because specification helps to highlight that the ``Reference`` -template parameter may not always be identical to the iterator's -``reference`` type, and will keep users making mistakes based on that -assumption. +.. include:: iterator_adaptor_body.rst Specialized Adaptors ==================== @@ -488,296 +287,12 @@ Header ```` synopsis [lib.iterator.helper.synopsis] Iterator facade [lib.iterator.facade] ===================================== -``iterator_facade`` is a base class template which implements the -interface of standard iterators in terms of a few core functions -and associated types, to be supplied by a derived iterator class. +..include:: iterator_facade_abstract.rst Class template ``iterator_facade`` ---------------------------------- -.. parsed-literal:: - - template < - class Derived - , class Value - , class AccessCategory - , class TraversalCategory - , class Reference = /* see below__ \*/ - , class Difference = ptrdiff_t - > - class iterator_facade { - public: - typedef remove_cv::type value_type; - typedef Reference reference; - typedef /* see `description of operator->`__ \*/ pointer; - typedef Difference difference_type; - typedef iterator_tag iterator_category; - - reference operator\*() const; - /* see below__ \*/ operator->() const; - /* see below__ \*/ operator[](difference_type n) const; - Derived& operator++(); - Derived operator++(int); - Derived& operator--(); - Derived operator--(int); - Derived& operator+=(difference_type n); - Derived& operator-=(difference_type n); - Derived operator-(difference_type n) const; - }; - - // Comparison operators - template - typename enable_if_interoperable::type // exposition - operator ==(iterator_facade const& lhs, - iterator_facade const& rhs); - - template - typename enable_if_interoperable::type - operator !=(iterator_facade const& lhs, - iterator_facade const& rhs); - - template - typename enable_if_interoperable::type - operator <(iterator_facade const& lhs, - iterator_facade const& rhs); - - template - typename enable_if_interoperable::type - operator <=(iterator_facade const& lhs, - iterator_facade const& rhs); - - template - typename enable_if_interoperable::type - operator >(iterator_facade const& lhs, - iterator_facade const& rhs); - - template - typename enable_if_interoperable::type - operator >=(iterator_facade const& lhs, - iterator_facade const& rhs); - - template - typename enable_if_interoperable::type - operator >=(iterator_facade const& lhs, - iterator_facade const& rhs); - - // Iterator difference - template - typename enable_if_interoperable::type - operator -(iterator_facade const& lhs, - iterator_facade const& rhs); - - // Iterator addition - template - Derived operator+ (iterator_facade const&, - typename Derived::difference_type n) - - -__ `iterator facade requirements`_ - -__ `operator arrow`_ - -__ `operator arrow`_ - -__ brackets_ - -[*Note:* The ``enable_if_interoperable`` template used above is for exposition -purposes. The member operators should be only be in an overload set -provided the derived types ``Dr1`` and ``Dr2`` are interoperable, by -which we mean they are convertible to each other. The -``enable_if_interoperable`` approach uses SFINAE to take the operators -out of the overload set when the types are not interoperable.] - - -.. we need a new label here because the presence of markup in the - title prevents an automatic link from being generated - -.. _iterator facade requirements: - -``iterator_facade`` requirements --------------------------------- - -The ``Derived`` template parameter must be a class derived from -``iterator_facade``. - -The default for the ``Reference`` parameter is ``Value&`` if the -access category for ``iterator_facade`` is implicitly convertible to -``writable_iterator_tag``, and ``const Value&`` otherwise. - -The following table describes the other requirements on the -``Derived`` parameter. Depending on the resulting iterator's -``iterator_category``, a subset of the expressions listed in the table -are required to be valid. The operations in the first column must be -accessible to member functions of class ``iterator_core_access``. - -In the table below, ``X`` is the derived iterator type, ``a`` is an -object of type ``X``, ``b`` and ``c`` are objects of type ``const X``, -``n`` is an object of ``X::difference_type``, ``y`` is a constant -object of a single pass iterator type interoperable with X, and ``z`` -is a constant object of a random access traversal iterator type -interoperable with ``X``. - -+--------------------+-------------------+-------------------------------------+---------------------------+ -|Expression |Return Type |Assertion/Note |Required to implement | -| | | |Iterator Concept(s) | -+====================+===================+=====================================+===========================+ -|``c.dereference()`` |``X::reference`` | |Readable Iterator, Writable| -| | | |Iterator | -+--------------------+-------------------+-------------------------------------+---------------------------+ -|``c.equal(b)`` |convertible to bool|true iff ``b`` and ``c`` are |Single Pass Iterator | -| | |equivalent. | | -+--------------------+-------------------+-------------------------------------+---------------------------+ -|``c.equal(y)`` |convertible to bool|true iff ``c`` and ``y`` refer to the|Single Pass Iterator | -| | |same position. Implements ``c == y``| | -| | |and ``c != y``. | | -+--------------------+-------------------+-------------------------------------+---------------------------+ -|``a.advance(n)`` |unused | |Random Access Traversal | -| | | |Iterator | -+--------------------+-------------------+-------------------------------------+---------------------------+ -|``a.increment()`` |unused | |Incrementable Iterator | -+--------------------+-------------------+-------------------------------------+---------------------------+ -|``a.decrement()`` |unused | |Bidirectional Traversal | -| | | |Iterator | -+--------------------+-------------------+-------------------------------------+---------------------------+ -|``c.distance_to(b)``|convertible to |equivalent to ``distance(c, b)`` |Random Access Traversal | -| |X::difference_type | |Iterator | -+--------------------+-------------------+-------------------------------------+---------------------------+ -|``c.distance_to(z)``|convertible to |equivalent to ``distance(c, z)``. |Random Access Traversal | -| |X::difference_type |Implements ``c - z``, ``c < z``, ``c |Iterator | -| | |<= z``, ``c > z``, and ``c >= c``. | | -+--------------------+-------------------+-------------------------------------+---------------------------+ - -.. We should explain more about how the - functions in the interface of iterator_facade - are there conditionally. -JGS - - -``iterator_facade`` operations ------------------------------- - -The operations in this section are described in terms of operations on -the core interface of ``Derived`` which may be inaccessible -(i.e. private). The implementation should access these operations -through member functions of class ``iterator_core_access``. - -``reference operator*() const;`` - -:Returns: ``static_cast(this)->dereference()`` - -``operator->() const;`` (see below__) - -__ `operator arrow`_ - -:Returns: If ``X::reference`` is a reference type, returns an object - of type ``X::pointer`` equal to:: - - &static_cast(this)->dereference() - - Otherwise returns an object of unspecified type such that, given an - object ``a`` of type ``X``, ``a->m`` is equivalent to ``(w = *a, - w.m)`` for some temporary object ``w`` of type ``X::value_type``. - - The type ``X::pointer`` is ``Value*`` if the access category for - ``X`` is implicitly convertible to ``writable_iterator_tag``, and - ``Value const*`` otherwise. - - -.. _brackets: - -*unspecified* ``operator[](difference_type n) const;`` - -:Returns: an object convertible to ``X::reference`` and holding a copy - *p* of ``a+n`` such that, for a constant object ``v`` of type - ``X::value_type``, ``X::reference(a[n] = v)`` is equivalent - to ``p = v``. - - - -``Derived& operator++();`` - -:Effects: - - :: - - static_cast(this)->increment(); - return *this; - -.. I realize that the committee is moving away from specifying things - like this in terms of code, but I worried about the imprecision of - saying that a core interface function is invoked without describing - the downcast. An alternative to what I did would be to mention it - above where we talk about accessibility. - - -``Derived operator++(int);`` - -:Effects: - - :: - - Derived tmp(static_cast(this)); - ++*this; - return tmp; - - -``Derived& operator--();`` - -:Effects: - - :: - - static_cast(this)->decrement(); - return *this; - - -``Derived operator--(int);`` - -:Effects: - - :: - - Derived tmp(static_cast(this)); - --*this; - return tmp; - - -``Derived& operator+=(difference_type n);`` - -:Effects: - - :: - - static_cast(this)->advance(n); - return *this; - - -``Derived& operator-=(difference_type n);`` - -:Effects: - - :: - - static_cast(this)->advance(-n); - return *this; - - -``Derived operator-(difference_type n) const;`` - -:Effects: - - Derived tmp(static_cast(this)); - return tmp -= n; - -:Returns: ``static_cast(this)->advance(-n);`` - +..include:: iterator_facade_ref.rst Iterator adaptor [lib.iterator.adaptor] ======================================= @@ -1618,9 +1133,6 @@ and Incrementable Iterator concepts. -.. [Cop95] [Coplien, 1995] Coplien, J., Curiously Recurring Template - Patterns, C++ Report, February 1995, pp. 24-27. - .. LocalWords: Abrahams Siek Witt istream ostream iter MTL strided interoperate LocalWords: CRTP metafunctions inlining lvalue JGS incrementable BGL LEDA cv diff --git a/doc/index.html b/doc/index.html index 7d3058b..b8344c8 100755 --- a/doc/index.html +++ b/doc/index.html @@ -3,13 +3,13 @@ - -The Boost Iterator Library - + +The Boost Iterator Library Boost + +
+

iterator_facade operations

+

The operations in this section are described in terms of operations on +the core interface of Derived which may be inaccessible +(i.e. private). The implementation should access these operations +through member functions of class iterator_core_access.

+

reference operator*() const;

+ +++ + + + +
Returns:static_cast<Derived const*>(this)->dereference()
+

operator->() const; (see below)

+ +++ + + + +
Returns:

If X::reference is a reference type, returns an object +of type X::pointer equal to:

+
+&static_cast<Derived const*>(this)->dereference()
+
+

Otherwise returns an object of unspecified type such that, given an +object a of type X, a->m is equivalent to (w = *a, +w.m) for some temporary object w of type X::value_type.

+

The type X::pointer is Value* if the access category for +X is implicitly convertible to writable_iterator_tag, and +Value const* otherwise.

+
+

unspecified operator[](difference_type n) const;

+ +++ + + + +
Returns:an object convertible to X::reference and holding a copy +p of a+n such that, for a constant object v of type +X::value_type, X::reference(a[n] = v) is equivalent +to p = v.
+

Derived& operator++();

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->increment();
+return *this;
+
+
+ +

Derived operator++(int);

+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+++*this;
+return tmp;
+
+
+

Derived& operator--();

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->decrement();
+return *this;
+
+
+

Derived operator--(int);

+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+--*this;
+return tmp;
+
+
+

Derived& operator+=(difference_type n);

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->advance(n);
+return *this;
+
+
+

Derived& operator-=(difference_type n);

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->advance(-n);
+return *this;
+
+
+

Derived operator-(difference_type n) const;

+ +++ + + + + + +
Effects:Derived tmp(static_cast<Derived const*>(this)); +return tmp -= n;
Returns:static_cast<Derived const*>(this)->advance(-n);
+
-

Iterator adaptor [lib.iterator.adaptor]

+

Iterator adaptor [lib.iterator.adaptor]

The iterator_adaptor is a base class template derived from an instantiation of iterator_facade. The core interface functions expected by iterator_facade are implemented in terms of the @@ -580,7 +914,7 @@ depends on the operations supported by the iterator_facade are redefined in the Derived class.

-

Class template iterator_adaptor

+

Class template iterator_adaptor

 template <
     class Derived
@@ -625,7 +959,7 @@ class iterator_adaptor
 
-

iterator_adaptor requirements

+

iterator_adaptor requirements

The Derived template parameter must be a derived class of iterator_adaptor. The Base type must implement the expressions involving m_iterator in the specifications of those private member @@ -679,7 +1013,7 @@ else iterator_category = Category; -->

-

iterator_adaptor public operations

+

iterator_adaptor public operations

iterator_adaptor();

@@ -713,7 +1047,7 @@ else
-

iterator_adaptor protected member functions

+

iterator_adaptor protected member functions

Base const& base_reference() const;

@@ -734,7 +1068,7 @@ else
-

iterator_adaptor private member functions

+

iterator_adaptor private member functions

typename iterator_adaptor::reference dereference() const;

@@ -803,7 +1137,7 @@ typename iterator_adaptor::difference_type distance_to(
-

Specialized adaptors [lib.iterator.special.adaptors]

+

Specialized adaptors [lib.iterator.special.adaptors]

[Note: The enable_if_convertible<X,Y>::type expression used in @@ -814,7 +1148,7 @@ type Y. The -

Indirect iterator

+

Indirect iterator

The indirect iterator adapts an iterator by applying an extra dereference inside of operator*(). For example, this iterator adaptor makes it possible to view a container of pointers @@ -823,7 +1157,7 @@ adaptor makes it possible to view a container of pointers

-

Class template indirect_iterator

+

Class template indirect_iterator

 template <
     class Iterator
@@ -858,7 +1192,7 @@ private: // as-if specification
 
-

indirect_iterator requirements

+

indirect_iterator requirements

The value_type of the Iterator template parameter should itself be dereferenceable. The return type of the operator* for the value_type must be the same type as the Reference template @@ -883,7 +1217,7 @@ iterator will model the most refined standard access concept that is modeled by the value type of Iterator.

@@ -931,13 +1265,13 @@ indirect_iterator(
-

Reverse iterator

+

Reverse iterator

The reverse iterator adaptor flips the direction of a base iterator's motion. Invoking operator++() moves the base iterator backward and invoking operator--() moves the base iterator forward.

-

Class template reverse_iterator

+

Class template reverse_iterator

 template <class Iterator>
 class reverse_iterator :
@@ -976,7 +1310,7 @@ private: // as-if specification
 
-

reverse_iterator requirements

+

reverse_iterator requirements

The base Iterator must be a model of Bidirectional Traversal Iterator. The resulting reverse_iterator will be a model of the most refined standard traversal and access concepts that are modeled @@ -1023,14 +1357,14 @@ reverse_iterator(

-

Transform iterator

+

Transform iterator

The transform iterator adapts an iterator by applying some function object to the result of dereferencing the iterator. In other words, the operator* of the transform iterator first dereferences the base iterator, passes the result of this to the function object, and then returns the result.

-

Class template transform_iterator

+

Class template transform_iterator

 template <class AdaptableUnaryFunction,
           class Iterator, 
@@ -1058,7 +1392,7 @@ private:
 
-

transform_iterator requirements

+

transform_iterator requirements

The type AdaptableUnaryFunction must be Assignable, Copy Constructible, and the expression f(x) must be valid where f is an object of type AdaptableUnaryFunction, x is an object of @@ -1083,7 +1417,7 @@ concept that is modeled by Iterator result_type.

@@ -1132,7 +1466,7 @@ transform_iterator(
-

transform_iterator private operations

+

transform_iterator private operations

typename transform_iterator::value_type dereference() const;

@@ -1145,7 +1479,7 @@ transform_iterator(
-

Filter iterator

+

Filter iterator

The filter iterator adaptor creates a view of an iterator range in which some elements of the range are skipped over. A predicate function object controls which elements are skipped. When the @@ -1157,7 +1491,7 @@ of the underlying range. Therefore the constructor of the filter iterator takes two iterator parameters: the position for the filtered iterator and the end of the range.

-

Class template filter_iterator

+

Class template filter_iterator

 template <class Predicate, class Iterator>
 class filter_iterator
@@ -1199,7 +1533,7 @@ class filter_iterator
 
-

filter_iterator requirements

+

filter_iterator requirements

The base Iterator parameter must be a model of Readable Iterator and Single Pass Iterator. The resulting filter_iterator will be a model of Forward Traversal Iterator if Iterator is, otherwise the @@ -1215,7 +1549,7 @@ expression p(x) must be valid p(x) must be convertible to bool.

@@ -1288,14 +1622,14 @@ filter_iterator(
-
-

Counting iterator

+
+

Counting iterator

The counting iterator adaptor implements dereference by returning a reference to the base object. The other operations are implemented by the base m_iterator, as per the inheritance from iterator_adaptor.

-

Class template counting_iterator

+

Class template counting_iterator

 template <class Incrementable, class Category = use_default, class Difference = use_default>
 class counting_iterator
@@ -1328,7 +1662,7 @@ the cases when the Incrementable
 
-

counting_iterator requirements

+

counting_iterator requirements

The Incrementable type must be Default Constructible, Copy Constructible, and Assignable. The default distance is an implementation defined signed integegral type.

@@ -1356,7 +1690,7 @@ i < j
-

counting_iterator operations

+

counting_iterator operations

counting_iterator();

@@ -1387,7 +1721,7 @@ object copy constructed from x
-

Function output iterator

+

Function output iterator

The function output iterator adaptor makes it easier to create custom output iterators. The adaptor takes a unary function and creates a model of Output Iterator. Each item assigned to the output iterator is @@ -1396,7 +1730,7 @@ iterator is that creating a conforming output iterator is non-trivial, particularly because the proper implementation usually requires a proxy object.

-

Class template function_output_iterator

+

Class template function_output_iterator

 template <class UnaryFunction>
 class function_output_iterator {
@@ -1424,7 +1758,7 @@ public:
 
-

function_output_iterator requirements

+

function_output_iterator requirements

The UnaryFunction must be Assignable, Copy Constructible, and the expression f(x) must be valid, where f is an object of type UnaryFunction and x is an object of a type accepted by f. @@ -1432,7 +1766,7 @@ The resulting function_output_iterator

-

function_output_iterator operations

+

function_output_iterator operations

explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());

@@ -1473,7 +1807,7 @@ a copy of the unary function f
-

function_output_iterator::output_proxy operations

+

function_output_iterator::output_proxy operations

output_proxy(UnaryFunction& f);

diff --git a/doc/facade-and-adaptor.rst b/doc/facade-and-adaptor.rst index 886124c..3c6a788 100644 --- a/doc/facade-and-adaptor.rst +++ b/doc/facade-and-adaptor.rst @@ -287,208 +287,22 @@ Header ```` synopsis [lib.iterator.helper.synopsis] Iterator facade [lib.iterator.facade] ===================================== -..include:: iterator_facade_abstract.rst +.. include:: iterator_facade_abstract.rst Class template ``iterator_facade`` ---------------------------------- -..include:: iterator_facade_ref.rst +.. include:: iterator_facade_ref.rst Iterator adaptor [lib.iterator.adaptor] ======================================= -The ``iterator_adaptor`` is a base class template derived from an -instantiation of ``iterator_facade``. The core interface functions -expected by ``iterator_facade`` are implemented in terms of the -``iterator_adaptor``\ 's ``Base`` template parameter. A class derived -from ``iterator_adaptor`` typically redefines some of the core -interface functions to adapt the behavior of the ``Base`` type. -Whether the derived class models any of the standard iterator concepts -depends on the operations supported by the ``Base`` type and which -core interface functions of ``iterator_facade`` are redefined in the -``Derived`` class. - +.. include:: iterator_adaptor_abstract.rst Class template ``iterator_adaptor`` ----------------------------------- -.. parsed-literal:: - - template < - class Derived - , class Base - , class Value = use_default - , class Category = use_default - , class Reference = use_default - , class Difference = use_default - > - class iterator_adaptor - : public iterator_facade - { - friend class iterator_core_access; - public: - iterator_adaptor(); - explicit iterator_adaptor(Base iter); - Base base() const; - protected: - Base const& base_reference() const; - Base& base_reference(); - private: // Core iterator interface for iterator_facade. - typename iterator_adaptor::reference dereference() const; - - template < - class OtherDerived, class OtherIterator, class V, class C, class R, class D - > - bool equal(iterator_adaptor const& x) const; - - void advance(typename iterator_adaptor::difference_type n); - void increment(); - void decrement(); - - template < - class OtherDerived, class OtherIterator, class V, class C, class R, class D - > - typename iterator_adaptor::difference_type distance_to( - iterator_adaptor const& y) const; - - private: - Base m_iterator; - }; - -__ : - -``iterator_adaptor`` requirements ---------------------------------- - -The ``Derived`` template parameter must be a derived class of -``iterator_adaptor``. The ``Base`` type must implement the expressions -involving ``m_iterator`` in the specifications of those private member -functions of ``iterator_adaptor`` that are not redefined by the -``Derived`` class and that are needed to model the concept -corresponding to the chosen ``Category`` according to the requirements -of ``iterator_facade``. The rest of the template parameters specify -the types for the member typedefs in ``iterator_facade``. The -following pseudo-code specifies the traits types for -``iterator_adaptor``. - -:: - - if (Value == use_default) - value_type = iterator_traits::value_type; - else - value_type = remove_cv::type; - - if (Reference == use_default) { - if (Value == use_default) - reference = iterator_traits::reference; - else - reference = Value&; - } else - reference = Reference; - - if (Distance == use_default) - difference_type = iterator_traits::difference_type; - else - difference_type = Distance; - - if (Category == use_default) - iterator_category = iterator_tag< - access_category< - iterator< iterator_traits::iterator_category, - Value, - Distance, - Value*, - Reference > >, - traversal_category< - iterator< iterator_traits::iterator_category, - Value, - Distance, - Value*, - Reference > > - else - iterator_category = Category; - - -.. Replaced with new semantics --thw - if (Category == use_default) - iterator_category = iterator_traits::iterator_category; - else - iterator_category = Category; - - - -``iterator_adaptor`` public operations --------------------------------------- - -``iterator_adaptor();`` - -:Requires: The ``Base`` type must be Default Constructible. -:Returns: An instance of ``iterator_adaptor`` with - ``m_iterator`` default constructed. - - -``explicit iterator_adaptor(Base iter);`` - -:Returns: An instance of ``iterator_adaptor`` with - ``m_iterator`` copy constructed from ``iter``. - -``Base base() const;`` - -:Returns: ``m_iterator`` - - -``iterator_adaptor`` protected member functions ------------------------------------------------ - -``Base const& base_reference() const;`` - -:Returns: A const reference to ``m_iterator``. - - -``Base& base_reference();`` - -:Returns: A non-const reference to ``m_iterator``. - - -``iterator_adaptor`` private member functions ---------------------------------------------- - -``typename iterator_adaptor::reference dereference() const;`` - -:Returns: ``*m_iterator`` - -:: - - template < - class OtherDerived, class OtherIterator, class V, class C, class R, class D - > - bool equal(iterator_adaptor const& x) const; - -:Returns: ``m_iterator == x.base()`` - - -``void advance(typename iterator_adaptor::difference_type n);`` - -:Effects: ``m_iterator += n;`` - -``void increment();`` - -:Effects: ``++m_iterator;`` - -``void decrement();`` - -:Effects: ``--m_iterator;`` - -:: - - template < - class OtherDerived, class OtherIterator, class V, class C, class R, class D - > - typename iterator_adaptor::difference_type distance_to( - iterator_adaptor const& y) const; - -:Returns: ``y.base() - m_iterator`` - +.. include:: iterator_adaptor_ref.rst Specialized adaptors [lib.iterator.special.adaptors] diff --git a/doc/index.html b/doc/index.html index b8344c8..6940f28 100755 --- a/doc/index.html +++ b/doc/index.html @@ -3,7 +3,7 @@ - + The Boost Iterator Library Boost diff --git a/doc/iterator_adaptor.rst b/doc/iterator_adaptor.rst index 0c7dd68..d46f4fd 100644 --- a/doc/iterator_adaptor.rst +++ b/doc/iterator_adaptor.rst @@ -14,5 +14,19 @@ .. _`Open Systems Lab`: http://www.osl.iu.edu .. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de +:abstract: + +.. include:: iterator_adaptor_abstract.rst + +.. contents:: Table of Contents + +Introduction +============ + .. include:: iterator_adaptor_body.rst + +Reference +========= + +.. include:: iterator_adaptor_ref.rst diff --git a/doc/iterator_adaptor_abstract.rst b/doc/iterator_adaptor_abstract.rst new file mode 100644 index 0000000..ee75455 --- /dev/null +++ b/doc/iterator_adaptor_abstract.rst @@ -0,0 +1,10 @@ +The ``iterator_adaptor`` is a base class template derived from an +instantiation of ``iterator_facade``. The core interface functions +expected by ``iterator_facade`` are implemented in terms of the +``iterator_adaptor``\ 's ``Base`` template parameter. A class derived +from ``iterator_adaptor`` typically redefines some of the core +interface functions to adapt the behavior of the ``Base`` type. +Whether the derived class models any of the standard iterator concepts +depends on the operations supported by the ``Base`` type and which +core interface functions of ``iterator_facade`` are redefined in the +``Derived`` class. diff --git a/doc/iterator_adaptor_ref.rst b/doc/iterator_adaptor_ref.rst new file mode 100644 index 0000000..62c1d78 --- /dev/null +++ b/doc/iterator_adaptor_ref.rst @@ -0,0 +1,176 @@ +.. parsed-literal:: + + template < + class Derived + , class Base + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class iterator_adaptor + : public iterator_facade + { + friend class iterator_core_access; + public: + iterator_adaptor(); + explicit iterator_adaptor(Base iter); + Base base() const; + protected: + Base const& base_reference() const; + Base& base_reference(); + private: // Core iterator interface for iterator_facade. + typename iterator_adaptor::reference dereference() const; + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + bool equal(iterator_adaptor const& x) const; + + void advance(typename iterator_adaptor::difference_type n); + void increment(); + void decrement(); + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + typename iterator_adaptor::difference_type distance_to( + iterator_adaptor const& y) const; + + private: + Base m_iterator; + }; + +__ : + +``iterator_adaptor`` requirements +--------------------------------- + +The ``Derived`` template parameter must be a derived class of +``iterator_adaptor``. The ``Base`` type must implement the expressions +involving ``m_iterator`` in the specifications of those private member +functions of ``iterator_adaptor`` that are not redefined by the +``Derived`` class and that are needed to model the concept +corresponding to the chosen ``Category`` according to the requirements +of ``iterator_facade``. The rest of the template parameters specify +the types for the member typedefs in ``iterator_facade``. The +following pseudo-code specifies the traits types for +``iterator_adaptor``. + +:: + + if (Value == use_default) + value_type = iterator_traits::value_type; + else + value_type = remove_cv::type; + + if (Reference == use_default) { + if (Value == use_default) + reference = iterator_traits::reference; + else + reference = Value&; + } else + reference = Reference; + + if (Distance == use_default) + difference_type = iterator_traits::difference_type; + else + difference_type = Distance; + + if (Category == use_default) + iterator_category = iterator_tag< + access_category< + iterator< iterator_traits::iterator_category, + Value, + Distance, + Value*, + Reference > >, + traversal_category< + iterator< iterator_traits::iterator_category, + Value, + Distance, + Value*, + Reference > > + else + iterator_category = Category; + + +.. Replaced with new semantics --thw + if (Category == use_default) + iterator_category = iterator_traits::iterator_category; + else + iterator_category = Category; + + + +``iterator_adaptor`` public operations +-------------------------------------- + +``iterator_adaptor();`` + +:Requires: The ``Base`` type must be Default Constructible. +:Returns: An instance of ``iterator_adaptor`` with + ``m_iterator`` default constructed. + + +``explicit iterator_adaptor(Base iter);`` + +:Returns: An instance of ``iterator_adaptor`` with + ``m_iterator`` copy constructed from ``iter``. + +``Base base() const;`` + +:Returns: ``m_iterator`` + + +``iterator_adaptor`` protected member functions +----------------------------------------------- + +``Base const& base_reference() const;`` + +:Returns: A const reference to ``m_iterator``. + + +``Base& base_reference();`` + +:Returns: A non-const reference to ``m_iterator``. + + +``iterator_adaptor`` private member functions +--------------------------------------------- + +``typename iterator_adaptor::reference dereference() const;`` + +:Returns: ``*m_iterator`` + +:: + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + bool equal(iterator_adaptor const& x) const; + +:Returns: ``m_iterator == x.base()`` + + +``void advance(typename iterator_adaptor::difference_type n);`` + +:Effects: ``m_iterator += n;`` + +``void increment();`` + +:Effects: ``++m_iterator;`` + +``void decrement();`` + +:Effects: ``--m_iterator;`` + +:: + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + typename iterator_adaptor::difference_type distance_to( + iterator_adaptor const& y) const; + +:Returns: ``y.base() - m_iterator`` diff --git a/doc/iterator_facade_abstract.rst b/doc/iterator_facade_abstract.rst index 70c64cb..f024b9b 100644 --- a/doc/iterator_facade_abstract.rst +++ b/doc/iterator_facade_abstract.rst @@ -1,4 +1,4 @@ -``iterator_facade`` is a base class template which implements the +``iterator_facade`` is a base class template that implements the interface of standard iterators in terms of a few core functions and associated types, to be supplied by a derived iterator class. diff --git a/doc/iterator_facade_ref.rst b/doc/iterator_facade_ref.rst index 9a1a344..04d5150 100644 --- a/doc/iterator_facade_ref.rst +++ b/doc/iterator_facade_ref.rst @@ -106,7 +106,7 @@ out of the overload set when the types are not interoperable.] .. _iterator facade requirements: ``iterator_facade`` requirements -================================ +................................ The ``Derived`` template parameter must be a class derived from ``iterator_facade``. @@ -164,7 +164,7 @@ interoperable with ``X``. ``iterator_facade`` operations -============================== +.............................. The operations in this section are described in terms of operations on the core interface of ``Derived`` which may be inaccessible diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index d245d04..fd98e5f 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -3,7 +3,7 @@ - + New Iterator Concepts @@ -92,7 +92,7 @@ geared towards iterator traversal (hence the category names), while requirements that address value access sneak in at various places. The following table gives a summary of the current value access requirements in the iterator categories.

-
+
@@ -326,7 +326,7 @@ for the value type T if the fo respect the stated semantics. U is the type of any specified member of type T.

-
+
@@ -403,7 +403,7 @@ semantics.

if the following expressions are valid and respect the stated semantics.

-
+
@@ -435,7 +435,7 @@ semantics.

The Readable Lvalue Iterator concept adds the requirement that the reference type be a reference to the value type of the iterator.

-
+
@@ -472,7 +472,7 @@ cv-qualificationreference type be a non-const reference to the value type of the iterator.

-
+
@@ -508,7 +508,7 @@ type X,
-
+
@@ -545,7 +545,7 @@ semantics.

concept if the following expressions are valid and respect the stated semantics.

-
+
@@ -590,7 +590,7 @@ its domain concept if the following expressions are valid and respect the stated semantics.

-
+
@@ -636,7 +636,7 @@ the distance between iterators Iterator concept if the following expressions are valid and respect the stated semantics.

-
+
@@ -680,7 +680,7 @@ the stated semantics. In the table below, iterator_traits<X>::difference_type and n represents a constant object of type Distance.

-
+
From 76af84c0e747826350ffbf6ce4109074dfeca2c1 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Tue, 5 Aug 2003 19:42:37 +0000 Subject: [PATCH 197/265] factoring the specialized iterator adaptors [SVN r19467] --- doc/counting_iterator.rst | 23 + doc/counting_iterator_abstract.rst | 5 + doc/counting_iterator_ref.rst | 85 ++++ doc/facade-and-adaptor.rst | 582 +--------------------- doc/filter_iterator.rst | 23 + doc/filter_iterator_abstract.rst | 10 + doc/filter_iterator_ref.rst | 108 ++++ doc/function_output_iterator.rst | 23 + doc/function_output_iterator_abstract.rst | 8 + doc/function_output_iterator_ref.rst | 77 +++ doc/indirect_iterator.rst | 23 + doc/indirect_iterator_abstract.rst | 8 + doc/indirect_iterator_ref.rst | 96 ++++ doc/permutation_iterator.rst | 31 ++ doc/permutation_iterator_abstract.rst | 4 + doc/permutation_iterator_body.rst | 15 + doc/permutation_iterator_ref.rst | 54 ++ doc/reverse_iterator.rst | 23 + doc/reverse_iterator_abstract.rst | 6 + doc/reverse_iterator_ref.rst | 69 +++ doc/transform_iterator.rst | 23 + doc/transform_iterator_abstract.rst | 5 + doc/transform_iterator_ref.rst | 95 ++++ 23 files changed, 826 insertions(+), 570 deletions(-) create mode 100644 doc/counting_iterator.rst create mode 100644 doc/counting_iterator_abstract.rst create mode 100644 doc/counting_iterator_ref.rst create mode 100644 doc/filter_iterator.rst create mode 100644 doc/filter_iterator_abstract.rst create mode 100644 doc/filter_iterator_ref.rst create mode 100644 doc/function_output_iterator.rst create mode 100644 doc/function_output_iterator_abstract.rst create mode 100644 doc/function_output_iterator_ref.rst create mode 100644 doc/indirect_iterator.rst create mode 100644 doc/indirect_iterator_abstract.rst create mode 100644 doc/indirect_iterator_ref.rst create mode 100644 doc/permutation_iterator.rst create mode 100644 doc/permutation_iterator_abstract.rst create mode 100644 doc/permutation_iterator_body.rst create mode 100644 doc/permutation_iterator_ref.rst create mode 100644 doc/reverse_iterator.rst create mode 100644 doc/reverse_iterator_abstract.rst create mode 100644 doc/reverse_iterator_ref.rst create mode 100644 doc/transform_iterator.rst create mode 100644 doc/transform_iterator_abstract.rst create mode 100644 doc/transform_iterator_ref.rst diff --git a/doc/counting_iterator.rst b/doc/counting_iterator.rst new file mode 100644 index 0000000..d6aedf7 --- /dev/null +++ b/doc/counting_iterator.rst @@ -0,0 +1,23 @@ ++++++++++++++++++++ + Counting Iterator ++++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, University of Hanover `Institute for Transport + Railway Operation and Construction`_ +:date: $Date$ +:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:abstract: + +.. include:: counting_iterator_abstract.rst + +.. contents:: Table of Contents + +.. include:: counting_iterator_ref.rst diff --git a/doc/counting_iterator_abstract.rst b/doc/counting_iterator_abstract.rst new file mode 100644 index 0000000..2ac2233 --- /dev/null +++ b/doc/counting_iterator_abstract.rst @@ -0,0 +1,5 @@ +The counting iterator adaptor implements dereference by returning a +reference to the base object. The other operations are implemented by +the base ``m_iterator``, as per the inheritance from +``iterator_adaptor``. + diff --git a/doc/counting_iterator_ref.rst b/doc/counting_iterator_ref.rst new file mode 100644 index 0000000..fc01011 --- /dev/null +++ b/doc/counting_iterator_ref.rst @@ -0,0 +1,85 @@ +:: + + template + class counting_iterator + : public iterator_adaptor< + counting_iterator + , Incrementable + , Incrementable + , /* see details for category */ + , Incrementable const& + , Incrementable const* + , /* distance = Difference or a signed integral type */> + { + friend class iterator_core_access; + public: + counting_iterator(); + counting_iterator(counting_iterator const& rhs); + counting_iterator(Incrementable x); + private: + typename counting_iterator::reference dereference() const + { + return this->base_reference(); + } + }; + + +[*Note:* implementers are encouraged to provide an implementation of + ``distance_to`` and a ``difference_type`` that avoids overflows in + the cases when the ``Incrementable`` type is a numeric type.] + +``counting_iterator`` requirements +---------------------------------- + +The ``Incrementable`` type must be Default Constructible, Copy +Constructible, and Assignable. The default distance is +an implementation defined signed integegral type. + +The resulting ``counting_iterator`` models Readable Lvalue Iterator. + +Furthermore, if you wish to create a counting iterator that is a Forward +Traversal Iterator, then the following expressions must be valid: +:: + + Incrementable i, j; + ++i // pre-increment + i == j // operator equal + +If you wish to create a counting iterator that is a +Bidirectional Traversal Iterator, then pre-decrement is also required: +:: + + --i + +If you wish to create a counting iterator that is a Random Access +Traversal Iterator, then these additional expressions are also +required: +:: + + counting_iterator::difference_type n; + i += n + n = i - j + i < j + + + + +``counting_iterator`` operations +-------------------------------- + +``counting_iterator();`` + +:Returns: A default constructed instance of ``counting_iterator``. + + +``counting_iterator(counting_iterator const& rhs);`` + +:Returns: An instance of ``counting_iterator`` that is a copy of ``rhs``. + + + +``counting_iterator(Incrementable x);`` + +:Returns: An instance of ``counting_iterator`` with its base + object copy constructed from ``x``. + diff --git a/doc/facade-and-adaptor.rst b/doc/facade-and-adaptor.rst index 3c6a788..a2d0493 100644 --- a/doc/facade-and-adaptor.rst +++ b/doc/facade-and-adaptor.rst @@ -324,626 +324,68 @@ implicitly convertible.] Indirect iterator ----------------- -The indirect iterator adapts an iterator by applying an *extra* -dereference inside of ``operator*()``. For example, this iterator -adaptor makes it possible to view a container of pointers -(e.g. ``list``) as if it were a container of the pointed-to type -(e.g. ``list``) . - -.. At some point we should add the capability to handle - iterators over smart pointers, which the impl handles. -JGS - +.. include:: indirect_iterator_abstract.rst Class template ``indirect_iterator`` .................................... -:: - - template < - class Iterator - , class Value = use_default - , class Category = use_default - , class Reference = use_default - , class Difference = use_default - > - class indirect_iterator - : public iterator_adaptor - { - friend class iterator_core_access; - public: - indirect_iterator(); - indirect_iterator(Iterator x); - template < - class Iterator2, class Value2, class Category2 - , class Reference2, class Difference2 - > - indirect_iterator( - indirect_iterator< - Iterator2, Value2, Category2, Reference2, Difference2 - > const& y - , typename enable_if_convertible::type* = 0 // exposition - ); - private: // as-if specification - typename indirect_iterator::reference dereference() const - { - return **this->base(); - } - }; - -``indirect_iterator`` requirements -.................................. - -The ``value_type`` of the ``Iterator`` template parameter should -itself be dereferenceable. The return type of the ``operator*`` for -the ``value_type`` must be the same type as the ``Reference`` template -parameter. The ``Value`` template parameter will be the ``value_type`` -for the ``indirect_iterator``, unless ``Value`` is const. If ``Value`` -is ``const X``, then ``value_type`` will be *non-* ``const X``. The -default for ``Value`` is - -:: - - iterator_traits< iterator_traits::value_type >::value_type - -If the default is used for ``Value``, then there must be a valid -specialization of ``iterator_traits`` for the value type of the base -iterator. - -The ``Reference`` parameter will be the ``reference`` type of the -``indirect_iterator``. The default is ``Value&``. - -The ``Category`` parameter is the ``iterator_category`` type for the -``indirect_iterator``. The default is -``iterator_traits::iterator_category``. - -The indirect iterator will model the most refined standard traversal -concept that is modeled by the ``Iterator`` type. The indirect -iterator will model the most refined standard access concept that is -modeled by the value type of ``Iterator``. - - -``indirect_iterator`` operations -................................ - -``indirect_iterator();`` - -:Requires: ``Iterator`` must be Default Constructible. -:Returns: An instance of ``indirect_iterator`` with - a default constructed base object. - - -``indirect_iterator(Iterator x);`` - -:Returns: An instance of ``indirect_iterator`` with - the ``iterator_adaptor`` subobject copy constructed from ``x``. - -:: - - template < - class Iterator2, class Value2, class Category2 - , class Reference2, class Difference2 - > - indirect_iterator( - indirect_iterator< - Iterator2, Value2, Category2, Reference2, Difference2 - > const& y - , typename enable_if_convertible::type* = 0 // exposition - ); - -:Requires: ``Iterator2`` is implicitly convertible to ``Iterator``. -:Returns: An instance of ``indirect_iterator`` that is a copy of ``y``. +.. include:: indirect_iterator_ref.rst Reverse iterator ---------------- -.. I think we'd better strike the old reverse_iterator text from the standard, eh? - -The reverse iterator adaptor flips the direction of a base iterator's -motion. Invoking ``operator++()`` moves the base iterator backward and -invoking ``operator--()`` moves the base iterator forward. +.. include:: reverse_iterator_abstract.rst Class template ``reverse_iterator`` ................................... -:: - - template - class reverse_iterator : - public iterator_adaptor< reverse_iterator, Iterator > - { - friend class iterator_core_access; - public: - reverse_iterator() {} - explicit reverse_iterator(Iterator x) ; - - template - reverse_iterator( - reverse_iterator const& r - , typename enable_if_convertible::type* = 0 // exposition - ); - - private: // as-if specification - typename reverse_iterator::reference dereference() const { return *prior(this->base()); } - - void increment() { --this->base_reference(); } - void decrement() { ++this->base_reference(); } - - void advance(typename reverse_iterator::difference_type n) - { - this->base_reference() += -n; - } - - template - typename reverse_iterator::difference_type - distance_to(reverse_iterator const& y) const - { - return this->base_reference() - y.base(); - } - - }; - - -``reverse_iterator`` requirements -................................. - -The base ``Iterator`` must be a model of Bidirectional Traversal -Iterator. The resulting ``reverse_iterator`` will be a model of the -most refined standard traversal and access concepts that are modeled -by ``Iterator``. - - -``reverse_iterator();`` - -:Requires: ``Iterator`` must be Default Constructible. -:Returns: An instance of ``reverse_iterator`` with a - default constructed base object. - -``explicit reverse_iterator(Iterator x);`` - -:Returns: An instance of ``reverse_iterator`` with a - base object copy constructed from ``x``. - - -:: - - template - reverse_iterator( - reverse_iterator const& r - , typename enable_if_convertible::type* = 0 // exposition - ); - -:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. -:Returns: An instance of ``reverse_iterator`` that is a copy of ``r``. +.. include:: reverse_iterator_ref.rst Transform iterator ------------------ -The transform iterator adapts an iterator by applying some function -object to the result of dereferencing the iterator. In other words, -the ``operator*`` of the transform iterator first dereferences the -base iterator, passes the result of this to the function object, and -then returns the result. - +.. include:: transform_iterator_abstract.rst Class template ``transform_iterator`` ..................................... -:: - - template - class transform_iterator - : public iterator_adaptor - { - friend class iterator_core_access; - public: - transform_iterator(); - transform_iterator(Iterator const& x, AdaptableUnaryFunction f); - - template - transform_iterator( - transform_iterator const& t - , typename enable_if_convertible::type* = 0 // exposition - ); - - AdaptableUnaryFunction functor() const; - private: - typename transform_iterator::value_type dereference() const; - AdaptableUnaryFunction m_f; - }; - - -``transform_iterator`` requirements -................................... - -The type ``AdaptableUnaryFunction`` must be Assignable, Copy -Constructible, and the expression ``f(x)`` must be valid where ``f`` -is an object of type ``AdaptableUnaryFunction``, ``x`` is an object of -type ``AdaptableUnaryFunction::argument_type``, and where the type of -``f(x)`` must be ``AdaptableUnaryFunction::result_type``. - -The type ``Iterator`` must at least model Readable Iterator. The -resulting ``transform_iterator`` models the most refined of the -following options that is also modeled by ``Iterator``. - - * Writable Lvalue Iterator if the ``result_type`` of the - ``AdaptableUnaryFunction`` is a non-const reference. - - * Readable Lvalue Iterator if the ``result_type`` is a const - reference. - - * Readable Iterator otherwise. - - -The ``transform_iterator`` models the most refined standard traversal -concept that is modeled by ``Iterator``. - -The ``value_type`` of ``transform_iterator`` is -``remove_reference::type``. The ``reference`` type is -``result_type``. - - -``transform_iterator`` public operations -........................................ - - -``transform_iterator();`` - -:Returns: An instance of ``transform_iterator`` with ``m_f`` - and ``m_iterator`` default constructed. - - -``transform_iterator(Iterator const& x, AdaptableUnaryFunction f);`` - -:Returns: An instance of ``transform_iterator`` with ``m_f`` - initialized to ``f`` and ``m_iterator`` initialized to ``x``. - - -:: - - template - transform_iterator( - transform_iterator const& t - , typename enable_if_convertible::type* = 0 // exposition - ); - -:Returns: An instance of ``transform_iterator`` that is a copy of ``t``. -:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. - -``AdaptableUnaryFunction functor() const;`` - -:Returns: ``m_f`` - -``transform_iterator`` private operations -......................................... - -``typename transform_iterator::value_type dereference() const;`` - -:Returns: ``m_f(transform_iterator::dereference());`` - +.. include:: transform_iterator_ref.rst Filter iterator --------------- -The filter iterator adaptor creates a view of an iterator range in -which some elements of the range are skipped over. A predicate -function object controls which elements are skipped. When the -predicate is applied to an element, if it returns ``true`` then the -element is retained and if it returns ``false`` then the element is -skipped over. When skipping over elements, it is necessary for the -filter adaptor to know when to stop so as to avoid going past the end -of the underlying range. Therefore the constructor of the filter -iterator takes two iterator parameters: the position for the filtered -iterator and the end of the range. - +.. include:: filter_iterator_abstract.rst Class template ``filter_iterator`` .................................. -:: - - template - class filter_iterator - : public iterator_adaptor< - filter_iterator, Iterator - , use_default - , /* see details */ - > - { - public: - filter_iterator(); - filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); - filter_iterator(Iterator x, Iterator end = Iterator()); - template - filter_iterator( - filter_iterator const& t - , typename enable_if_convertible::type* = 0 // exposition - ); - Predicate predicate() const; - Iterator end() const; - - private: // as-if specification - void increment() - { - ++(this->base_reference()); - satisfy_predicate(); - } - - void satisfy_predicate() - { - while (this->base() != this->m_end && !this->m_predicate(*this->base())) - ++(this->base_reference()); - } - - Predicate m_predicate; - Iterator m_end; - }; - - -``filter_iterator`` requirements --------------------------------- - -The base ``Iterator`` parameter must be a model of Readable Iterator -and Single Pass Iterator. The resulting ``filter_iterator`` will be a -model of Forward Traversal Iterator if ``Iterator`` is, otherwise the -``filter_iterator`` will be a model of Single Pass Iterator. The -access category of the ``filter_iterator`` will be the most refined -standard access category that is modeled by ``Iterator``. - -.. Thomas is going to try implementing filter_iterator so that - it will be bidirectional if the underlying iterator is. -JGS - - -The ``Predicate`` must be Assignable, Copy Constructible, and the -expression ``p(x)`` must be valid where ``p`` is an object of type -``Predicate``, ``x`` is an object of type -``iterator_traits::value_type``, and where the type of -``p(x)`` must be convertible to ``bool``. - - - -``filter_iterator`` operations ------------------------------- - -``filter_iterator();`` - -:Requires: ``Predicate`` and ``Iterator`` must be Default Constructible. -:Returns: a ``filter_iterator`` whose - predicate is a default constructed ``Predicate`` and - whose ``end`` is a default constructed ``Iterator``. - - -``filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());`` - -:Returns: A ``filter_iterator`` at position ``x`` that filters according - to predicate ``f`` and that will not increment past ``end``. - - -``filter_iterator(Iterator x, Iterator end = Iterator());`` - -:Requires: ``Predicate`` must be Default Constructible. -:Returns: A ``filter_iterator`` at position ``x`` that filters - according to a default constructed ``Predicate`` - and that will not increment past ``end``. - - -:: - - template - filter_iterator( - filter_iterator const& t - , typename enable_if_convertible::type* = 0 // exposition - );`` - -:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. -:Returns: A copy of iterator ``t``. - - -``Predicate predicate() const;`` - -:Returns: A copy of the predicate object used to construct ``*this``. - - -``Iterator end() const;`` - -:Returns: The object ``end`` used to construct ``*this``. +.. include:: filter_iterator_ref.rst Counting iterator ----------------- -The counting iterator adaptor implements dereference by returning a -reference to the base object. The other operations are implemented by -the base ``m_iterator``, as per the inheritance from -``iterator_adaptor``. - +.. include:: counting_iterator_abstract.rst Class template ``counting_iterator`` .................................... -:: - - template - class counting_iterator - : public iterator_adaptor< - counting_iterator - , Incrementable - , Incrementable - , /* see details for category */ - , Incrementable const& - , Incrementable const* - , /* distance = Difference or a signed integral type */> - { - friend class iterator_core_access; - public: - counting_iterator(); - counting_iterator(counting_iterator const& rhs); - counting_iterator(Incrementable x); - private: - typename counting_iterator::reference dereference() const - { - return this->base_reference(); - } - }; - - -[*Note:* implementers are encouraged to provide an implementation of - ``distance_to`` and a ``difference_type`` that avoids overflows in - the cases when the ``Incrementable`` type is a numeric type.] - -``counting_iterator`` requirements ----------------------------------- - -The ``Incrementable`` type must be Default Constructible, Copy -Constructible, and Assignable. The default distance is -an implementation defined signed integegral type. - -The resulting ``counting_iterator`` models Readable Lvalue Iterator. - -Furthermore, if you wish to create a counting iterator that is a Forward -Traversal Iterator, then the following expressions must be valid: -:: - - Incrementable i, j; - ++i // pre-increment - i == j // operator equal - -If you wish to create a counting iterator that is a -Bidirectional Traversal Iterator, then pre-decrement is also required: -:: - - --i - -If you wish to create a counting iterator that is a Random Access -Traversal Iterator, then these additional expressions are also -required: -:: - - counting_iterator::difference_type n; - i += n - n = i - j - i < j - - - - -``counting_iterator`` operations --------------------------------- - -``counting_iterator();`` - -:Returns: A default constructed instance of ``counting_iterator``. - - -``counting_iterator(counting_iterator const& rhs);`` - -:Returns: An instance of ``counting_iterator`` that is a copy of ``rhs``. - - - -``counting_iterator(Incrementable x);`` - -:Returns: An instance of ``counting_iterator`` with its base - object copy constructed from ``x``. +.. include:: counting_iterator_ref.rst Function output iterator ------------------------ -The function output iterator adaptor makes it easier to create custom -output iterators. The adaptor takes a unary function and creates a -model of Output Iterator. Each item assigned to the output iterator is -passed as an argument to the unary function. The motivation for this -iterator is that creating a conforming output iterator is non-trivial, -particularly because the proper implementation usually requires a -proxy object. - +.. include:: function_output_iterator_abstract.rst Class template ``function_output_iterator`` ........................................... -:: +.. include:: function_output_iterator_ref.rst - template - class function_output_iterator { - public: - typedef iterator_tag< - writable_iterator_tag - , incrementable_traversal_tag - > iterator_category; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - - explicit function_output_iterator(const UnaryFunction& f = UnaryFunction()); - - struct output_proxy { - output_proxy(UnaryFunction& f); - template output_proxy& operator=(const T& value); - }; - output_proxy operator*(); - function_output_iterator& operator++(); - function_output_iterator& operator++(int); - }; - - -``function_output_iterator`` requirements ------------------------------------------ - -The ``UnaryFunction`` must be Assignable, Copy Constructible, and the -expression ``f(x)`` must be valid, where ``f`` is an object of type -``UnaryFunction`` and ``x`` is an object of a type accepted by ``f``. -The resulting ``function_output_iterator`` is a model of the Writable -and Incrementable Iterator concepts. - - -``function_output_iterator`` operations ---------------------------------------- - -``explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());`` - -:Returns: An instance of ``function_output_iterator`` with - ``f`` stored as a data member. - - -``output_proxy operator*();`` - -:Returns: An instance of ``output_proxy`` constructed with - a copy of the unary function ``f``. - - -``function_output_iterator& operator++();`` - -:Returns: ``*this`` - - -``function_output_iterator& operator++(int);`` - -:Returns: ``*this`` - - -``function_output_iterator::output_proxy`` operations ------------------------------------------------------ - -``output_proxy(UnaryFunction& f);`` - -:Returns: An instance of ``output_proxy`` with ``f`` stored as - a data member. - - -``template output_proxy& operator=(const T& value);`` - -:Effects: - :: - - m_f(value); - return *this; diff --git a/doc/filter_iterator.rst b/doc/filter_iterator.rst new file mode 100644 index 0000000..06a7c5f --- /dev/null +++ b/doc/filter_iterator.rst @@ -0,0 +1,23 @@ ++++++++++++++++++ + Filter Iterator ++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, University of Hanover `Institute for Transport + Railway Operation and Construction`_ +:date: $Date$ +:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:abstract: + +.. include:: filter_iterator_abstract.rst + +.. contents:: Table of Contents + +.. include:: filter_iterator_ref.rst diff --git a/doc/filter_iterator_abstract.rst b/doc/filter_iterator_abstract.rst new file mode 100644 index 0000000..9517b23 --- /dev/null +++ b/doc/filter_iterator_abstract.rst @@ -0,0 +1,10 @@ +The filter iterator adaptor creates a view of an iterator range in +which some elements of the range are skipped over. A predicate +function object controls which elements are skipped. When the +predicate is applied to an element, if it returns ``true`` then the +element is retained and if it returns ``false`` then the element is +skipped over. When skipping over elements, it is necessary for the +filter adaptor to know when to stop so as to avoid going past the end +of the underlying range. Therefore the constructor of the filter +iterator takes two iterator parameters: the position for the filtered +iterator and the end of the range. diff --git a/doc/filter_iterator_ref.rst b/doc/filter_iterator_ref.rst new file mode 100644 index 0000000..29bc166 --- /dev/null +++ b/doc/filter_iterator_ref.rst @@ -0,0 +1,108 @@ +:: + + template + class filter_iterator + : public iterator_adaptor< + filter_iterator, Iterator + , use_default + , /* see details */ + > + { + public: + filter_iterator(); + filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); + filter_iterator(Iterator x, Iterator end = Iterator()); + template + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + ); + Predicate predicate() const; + Iterator end() const; + + private: // as-if specification + void increment() + { + ++(this->base_reference()); + satisfy_predicate(); + } + + void satisfy_predicate() + { + while (this->base() != this->m_end && !this->m_predicate(*this->base())) + ++(this->base_reference()); + } + + Predicate m_predicate; + Iterator m_end; + }; + + +``filter_iterator`` requirements +-------------------------------- + +The base ``Iterator`` parameter must be a model of Readable Iterator +and Single Pass Iterator. The resulting ``filter_iterator`` will be a +model of Forward Traversal Iterator if ``Iterator`` is, otherwise the +``filter_iterator`` will be a model of Single Pass Iterator. The +access category of the ``filter_iterator`` will be the most refined +standard access category that is modeled by ``Iterator``. + +.. Thomas is going to try implementing filter_iterator so that + it will be bidirectional if the underlying iterator is. -JGS + + +The ``Predicate`` must be Assignable, Copy Constructible, and the +expression ``p(x)`` must be valid where ``p`` is an object of type +``Predicate``, ``x`` is an object of type +``iterator_traits::value_type``, and where the type of +``p(x)`` must be convertible to ``bool``. + + + +``filter_iterator`` operations +------------------------------ + +``filter_iterator();`` + +:Requires: ``Predicate`` and ``Iterator`` must be Default Constructible. +:Returns: a ``filter_iterator`` whose + predicate is a default constructed ``Predicate`` and + whose ``end`` is a default constructed ``Iterator``. + + +``filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());`` + +:Returns: A ``filter_iterator`` at position ``x`` that filters according + to predicate ``f`` and that will not increment past ``end``. + + +``filter_iterator(Iterator x, Iterator end = Iterator());`` + +:Requires: ``Predicate`` must be Default Constructible. +:Returns: A ``filter_iterator`` at position ``x`` that filters + according to a default constructed ``Predicate`` + and that will not increment past ``end``. + + +:: + + template + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + );`` + +:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. +:Returns: A copy of iterator ``t``. + + +``Predicate predicate() const;`` + +:Returns: A copy of the predicate object used to construct ``*this``. + + +``Iterator end() const;`` + +:Returns: The object ``end`` used to construct ``*this``. + diff --git a/doc/function_output_iterator.rst b/doc/function_output_iterator.rst new file mode 100644 index 0000000..33ea80e --- /dev/null +++ b/doc/function_output_iterator.rst @@ -0,0 +1,23 @@ +++++++++++++++++++++++++++ + Function Output Iterator +++++++++++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, University of Hanover `Institute for Transport + Railway Operation and Construction`_ +:date: $Date$ +:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:abstract: + +.. include:: function_output_iterator_abstract.rst + +.. contents:: Table of Contents + +.. include:: function_output_iterator_ref.rst diff --git a/doc/function_output_iterator_abstract.rst b/doc/function_output_iterator_abstract.rst new file mode 100644 index 0000000..11fb4f1 --- /dev/null +++ b/doc/function_output_iterator_abstract.rst @@ -0,0 +1,8 @@ +The function output iterator adaptor makes it easier to create custom +output iterators. The adaptor takes a unary function and creates a +model of Output Iterator. Each item assigned to the output iterator is +passed as an argument to the unary function. The motivation for this +iterator is that creating a conforming output iterator is non-trivial, +particularly because the proper implementation usually requires a +proxy object. + diff --git a/doc/function_output_iterator_ref.rst b/doc/function_output_iterator_ref.rst new file mode 100644 index 0000000..4bb5cf1 --- /dev/null +++ b/doc/function_output_iterator_ref.rst @@ -0,0 +1,77 @@ +:: + + template + class function_output_iterator { + public: + typedef iterator_tag< + writable_iterator_tag + , incrementable_traversal_tag + > iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + explicit function_output_iterator(const UnaryFunction& f = UnaryFunction()); + + struct output_proxy { + output_proxy(UnaryFunction& f); + template output_proxy& operator=(const T& value); + }; + output_proxy operator*(); + function_output_iterator& operator++(); + function_output_iterator& operator++(int); + }; + + +``function_output_iterator`` requirements +----------------------------------------- + +The ``UnaryFunction`` must be Assignable, Copy Constructible, and the +expression ``f(x)`` must be valid, where ``f`` is an object of type +``UnaryFunction`` and ``x`` is an object of a type accepted by ``f``. +The resulting ``function_output_iterator`` is a model of the Writable +and Incrementable Iterator concepts. + + +``function_output_iterator`` operations +--------------------------------------- + +``explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());`` + +:Returns: An instance of ``function_output_iterator`` with + ``f`` stored as a data member. + + +``output_proxy operator*();`` + +:Returns: An instance of ``output_proxy`` constructed with + a copy of the unary function ``f``. + + +``function_output_iterator& operator++();`` + +:Returns: ``*this`` + + +``function_output_iterator& operator++(int);`` + +:Returns: ``*this`` + + +``function_output_iterator::output_proxy`` operations +----------------------------------------------------- + +``output_proxy(UnaryFunction& f);`` + +:Returns: An instance of ``output_proxy`` with ``f`` stored as + a data member. + + +``template output_proxy& operator=(const T& value);`` + +:Effects: + :: + + m_f(value); + return *this; diff --git a/doc/indirect_iterator.rst b/doc/indirect_iterator.rst new file mode 100644 index 0000000..7d19ba2 --- /dev/null +++ b/doc/indirect_iterator.rst @@ -0,0 +1,23 @@ ++++++++++++++++++++ + Indirect Iterator ++++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, University of Hanover `Institute for Transport + Railway Operation and Construction`_ +:date: $Date$ +:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:abstract: + +.. include:: indirect_iterator_abstract.rst + +.. contents:: Table of Contents + +.. include:: indirect_iterator_ref.rst diff --git a/doc/indirect_iterator_abstract.rst b/doc/indirect_iterator_abstract.rst new file mode 100644 index 0000000..3b6c2a6 --- /dev/null +++ b/doc/indirect_iterator_abstract.rst @@ -0,0 +1,8 @@ +The indirect iterator adapts an iterator by applying an *extra* +dereference inside of ``operator*()``. For example, this iterator +adaptor makes it possible to view a container of pointers +(e.g. ``list``) as if it were a container of the pointed-to type +(e.g. ``list``) . + +.. At some point we should add the capability to handle + iterators over smart pointers, which the impl handles. -JGS diff --git a/doc/indirect_iterator_ref.rst b/doc/indirect_iterator_ref.rst new file mode 100644 index 0000000..ebbe2ff --- /dev/null +++ b/doc/indirect_iterator_ref.rst @@ -0,0 +1,96 @@ +:: + + template < + class Iterator + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class indirect_iterator + : public iterator_adaptor + { + friend class iterator_core_access; + public: + indirect_iterator(); + indirect_iterator(Iterator x); + template < + class Iterator2, class Value2, class Category2 + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Category2, Reference2, Difference2 + > const& y + , typename enable_if_convertible::type* = 0 // exposition + ); + private: // as-if specification + typename indirect_iterator::reference dereference() const + { + return **this->base(); + } + }; + +``indirect_iterator`` requirements +.................................. + +The ``value_type`` of the ``Iterator`` template parameter should +itself be dereferenceable. The return type of the ``operator*`` for +the ``value_type`` must be the same type as the ``Reference`` template +parameter. The ``Value`` template parameter will be the ``value_type`` +for the ``indirect_iterator``, unless ``Value`` is const. If ``Value`` +is ``const X``, then ``value_type`` will be *non-* ``const X``. The +default for ``Value`` is + +:: + + iterator_traits< iterator_traits::value_type >::value_type + +If the default is used for ``Value``, then there must be a valid +specialization of ``iterator_traits`` for the value type of the base +iterator. + +The ``Reference`` parameter will be the ``reference`` type of the +``indirect_iterator``. The default is ``Value&``. + +The ``Category`` parameter is the ``iterator_category`` type for the +``indirect_iterator``. The default is +``iterator_traits::iterator_category``. + +The indirect iterator will model the most refined standard traversal +concept that is modeled by the ``Iterator`` type. The indirect +iterator will model the most refined standard access concept that is +modeled by the value type of ``Iterator``. + + +``indirect_iterator`` operations +................................ + +``indirect_iterator();`` + +:Requires: ``Iterator`` must be Default Constructible. +:Returns: An instance of ``indirect_iterator`` with + a default constructed base object. + + +``indirect_iterator(Iterator x);`` + +:Returns: An instance of ``indirect_iterator`` with + the ``iterator_adaptor`` subobject copy constructed from ``x``. + +:: + + template < + class Iterator2, class Value2, class Category2 + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Category2, Reference2, Difference2 + > const& y + , typename enable_if_convertible::type* = 0 // exposition + ); + +:Requires: ``Iterator2`` is implicitly convertible to ``Iterator``. +:Returns: An instance of ``indirect_iterator`` that is a copy of ``y``. + diff --git a/doc/permutation_iterator.rst b/doc/permutation_iterator.rst new file mode 100644 index 0000000..3d75608 --- /dev/null +++ b/doc/permutation_iterator.rst @@ -0,0 +1,31 @@ +++++++++++++++++++++++ + Permutation Iterator +++++++++++++++++++++++ + +:Author: Toon Knapen, David Abrahams, Roland Richter, Jeremy Siek +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_ +:date: $Date$ +:copyright: Copyright Toon Knapen, Dave Abrahams, Roland Richter, and Jeremy Siek 2003. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu + +:abstract: + +.. include:: permutation_iterator_abstract.rst + +.. contents:: Table of Contents + + +Introduction +============ + +.. include:: permutation_iterator_body.rst + + +Reference +========= + +.. include:: permutation_iterator_ref.rst diff --git a/doc/permutation_iterator_abstract.rst b/doc/permutation_iterator_abstract.rst new file mode 100644 index 0000000..578b3ed --- /dev/null +++ b/doc/permutation_iterator_abstract.rst @@ -0,0 +1,4 @@ +The permutation iterator adaptor provides a permuted view of a given +range. That is, the view includes every element of the given range but +in a potentially different order. + diff --git a/doc/permutation_iterator_body.rst b/doc/permutation_iterator_body.rst new file mode 100644 index 0000000..0f838e7 --- /dev/null +++ b/doc/permutation_iterator_body.rst @@ -0,0 +1,15 @@ +The adaptor takes two arguments: + + * an iterator to the range V on which the permutation + will be applied + * the reindexing scheme that defines how the + elements of V will be permuted. + +Note that the permutation iterator is not limited to strict +permutations of the given range V. The distance between begin and end +of the reindexing iterators is allowed to be smaller compared to the +size of the range V, in which case the permutation iterator only +provides a permutation of a subrange of V. The indexes neither need +to be unique. In this same context, it must be noted that the past the +end permutation iterator is completely defined by means of the +past-the-end iterator to the indices. diff --git a/doc/permutation_iterator_ref.rst b/doc/permutation_iterator_ref.rst new file mode 100644 index 0000000..ef84045 --- /dev/null +++ b/doc/permutation_iterator_ref.rst @@ -0,0 +1,54 @@ +.. parsed-literal:: + + template< class ElementIterator + , class IndexIterator + , class ValueT = use_default + , class CategoryT = use_default + , class ReferenceT = use_default + , class DifferenceT = use_default > + class permutation_iterator + : public iterator_adaptor<...> + { + typedef iterator_adaptor<...> + friend class iterator_core_access; + public: + permutation_iterator(); + explicit permutation_iterator(ElementIterator x, IndexIterator y); + + template< class OEIter, class OIIter, class V, class C, class R, class D > + permutation_iterator( + permutation_iterator const& r + , typename enable_if_convertible::type* = 0 + , typename enable_if_convertible::type* = 0 + ); + }; + + + +``permutation_iterator`` requirements +------------------------------------- + +``ElementIterator`` must be a model of RandomAccessIterator__. +``IndexIterator`` must at least be a model ForwardIterator__. The +value type of the ``IndexIterator`` must be convertible to the +difference type of ``ElementIterator``. + +__ http://www.sgi.com/tech/stl/RandomAccessIterator.html + +__ http://www.sgi.com/tech/stl/ForwardIterator.html + + + + +``permutation_iterator`` operations +----------------------------------- + +The permutation iterator implements the member functions and operators +required for the `Random Access Iterator`__ concept. However, the +permutation iterator can only meet the complexity guarantees of the +same concept as the IndexIterator. Thus for instance, although the +permutation iterator provides ``operator+=(distance)``, this operation +will take linear time in case the IndexIterator is a model of +ForwardIterator instead of amortized constant time. + +__ http://www.sgi.com/tech/stl/RandomAccessIterator.html diff --git a/doc/reverse_iterator.rst b/doc/reverse_iterator.rst new file mode 100644 index 0000000..44b9101 --- /dev/null +++ b/doc/reverse_iterator.rst @@ -0,0 +1,23 @@ +++++++++++++++++++ + Reverse Iterator +++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, University of Hanover `Institute for Transport + Railway Operation and Construction`_ +:date: $Date$ +:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:abstract: + +.. include:: reverse_iterator_abstract.rst + +.. contents:: Table of Contents + +.. include:: reverse_iterator_ref.rst diff --git a/doc/reverse_iterator_abstract.rst b/doc/reverse_iterator_abstract.rst new file mode 100644 index 0000000..0574988 --- /dev/null +++ b/doc/reverse_iterator_abstract.rst @@ -0,0 +1,6 @@ +.. I think we'd better strike the old reverse_iterator text from the standard, eh? + +The reverse iterator adaptor flips the direction of a base iterator's +motion. Invoking ``operator++()`` moves the base iterator backward and +invoking ``operator--()`` moves the base iterator forward. + diff --git a/doc/reverse_iterator_ref.rst b/doc/reverse_iterator_ref.rst new file mode 100644 index 0000000..c0acc2b --- /dev/null +++ b/doc/reverse_iterator_ref.rst @@ -0,0 +1,69 @@ +:: + + template + class reverse_iterator : + public iterator_adaptor< reverse_iterator, Iterator > + { + friend class iterator_core_access; + public: + reverse_iterator() {} + explicit reverse_iterator(Iterator x) ; + + template + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::type* = 0 // exposition + ); + + private: // as-if specification + typename reverse_iterator::reference dereference() const { return *prior(this->base()); } + + void increment() { --this->base_reference(); } + void decrement() { ++this->base_reference(); } + + void advance(typename reverse_iterator::difference_type n) + { + this->base_reference() += -n; + } + + template + typename reverse_iterator::difference_type + distance_to(reverse_iterator const& y) const + { + return this->base_reference() - y.base(); + } + + }; + + +``reverse_iterator`` requirements +................................. + +The base ``Iterator`` must be a model of Bidirectional Traversal +Iterator. The resulting ``reverse_iterator`` will be a model of the +most refined standard traversal and access concepts that are modeled +by ``Iterator``. + + +``reverse_iterator();`` + +:Requires: ``Iterator`` must be Default Constructible. +:Returns: An instance of ``reverse_iterator`` with a + default constructed base object. + +``explicit reverse_iterator(Iterator x);`` + +:Returns: An instance of ``reverse_iterator`` with a + base object copy constructed from ``x``. + + +:: + + template + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::type* = 0 // exposition + ); + +:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. +:Returns: An instance of ``reverse_iterator`` that is a copy of ``r``. diff --git a/doc/transform_iterator.rst b/doc/transform_iterator.rst new file mode 100644 index 0000000..6f8be45 --- /dev/null +++ b/doc/transform_iterator.rst @@ -0,0 +1,23 @@ +++++++++++++++++++++ + Transform Iterator +++++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, University of Hanover `Institute for Transport + Railway Operation and Construction`_ +:date: $Date$ +:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:abstract: + +.. include:: transform_iterator_abstract.rst + +.. contents:: Table of Contents + +.. include:: transform_iterator_ref.rst diff --git a/doc/transform_iterator_abstract.rst b/doc/transform_iterator_abstract.rst new file mode 100644 index 0000000..6a7534e --- /dev/null +++ b/doc/transform_iterator_abstract.rst @@ -0,0 +1,5 @@ +The transform iterator adapts an iterator by applying some function +object to the result of dereferencing the iterator. In other words, +the ``operator*`` of the transform iterator first dereferences the +base iterator, passes the result of this to the function object, and +then returns the result. diff --git a/doc/transform_iterator_ref.rst b/doc/transform_iterator_ref.rst new file mode 100644 index 0000000..bb59c1e --- /dev/null +++ b/doc/transform_iterator_ref.rst @@ -0,0 +1,95 @@ +:: + + template + class transform_iterator + : public iterator_adaptor + { + friend class iterator_core_access; + public: + transform_iterator(); + transform_iterator(Iterator const& x, AdaptableUnaryFunction f); + + template + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + ); + + AdaptableUnaryFunction functor() const; + private: + typename transform_iterator::value_type dereference() const; + AdaptableUnaryFunction m_f; + }; + + +``transform_iterator`` requirements +................................... + +The type ``AdaptableUnaryFunction`` must be Assignable, Copy +Constructible, and the expression ``f(x)`` must be valid where ``f`` +is an object of type ``AdaptableUnaryFunction``, ``x`` is an object of +type ``AdaptableUnaryFunction::argument_type``, and where the type of +``f(x)`` must be ``AdaptableUnaryFunction::result_type``. + +The type ``Iterator`` must at least model Readable Iterator. The +resulting ``transform_iterator`` models the most refined of the +following options that is also modeled by ``Iterator``. + + * Writable Lvalue Iterator if the ``result_type`` of the + ``AdaptableUnaryFunction`` is a non-const reference. + + * Readable Lvalue Iterator if the ``result_type`` is a const + reference. + + * Readable Iterator otherwise. + + +The ``transform_iterator`` models the most refined standard traversal +concept that is modeled by ``Iterator``. + +The ``value_type`` of ``transform_iterator`` is +``remove_reference::type``. The ``reference`` type is +``result_type``. + + +``transform_iterator`` public operations +........................................ + + +``transform_iterator();`` + +:Returns: An instance of ``transform_iterator`` with ``m_f`` + and ``m_iterator`` default constructed. + + +``transform_iterator(Iterator const& x, AdaptableUnaryFunction f);`` + +:Returns: An instance of ``transform_iterator`` with ``m_f`` + initialized to ``f`` and ``m_iterator`` initialized to ``x``. + + +:: + + template + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + ); + +:Returns: An instance of ``transform_iterator`` that is a copy of ``t``. +:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. + +``AdaptableUnaryFunction functor() const;`` + +:Returns: ``m_f`` + +``transform_iterator`` private operations +......................................... + +``typename transform_iterator::value_type dereference() const;`` + +:Returns: ``m_f(transform_iterator::dereference());`` + From f98f3497b82b0901d2d05c19043964fdcf98cded Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Tue, 5 Aug 2003 19:48:41 +0000 Subject: [PATCH 198/265] generated output [SVN r19468] --- doc/counting_iterator.html | 144 ++++++++ doc/filter_iterator.html | 190 ++++++++++ doc/function_output_iterator.html | 159 +++++++++ doc/indirect_iterator.html | 163 +++++++++ doc/iterator_adaptor.html | 326 +++++++++++++++++ doc/iterator_facade.html | 574 ++++++++++++++++++++++++++++++ doc/permutation_iterator.html | 122 +++++++ doc/reverse_iterator.html | 137 +++++++ doc/transform_iterator.html | 169 +++++++++ 9 files changed, 1984 insertions(+) create mode 100644 doc/counting_iterator.html create mode 100644 doc/filter_iterator.html create mode 100644 doc/function_output_iterator.html create mode 100644 doc/indirect_iterator.html create mode 100644 doc/iterator_adaptor.html create mode 100644 doc/iterator_facade.html create mode 100644 doc/permutation_iterator.html create mode 100644 doc/reverse_iterator.html create mode 100644 doc/transform_iterator.html diff --git a/doc/counting_iterator.html b/doc/counting_iterator.html new file mode 100644 index 0000000..4465a98 --- /dev/null +++ b/doc/counting_iterator.html @@ -0,0 +1,144 @@ + + + + + + +Counting Iterator + + + + + + + +
+

Counting Iterator

+
+++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2003-08-05
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
+ +++ + + + +
abstract:
+

The counting iterator adaptor implements dereference by returning a +reference to the base object. The other operations are implemented by +the base m_iterator, as per the inheritance from +iterator_adaptor.

+ +
+template <class Incrementable, class Category = use_default, class Difference = use_default>
+class counting_iterator
+  : public iterator_adaptor<
+        counting_iterator<Incrementable, Category, Difference>
+      , Incrementable
+      , Incrementable
+      , /* see details for category */
+      , Incrementable const&
+      , Incrementable const*
+      , /* distance = Difference or a signed integral type */>
+{
+    friend class iterator_core_access;
+ public:
+    counting_iterator();
+    counting_iterator(counting_iterator const& rhs);
+    counting_iterator(Incrementable x);
+ private:
+    typename counting_iterator::reference dereference() const
+    {
+        return this->base_reference();
+    }
+  };
+
+
+
[Note: implementers are encouraged to provide an implementation of
+
distance_to and a difference_type that avoids overflows in +the cases when the Incrementable type is a numeric type.]
+
+
+

counting_iterator requirements

+

The Incrementable type must be Default Constructible, Copy +Constructible, and Assignable. The default distance is +an implementation defined signed integegral type.

+

The resulting counting_iterator models Readable Lvalue Iterator.

+

Furthermore, if you wish to create a counting iterator that is a Forward +Traversal Iterator, then the following expressions must be valid:

+
+Incrementable i, j;
+++i         // pre-increment
+i == j      // operator equal
+
+

If you wish to create a counting iterator that is a +Bidirectional Traversal Iterator, then pre-decrement is also required:

+
+--i
+
+

If you wish to create a counting iterator that is a Random Access +Traversal Iterator, then these additional expressions are also +required:

+
+counting_iterator::difference_type n;
+i += n
+n = i - j
+i < j
+
+
+
+

counting_iterator operations

+

counting_iterator();

+ +++ + + + +
Returns:A default constructed instance of counting_iterator.
+

counting_iterator(counting_iterator const& rhs);

+ +++ + + + +
Returns:An instance of counting_iterator that is a copy of rhs.
+

counting_iterator(Incrementable x);

+ +++ + + + +
Returns:An instance of counting_iterator with its base +object copy constructed from x.
+
+
+ + diff --git a/doc/filter_iterator.html b/doc/filter_iterator.html new file mode 100644 index 0000000..a0fa47c --- /dev/null +++ b/doc/filter_iterator.html @@ -0,0 +1,190 @@ + + + + + + +Filter Iterator + + + + + + + +
+

Filter Iterator

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2003-08-05
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
+ +++ + + + +
abstract:
+

The filter iterator adaptor creates a view of an iterator range in +which some elements of the range are skipped over. A predicate +function object controls which elements are skipped. When the +predicate is applied to an element, if it returns true then the +element is retained and if it returns false then the element is +skipped over. When skipping over elements, it is necessary for the +filter adaptor to know when to stop so as to avoid going past the end +of the underlying range. Therefore the constructor of the filter +iterator takes two iterator parameters: the position for the filtered +iterator and the end of the range.

+ +
+template <class Predicate, class Iterator>
+class filter_iterator
+    : public iterator_adaptor<
+          filter_iterator<Predicate, Iterator>, Iterator
+        , use_default
+        , /* see details */
+      >
+{
+ public:
+    filter_iterator();
+    filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());
+    filter_iterator(Iterator x, Iterator end = Iterator());
+    template<class OtherIterator>
+    filter_iterator(
+        filter_iterator<Predicate, OtherIterator> const& t
+        , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+        );
+    Predicate predicate() const;
+    Iterator end() const;
+
+ private: // as-if specification
+    void increment()
+    {
+        ++(this->base_reference());
+        satisfy_predicate();
+    }
+
+    void satisfy_predicate()
+    {
+        while (this->base() != this->m_end && !this->m_predicate(*this->base()))
+            ++(this->base_reference());
+    }
+
+    Predicate m_predicate;
+    Iterator m_end;
+};
+
+
+

filter_iterator requirements

+

The base Iterator parameter must be a model of Readable Iterator +and Single Pass Iterator. The resulting filter_iterator will be a +model of Forward Traversal Iterator if Iterator is, otherwise the +filter_iterator will be a model of Single Pass Iterator. The +access category of the filter_iterator will be the most refined +standard access category that is modeled by Iterator.

+ +

The Predicate must be Assignable, Copy Constructible, and the +expression p(x) must be valid where p is an object of type +Predicate, x is an object of type +iterator_traits<Iterator>::value_type, and where the type of +p(x) must be convertible to bool.

+
+
+

filter_iterator operations

+

filter_iterator();

+ +++ + + + + + +
Requires:Predicate and Iterator must be Default Constructible.
Returns:a filter_iterator whose +predicate is a default constructed Predicate and +whose end is a default constructed Iterator.
+

filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());

+ +++ + + + +
Returns:A filter_iterator at position x that filters according +to predicate f and that will not increment past end.
+

filter_iterator(Iterator x, Iterator end = Iterator());

+ +++ + + + + + +
Requires:Predicate must be Default Constructible.
Returns:A filter_iterator at position x that filters +according to a default constructed Predicate +and that will not increment past end.
+
+template <class OtherIterator>
+filter_iterator(
+    filter_iterator<Predicate, OtherIterator> const& t
+    , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+    );``
+
+ +++ + + + + + +
Requires:OtherIterator is implicitly convertible to Iterator.
Returns:A copy of iterator t.
+

Predicate predicate() const;

+ +++ + + + +
Returns:A copy of the predicate object used to construct *this.
+

Iterator end() const;

+ +++ + + + +
Returns:The object end used to construct *this.
+
+
+ + diff --git a/doc/function_output_iterator.html b/doc/function_output_iterator.html new file mode 100644 index 0000000..e3e1ba3 --- /dev/null +++ b/doc/function_output_iterator.html @@ -0,0 +1,159 @@ + + + + + + +Function Output Iterator + + + + + + + +
+

Function Output Iterator

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2003-08-05
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
+ +++ + + + +
abstract:
+

The function output iterator adaptor makes it easier to create custom +output iterators. The adaptor takes a unary function and creates a +model of Output Iterator. Each item assigned to the output iterator is +passed as an argument to the unary function. The motivation for this +iterator is that creating a conforming output iterator is non-trivial, +particularly because the proper implementation usually requires a +proxy object.

+ +
+template <class UnaryFunction>
+class function_output_iterator {
+public:
+  typedef iterator_tag<
+        writable_iterator_tag
+      , incrementable_traversal_tag
+  > iterator_category;
+  typedef void                value_type;
+  typedef void                difference_type;
+  typedef void                pointer;
+  typedef void                reference;
+
+  explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());
+
+  struct output_proxy {
+    output_proxy(UnaryFunction& f);
+    template <class T> output_proxy& operator=(const T& value);
+  };
+  output_proxy operator*();
+  function_output_iterator& operator++();
+  function_output_iterator& operator++(int);
+};
+
+
+

function_output_iterator requirements

+

The UnaryFunction must be Assignable, Copy Constructible, and the +expression f(x) must be valid, where f is an object of type +UnaryFunction and x is an object of a type accepted by f. +The resulting function_output_iterator is a model of the Writable +and Incrementable Iterator concepts.

+
+
+

function_output_iterator operations

+

explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());

+ +++ + + + +
Returns:An instance of function_output_iterator with +f stored as a data member.
+

output_proxy operator*();

+ +++ + + + +
Returns:An instance of output_proxy constructed with +a copy of the unary function f.
+

function_output_iterator& operator++();

+ +++ + + + +
Returns:*this
+

function_output_iterator& operator++(int);

+ +++ + + + +
Returns:*this
+
+
+

function_output_iterator::output_proxy operations

+

output_proxy(UnaryFunction& f);

+ +++ + + + +
Returns:An instance of output_proxy with f stored as +a data member.
+

template <class T> output_proxy& operator=(const T& value);

+ +++ + + + +
Effects:
+m_f(value); 
+return *this; 
+
+
+
+
+ + diff --git a/doc/indirect_iterator.html b/doc/indirect_iterator.html new file mode 100644 index 0000000..cff848f --- /dev/null +++ b/doc/indirect_iterator.html @@ -0,0 +1,163 @@ + + + + + + +Indirect Iterator + + + + + + + +
+

Indirect Iterator

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2003-08-05
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
+ +++ + + + +
abstract:
+

The indirect iterator adapts an iterator by applying an extra +dereference inside of operator*(). For example, this iterator +adaptor makes it possible to view a container of pointers +(e.g. list<foo*>) as if it were a container of the pointed-to type +(e.g. list<foo>) .

+ + +
+template <
+    class Iterator
+  , class Value = use_default
+  , class Category = use_default
+  , class Reference = use_default
+  , class Difference = use_default
+>
+class indirect_iterator
+  : public iterator_adaptor</* see discussion */>
+{
+    friend class iterator_core_access;
+ public:
+    indirect_iterator();
+    indirect_iterator(Iterator x);
+    template <
+        class Iterator2, class Value2, class Category2
+      , class Reference2, class Difference2
+    >
+    indirect_iterator(
+        indirect_iterator<
+             Iterator2, Value2, Category2, Reference2, Difference2
+        > const& y
+      , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition
+    );
+private: // as-if specification
+    typename indirect_iterator::reference dereference() const
+    {
+        return **this->base();
+    }
+};
+
+
+

indirect_iterator requirements

+

The value_type of the Iterator template parameter should +itself be dereferenceable. The return type of the operator* for +the value_type must be the same type as the Reference template +parameter. The Value template parameter will be the value_type +for the indirect_iterator, unless Value is const. If Value +is const X, then value_type will be non- const X. The +default for Value is

+
+iterator_traits< iterator_traits<Iterator>::value_type >::value_type
+
+

If the default is used for Value, then there must be a valid +specialization of iterator_traits for the value type of the base +iterator.

+

The Reference parameter will be the reference type of the +indirect_iterator. The default is Value&.

+

The Category parameter is the iterator_category type for the +indirect_iterator. The default is +iterator_traits<Iterator>::iterator_category.

+

The indirect iterator will model the most refined standard traversal +concept that is modeled by the Iterator type. The indirect +iterator will model the most refined standard access concept that is +modeled by the value type of Iterator.

+
+
+

indirect_iterator operations

+

indirect_iterator();

+ +++ + + + + + +
Requires:Iterator must be Default Constructible.
Returns:An instance of indirect_iterator with +a default constructed base object.
+

indirect_iterator(Iterator x);

+ +++ + + + +
Returns:An instance of indirect_iterator with +the iterator_adaptor subobject copy constructed from x.
+
+template <
+    class Iterator2, class Value2, class Category2
+  , class Reference2, class Difference2
+>
+indirect_iterator(
+    indirect_iterator<
+         Iterator2, Value2, Category2, Reference2, Difference2
+    > const& y
+  , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition
+);
+
+ +++ + + + + + +
Requires:Iterator2 is implicitly convertible to Iterator.
Returns:An instance of indirect_iterator that is a copy of y.
+
+
+ + diff --git a/doc/iterator_adaptor.html b/doc/iterator_adaptor.html new file mode 100644 index 0000000..641ac85 --- /dev/null +++ b/doc/iterator_adaptor.html @@ -0,0 +1,326 @@ + + + + + + +Iterator Adaptor + + + + + + + +
+

Iterator Adaptor

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2003-08-05
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
+ +++ + + + +
abstract:
+

The iterator_adaptor is a base class template derived from an +instantiation of iterator_facade. The core interface functions +expected by iterator_facade are implemented in terms of the +iterator_adaptor's Base template parameter. A class derived +from iterator_adaptor typically redefines some of the core +interface functions to adapt the behavior of the Base type. +Whether the derived class models any of the standard iterator concepts +depends on the operations supported by the Base type and which +core interface functions of iterator_facade are redefined in the +Derived class.

+ +
+

Introduction

+

The iterator_adaptor class template adapts some Base 1 +type to create a new iterator. Instantiations of iterator_adaptor +are derived from a corresponding instantiation of iterator_facade +and implement the core behaviors in terms of the Base type. In +essence, iterator_adaptor merely forwards all operations to an +instance of the Base type, which it stores as a member.

+ + + + + +
[1]The term "Base" here does not refer to a base class and is +not meant to imply the use of derivation. We have followed the lead +of the standard library, which provides a base() function to access +the underlying iterator object of a reverse_iterator adaptor.
+

The user of iterator_adaptor creates a class derived from an +instantiation of iterator_adaptor and then selectively +redefines some of the core member functions described in the table +above. The Base type need not meet the full requirements for an +iterator. It need only support the operations used by the core +interface functions of iterator_adaptor that have not been +redefined in the user's derived class.

+

Several of the template parameters of iterator_adaptor default to +use_default. This allows the user to make use of a default +parameter even when the user wants to specify a parameter later in the +parameter list. Also, the defaults for the corresponding associated +types are fairly complicated, so metaprogramming is required to +compute them, and use_default can help to simplify the +implementation. Finally, use_default is not left unspecified +because specification helps to highlight that the Reference +template parameter may not always be identical to the iterator's +reference type, and will keep users making mistakes based on that +assumption.

+
+
+

Reference

+
+template <
+    class Derived
+  , class Base
+  , class Value      = use_default
+  , class Category   = use_default
+  , class Reference  = use_default
+  , class Difference = use_default
+>
+class iterator_adaptor 
+  : public iterator_facade<Derived, /* see details ...*/>
+{
+    friend class iterator_core_access;
+ public:
+    iterator_adaptor();
+    explicit iterator_adaptor(Base iter);
+    Base base() const;
+ protected:
+    Base const& base_reference() const;
+    Base& base_reference();
+ private: // Core iterator interface for iterator_facade.  
+    typename iterator_adaptor::reference dereference() const;
+
+    template <
+    class OtherDerived, class OtherIterator, class V, class C, class R, class D
+    >   
+    bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
+
+    void advance(typename iterator_adaptor::difference_type n);
+    void increment();
+    void decrement();
+
+    template <
+        class OtherDerived, class OtherIterator, class V, class C, class R, class D
+    >   
+    typename iterator_adaptor::difference_type distance_to(
+        iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
+
+ private:
+    Base m_iterator;
+};
+
+
+

iterator_adaptor requirements

+

The Derived template parameter must be a derived class of +iterator_adaptor. The Base type must implement the expressions +involving m_iterator in the specifications of those private member +functions of iterator_adaptor that are not redefined by the +Derived class and that are needed to model the concept +corresponding to the chosen Category according to the requirements +of iterator_facade. The rest of the template parameters specify +the types for the member typedefs in iterator_facade. The +following pseudo-code specifies the traits types for +iterator_adaptor.

+
+if (Value == use_default)
+    value_type = iterator_traits<Base>::value_type;
+else 
+    value_type = remove_cv<Value>::type;
+
+if (Reference == use_default) {
+    if (Value == use_default)
+        reference = iterator_traits<Base>::reference;
+    else 
+        reference = Value&;
+} else
+    reference = Reference;
+
+if (Distance == use_default)
+    difference_type = iterator_traits<Base>::difference_type;
+else
+    difference_type = Distance;
+
+if (Category == use_default)
+    iterator_category = iterator_tag< 
+        access_category< 
+            iterator< iterator_traits<Base>::iterator_category,
+                      Value,
+                      Distance,
+                      Value*,
+                      Reference > >,
+        traversal_category<
+            iterator< iterator_traits<Base>::iterator_category,
+                      Value,
+                      Distance,
+                      Value*,
+                      Reference > >
+else
+    iterator_category = Category;
+
+ +
+
+

iterator_adaptor public operations

+

iterator_adaptor();

+ +++ + + + + + +
Requires:The Base type must be Default Constructible.
Returns:An instance of iterator_adaptor with +m_iterator default constructed.
+

explicit iterator_adaptor(Base iter);

+ +++ + + + +
Returns:An instance of iterator_adaptor with +m_iterator copy constructed from iter.
+

Base base() const;

+ +++ + + + +
Returns:m_iterator
+
+
+

iterator_adaptor protected member functions

+

Base const& base_reference() const;

+ +++ + + + +
Returns:A const reference to m_iterator.
+

Base& base_reference();

+ +++ + + + +
Returns:A non-const reference to m_iterator.
+
+
+

iterator_adaptor private member functions

+

typename iterator_adaptor::reference dereference() const;

+ +++ + + + +
Returns:*m_iterator
+
+template <
+class OtherDerived, class OtherIterator, class V, class C, class R, class D
+>   
+bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
+
+ +++ + + + +
Returns:m_iterator == x.base()
+

void advance(typename iterator_adaptor::difference_type n);

+ +++ + + + +
Effects:m_iterator += n;
+

void increment();

+ +++ + + + +
Effects:++m_iterator;
+

void decrement();

+ +++ + + + +
Effects:--m_iterator;
+
+template <
+    class OtherDerived, class OtherIterator, class V, class C, class R, class D
+>   
+typename iterator_adaptor::difference_type distance_to(
+    iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
+
+ +++ + + + +
Returns:y.base() - m_iterator
+
+
+
+ + diff --git a/doc/iterator_facade.html b/doc/iterator_facade.html new file mode 100644 index 0000000..64c6764 --- /dev/null +++ b/doc/iterator_facade.html @@ -0,0 +1,574 @@ + + + + + + +Iterator Facade + + + + + + + +
+

Iterator Facade

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2003-08-05
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
+ +++ + + + +
abstract:
+

iterator_facade is a base class template that implements the +interface of standard iterators in terms of a few core functions +and associated types, to be supplied by a derived iterator class.

+ +
+

Motivation

+

While the iterator interface is rich, there is a core subset of the +interface that is necessary for all the functionality. We have +identified the following core behaviors for iterators:

+
    +
  • dereferencing
  • +
  • incrementing
  • +
  • decrementing
  • +
  • equality comparison
  • +
  • random-access motion
  • +
  • distance measurement
  • +
+

In addition to the behaviors listed above, the core interface elements +include the associated types exposed through iterator traits: +value_type, reference, difference_type, and +iterator_category.

+

Iterator facade uses the Curiously Recurring Template Pattern (CRTP) +[Cop95] so that the user can specify the behavior of +iterator_facade in a derived class. Former designs used policy +objects to specify the behavior. iterator_facade does not use policy +objects for several reasons:

+
+
    +
  1. the creation and eventual copying of the policy object may create +overhead that can be avoided with the current approach.
  2. +
  3. The policy object approach does not allow for custom constructors +on the created iterator types, an essential feature if +iterator_facade should be used in other library +implementations.
  4. +
  5. Without the use of CRTP, the standard requirement that an +iterator's operator++ returns the iterator type itself means +that all iterators generated by iterator_facade would be +instantiations of iterator_facade. Cumbersome type generator +metafunctions would be needed to build new parameterized +iterators, and a separate iterator_adaptor layer would be +impossible.
  6. +
+
+
+
+

Usage

+

The user of iterator_facade derives his iterator class from an +instantiation of iterator_facade which takes the derived iterator +class as the first template parameter. The order of the other +template parameters to iterator_facade have been carefully chosen +to take advantage of useful defaults. For example, when defining a +constant lvalue iterator, the user can pass a const-qualified version +of the iterator's value_type as iterator_facade's Value +parameter and omit the Reference parameter which follows.

+

The derived iterator class must define member functions implementing +the iterator's core behaviors. The following table describes +expressions which are required to be valid depending on the category +of the derived iterator type. These member functions are described +briefly below and in more detail in the iterator facade +requirements.

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionEffects
i.dereference()Access the value referred to
i.equal(j)Compare for equality with j
i.increment()Advance by one position
i.decrement()Retreat by one position
i.advance(n)Advance by n positions
i.distance_to(j)Measure the distance to j
+
+ +

In addition to implementing the core interface functions, an iterator +derived from iterator_facade typically defines several +constructors. To model any of the standard iterator concepts, the +iterator must at least have a copy constructor. Also, if the iterator +type X is meant to be automatically interoperate with another +iterator type Y (as with constant and mutable iterators) then +there must be an implicit conversion from X to Y or from Y +to X (but not both), typically implemented as a conversion +constructor. Finally, if the iterator is to model Forward Traversal +Iterator or a more-refined iterator concept, a default constructor is +required.

+
+
+

Iterator Core Access

+

iterator_facade and the operator implementations need to be able +to access the core member functions in the derived class. Making the +core member functions public would expose an implementation detail to +the user. The design used here ensures that implementation details do +not appear in the public interface of the derived iterator type.

+

Preventing direct access to the core member functions has two +advantages. First, there is no possibility for the user to accidently +use a member function of the iterator when a member of the value_type +was intended. This has been an issue with smart pointer +implementations in the past. The second and main advantage is that +library implementers can freely exchange a hand-rolled iterator +implementation for one based on iterator_facade without fear of +breaking code that was accessing the public core member functions +directly.

+

In a naive implementation, keeping the derived class' core member +functions private would require it to grant friendship to +iterator_facade and each of the seven operators. In order to +reduce the burden of limiting access, iterator_core_access is +provided, a class that acts as a gateway to the core member functions +in the derived iterator class. The author of the derived class only +needs to grant friendship to iterator_core_access to make his core +member functions available to the library.

+ + +

iterator_core_access will be typically implemented as an empty +class containing only private static member functions which invoke the +iterator core member functions. There is, however, no need to +standardize the gateway protocol. Note that even if +iterator_core_access used public member functions it would not +open a safety loophole, as every core member function preserves the +invariants of the iterator.

+
+
+

operator[]

+

The indexing operator for a generalized iterator presents special +challenges. A random access iterator's operator[] is only +required to return something convertible to its value_type. +Requiring that it return an lvalue would rule out currently-legal +random-access iterators which hold the referenced value in a data +member (e.g. counting_iterator), because *(p+n) is a reference +into the temporary iterator p+n, which is destroyed when +operator[] returns.

+

Writable iterators built with iterator_facade implement the +semantics required by the preferred resolution to issue 299 and +adopted by proposal n1477: the result of p[n] is a proxy object +containing a copy of p+n, and p[n] = x is equivalent to *(p ++ n) = x. This approach will work properly for any random-access +iterator regardless of the other details of its implementation. A +user who knows more about the implementation of her iterator is free +to implement an operator[] which returns an lvalue in the derived +iterator class; it will hide the one supplied by iterator_facade +from clients of her iterator.

+
+
+

operator->

+

The reference type of a readable iterator (and today's input +iterator) need not in fact be a reference, so long as it is +convertible to the iterator's value_type. When the value_type +is a class, however, it must still be possible to access members +through operator->. Therefore, an iterator whose reference +type is not in fact a reference must return a proxy containing a copy +of the referenced value from its operator->.

+

The return type for operator-> and operator[] is not +explicitly specified. Instead it requires each iterator_facade +instantiation to meet the requirements of its iterator_category.

+ + ++ + + +
[Cop95][Coplien, 1995] Coplien, J., Curiously Recurring Template +Patterns, C++ Report, February 1995, pp. 24-27.
+
+
+

Reference

+
+template <
+    class Derived
+  , class Value
+  , class AccessCategory
+  , class TraversalCategory
+  , class Reference  = /* see below */
+  , class Difference = ptrdiff_t
+>
+class iterator_facade {
+public:
+    typedef remove_cv<Value>::type value_type;
+    typedef Reference reference;
+    typedef /* see description of operator-> */ pointer;
+    typedef Difference difference_type;
+    typedef iterator_tag<AccessCategory, TraversalCategory> iterator_category;
+
+    reference operator*() const;
+    /* see below */ operator->() const;
+    /* see below */ operator[](difference_type n) const;
+    Derived& operator++();
+    Derived operator++(int);
+    Derived& operator--();
+    Derived operator--(int);
+    Derived& operator+=(difference_type n);
+    Derived& operator-=(difference_type n);
+    Derived operator-(difference_type n) const;
+};
+
+// Comparison operators
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type // exposition
+operator ==(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator !=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator <(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+           iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator <=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator >(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+           iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator >=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator >=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+// Iterator difference
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator -(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+           iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+// Iterator addition
+template <class Derived, class V, class AC, class TC, class R, class D>
+Derived operator+ (iterator_facade<Derived, V, AC, TC, R, D> const&,
+                   typename Derived::difference_type n)
+
+

[Note: The enable_if_interoperable template used above is for exposition +purposes. The member operators should be only be in an overload set +provided the derived types Dr1 and Dr2 are interoperable, by +which we mean they are convertible to each other. The +enable_if_interoperable approach uses SFINAE to take the operators +out of the overload set when the types are not interoperable.]

+ +
+

iterator_facade requirements

+

The Derived template parameter must be a class derived from +iterator_facade.

+

The default for the Reference parameter is Value& if the +access category for iterator_facade is implicitly convertible to +writable_iterator_tag, and const Value& otherwise.

+

The following table describes the other requirements on the +Derived parameter. Depending on the resulting iterator's +iterator_category, a subset of the expressions listed in the table +are required to be valid. The operations in the first column must be +accessible to member functions of class iterator_core_access.

+

In the table below, X is the derived iterator type, a is an +object of type X, b and c are objects of type const X, +n is an object of X::difference_type, y is a constant +object of a single pass iterator type interoperable with X, and z +is a constant object of a random access traversal iterator type +interoperable with X.

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionReturn TypeAssertion/NoteRequired to implement +Iterator Concept(s)
c.dereference()X::reference Readable Iterator, Writable +Iterator
c.equal(b)convertible to booltrue iff b and c are +equivalent.Single Pass Iterator
c.equal(y)convertible to booltrue iff c and y refer to the +same position. Implements c == y +and c != y.Single Pass Iterator
a.advance(n)unused Random Access Traversal +Iterator
a.increment()unused Incrementable Iterator
a.decrement()unused Bidirectional Traversal +Iterator
c.distance_to(b)convertible to +X::difference_typeequivalent to distance(c, b)Random Access Traversal +Iterator
c.distance_to(z)convertible to +X::difference_typeequivalent to distance(c, z). +Implements c - z, c < z, c +<= z, c > z, and c >= c.Random Access Traversal +Iterator
+ +
+
+

iterator_facade operations

+

The operations in this section are described in terms of operations on +the core interface of Derived which may be inaccessible +(i.e. private). The implementation should access these operations +through member functions of class iterator_core_access.

+

reference operator*() const;

+ +++ + + + +
Returns:static_cast<Derived const*>(this)->dereference()
+

operator->() const; (see below)

+ +++ + + + +
Returns:

If X::reference is a reference type, returns an object +of type X::pointer equal to:

+
+&static_cast<Derived const*>(this)->dereference()
+
+

Otherwise returns an object of unspecified type such that, given an +object a of type X, a->m is equivalent to (w = *a, +w.m) for some temporary object w of type X::value_type.

+

The type X::pointer is Value* if the access category for +X is implicitly convertible to writable_iterator_tag, and +Value const* otherwise.

+
+

unspecified operator[](difference_type n) const;

+ +++ + + + +
Returns:an object convertible to X::reference and holding a copy +p of a+n such that, for a constant object v of type +X::value_type, X::reference(a[n] = v) is equivalent +to p = v.
+

Derived& operator++();

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->increment();
+return *this;
+
+
+ +

Derived operator++(int);

+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+++*this;
+return tmp;
+
+
+

Derived& operator--();

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->decrement();
+return *this;
+
+
+

Derived operator--(int);

+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+--*this;
+return tmp;
+
+
+

Derived& operator+=(difference_type n);

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->advance(n);
+return *this;
+
+
+

Derived& operator-=(difference_type n);

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->advance(-n);
+return *this;
+
+
+

Derived operator-(difference_type n) const;

+ +++ + + + + + +
Effects:Derived tmp(static_cast<Derived const*>(this)); +return tmp -= n;
Returns:static_cast<Derived const*>(this)->advance(-n);
+
+
+
+ + diff --git a/doc/permutation_iterator.html b/doc/permutation_iterator.html new file mode 100644 index 0000000..8d74da7 --- /dev/null +++ b/doc/permutation_iterator.html @@ -0,0 +1,122 @@ + + + + + + +Permutation Iterator + + + + + + + +
+

Permutation Iterator

+ +++ + + + + + + + + + + + +
Author:Toon Knapen, David Abrahams, Roland Richter, Jeremy Siek
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu
Organization:Boost Consulting, Indiana University Open Systems +Lab
Date:2003-08-05
Copyright:Copyright Toon Knapen, Dave Abrahams, Roland Richter, and Jeremy Siek 2003. All rights reserved
+ +++ + + + +
abstract:
+

The permutation iterator adaptor provides a permuted view of a given +range. That is, the view includes every element of the given range but +in a potentially different order.

+ +
+

Introduction

+

The adaptor takes two arguments:

+
+
    +
  • an iterator to the range V on which the permutation +will be applied
  • +
  • the reindexing scheme that defines how the +elements of V will be permuted.
  • +
+
+

Note that the permutation iterator is not limited to strict +permutations of the given range V. The distance between begin and end +of the reindexing iterators is allowed to be smaller compared to the +size of the range V, in which case the permutation iterator only +provides a permutation of a subrange of V. The indexes neither need +to be unique. In this same context, it must be noted that the past the +end permutation iterator is completely defined by means of the +past-the-end iterator to the indices.

+
+
+

Reference

+
+template< class ElementIterator
+        , class IndexIterator
+        , class ValueT        = use_default
+        , class CategoryT     = use_default
+        , class ReferenceT    = use_default
+        , class DifferenceT   = use_default >
+class permutation_iterator
+  : public iterator_adaptor<...>
+{
+  typedef iterator_adaptor<...>
+  friend class iterator_core_access;
+public:
+  permutation_iterator();
+  explicit permutation_iterator(ElementIterator x, IndexIterator y);
+
+  template< class OEIter, class OIIter, class V, class C, class R, class D >
+  permutation_iterator(
+      permutation_iterator<OEIter, OIIter, V, C, R, D> const& r
+      , typename enable_if_convertible<OEIter, ElementIterator>::type* = 0
+      , typename enable_if_convertible<OIIter, IndexIterator>::type* = 0
+      );
+};
+
+
+

permutation_iterator requirements

+

ElementIterator must be a model of RandomAccessIterator. +IndexIterator must at least be a model ForwardIterator. The +value type of the IndexIterator must be convertible to the +difference type of ElementIterator.

+
+
+

permutation_iterator operations

+

The permutation iterator implements the member functions and operators +required for the Random Access Iterator concept. However, the +permutation iterator can only meet the complexity guarantees of the +same concept as the IndexIterator. Thus for instance, although the +permutation iterator provides operator+=(distance), this operation +will take linear time in case the IndexIterator is a model of +ForwardIterator instead of amortized constant time.

+
+
+
+ + diff --git a/doc/reverse_iterator.html b/doc/reverse_iterator.html new file mode 100644 index 0000000..60d1521 --- /dev/null +++ b/doc/reverse_iterator.html @@ -0,0 +1,137 @@ + + + + + + +Reverse Iterator + + + + + + + +
+

Reverse Iterator

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2003-08-05
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
+ +++ + + + +
abstract:
+ +

The reverse iterator adaptor flips the direction of a base iterator's +motion. Invoking operator++() moves the base iterator backward and +invoking operator--() moves the base iterator forward.

+ +
+template <class Iterator>
+class reverse_iterator :
+  public iterator_adaptor< reverse_iterator<Iterator>, Iterator >
+{
+  friend class iterator_core_access;
+public:
+  reverse_iterator() {}
+  explicit reverse_iterator(Iterator x) ;
+
+  template<class OtherIterator>
+  reverse_iterator(
+      reverse_iterator<OtherIterator> const& r
+    , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+  );
+
+private: // as-if specification
+  typename reverse_iterator::reference dereference() const { return *prior(this->base()); }
+
+  void increment() { --this->base_reference(); }
+  void decrement() { ++this->base_reference(); }
+
+  void advance(typename reverse_iterator::difference_type n)
+  {
+      this->base_reference() += -n;
+  }
+
+  template <class OtherIterator>
+  typename reverse_iterator::difference_type
+  distance_to(reverse_iterator<OtherIterator> const& y) const
+  {
+      return this->base_reference() - y.base();
+  }
+
+};
+
+
+

reverse_iterator requirements

+

The base Iterator must be a model of Bidirectional Traversal +Iterator. The resulting reverse_iterator will be a model of the +most refined standard traversal and access concepts that are modeled +by Iterator.

+

reverse_iterator();

+ +++ + + + + + +
Requires:Iterator must be Default Constructible.
Returns:An instance of reverse_iterator with a +default constructed base object.
+

explicit reverse_iterator(Iterator x);

+ +++ + + + +
Returns:An instance of reverse_iterator with a +base object copy constructed from x.
+
+template<class OtherIterator>
+reverse_iterator(
+    reverse_iterator<OtherIterator> const& r
+  , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+);
+
+ +++ + + + + + +
Requires:OtherIterator is implicitly convertible to Iterator.
Returns:An instance of reverse_iterator that is a copy of r.
+
+
+ + diff --git a/doc/transform_iterator.html b/doc/transform_iterator.html new file mode 100644 index 0000000..685d240 --- /dev/null +++ b/doc/transform_iterator.html @@ -0,0 +1,169 @@ + + + + + + +Transform Iterator + + + + + + + +
+

Transform Iterator

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2003-08-05
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
+ +++ + + + +
abstract:
+

The transform iterator adapts an iterator by applying some function +object to the result of dereferencing the iterator. In other words, +the operator* of the transform iterator first dereferences the +base iterator, passes the result of this to the function object, and +then returns the result.

+ +
+template <class AdaptableUnaryFunction,
+          class Iterator, 
+          class Reference = use_default, 
+          class Value = use_default>
+class transform_iterator
+  : public iterator_adaptor</* see discussion */>
+{
+  friend class iterator_core_access;
+public:
+  transform_iterator();
+  transform_iterator(Iterator const& x, AdaptableUnaryFunction f);
+
+  template<class OtherIterator, class R2, class V2>
+  transform_iterator(
+        transform_iterator<AdaptableUnaryFunction, OtherIterator, R2, V2> const& t
+      , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+  );
+
+  AdaptableUnaryFunction functor() const;
+private:
+  typename transform_iterator::value_type dereference() const;
+  AdaptableUnaryFunction m_f;
+};
+
+
+

transform_iterator requirements

+

The type AdaptableUnaryFunction must be Assignable, Copy +Constructible, and the expression f(x) must be valid where f +is an object of type AdaptableUnaryFunction, x is an object of +type AdaptableUnaryFunction::argument_type, and where the type of +f(x) must be AdaptableUnaryFunction::result_type.

+

The type Iterator must at least model Readable Iterator. The +resulting transform_iterator models the most refined of the +following options that is also modeled by Iterator.

+
+
    +
  • Writable Lvalue Iterator if the result_type of the +AdaptableUnaryFunction is a non-const reference.
  • +
  • Readable Lvalue Iterator if the result_type is a const +reference.
  • +
  • Readable Iterator otherwise.
  • +
+
+

The transform_iterator models the most refined standard traversal +concept that is modeled by Iterator.

+

The value_type of transform_iterator is +remove_reference<result_type>::type. The reference type is +result_type.

+
+
+

transform_iterator public operations

+

transform_iterator();

+ +++ + + + +
Returns:An instance of transform_iterator with m_f +and m_iterator default constructed.
+

transform_iterator(Iterator const& x, AdaptableUnaryFunction f);

+ +++ + + + +
Returns:An instance of transform_iterator with m_f +initialized to f and m_iterator initialized to x.
+
+template<class OtherIterator, class R2, class V2>
+transform_iterator(
+      transform_iterator<AdaptableUnaryFunction, OtherIterator, R2, V2> const& t
+    , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+);
+
+ +++ + + + + + +
Returns:An instance of transform_iterator that is a copy of t.
Requires:OtherIterator is implicitly convertible to Iterator.
+

AdaptableUnaryFunction functor() const;

+ +++ + + + +
Returns:m_f
+
+
+

transform_iterator private operations

+

typename transform_iterator::value_type dereference() const;

+ +++ + + + +
Returns:m_f(transform_iterator::dereference());
+
+
+ + From a5179f6dfcbee3e3f08e6314975944b4b9a426bc Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 6 Aug 2003 14:36:16 +0000 Subject: [PATCH 199/265] clean up formatting [SVN r19476] --- include/boost/iterator/iterator_facade.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index 774323e..9ab70ad 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -251,18 +251,18 @@ namespace boost // Macros which describe the declarations of binary operators # define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ template < \ - class Derived1, class V1, class AC1, class TC1, class R1, class D1 \ - , class Derived2, class V2, class AC2, class TC2, class R2, class D2 \ + class Derived1, class V1, class AC1, class TC1, class R1, class D1 \ + , class Derived2, class V2, class AC2, class TC2, class R2, class D2 \ > \ prefix typename detail::enable_if_interoperable< \ Derived1, Derived2, result_type \ >::type \ operator op( \ - iterator_facade const& lhs \ + iterator_facade const& lhs \ , iterator_facade const& rhs) # define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \ - template \ + template \ prefix Derived operator+ args // From 36feca8a524d13d2cf12188091f8db0d20642e40 Mon Sep 17 00:00:00 2001 From: Ronald Garcia Date: Mon, 11 Aug 2003 16:29:47 +0000 Subject: [PATCH 200/265] Updated shared_container_iterator to use the new iterator adaptors library. Updated the documentation and examples as well to reflect the changes. [SVN r19535] --- include/boost/shared_container_iterator.hpp | 43 +++++++++++---------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/include/boost/shared_container_iterator.hpp b/include/boost/shared_container_iterator.hpp index 95cf6c1..e21d8da 100644 --- a/include/boost/shared_container_iterator.hpp +++ b/include/boost/shared_container_iterator.hpp @@ -15,38 +15,41 @@ namespace boost { template -struct shared_container_iterator_policies : - public boost::default_iterator_policies { +class shared_container_iterator : public iterator_adaptor< + shared_container_iterator, + typename Container::iterator> { + + typedef iterator_adaptor< + shared_container_iterator, + typename Container::iterator> super_t; + + typedef typename Container::iterator iterator_t; typedef boost::shared_ptr container_ref_t; + container_ref_t container_ref; - shared_container_iterator_policies(container_ref_t const& c) : - container_ref(c) { } - shared_container_iterator_policies() { } -}; - - -template -class shared_container_iterator_generator { - typedef typename Container::iterator iterator; - typedef shared_container_iterator_policies policy; public: - typedef boost::iterator_adaptor type; + shared_container_iterator() { } + + shared_container_iterator(iterator_t const& x,container_ref_t const& c) : + super_t(x), container_ref(c) { } + + }; template -typename shared_container_iterator_generator::type +shared_container_iterator make_shared_container_iterator(typename Container::iterator iter, boost::shared_ptr const& container) { - typedef typename shared_container_iterator_generator::type - iterator; - typedef shared_container_iterator_policies policy; - return iterator(iter,policy(container)); + typedef shared_container_iterator iterator; + return iterator(iter,container); } + + template std::pair< - typename shared_container_iterator_generator::type, - typename shared_container_iterator_generator::type> + shared_container_iterator, + shared_container_iterator > make_shared_container_range(boost::shared_ptr const& container) { return std::make_pair( From f325582c402211a56b88a66c5acc5ee0b0b70897 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 14 Aug 2003 20:05:44 +0000 Subject: [PATCH 201/265] some fixes to writable iterators [SVN r19609] --- doc/new-iter-concepts.rst | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index be1b357..ff39358 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -350,17 +350,9 @@ Writable Iterators [lib.writable.iterators] A class or built-in type ``X`` models the *Writable Iterator* concept if the following expressions are valid and respect the stated -semantics. - -.. A type ``T`` belongs to the *set of value types* of ``X`` - if, for an object ``v`` of type ``T``, ``*a = v`` is valid. - - ** This appears to be a mutual recursion which ends up meaning - nothing. Kill the assertion column? - - Separate but related question: Is a writable iterator required - to have a meaningful value_type? If not, we need to use a - different name from ``v`` in this table -DWA +semantics. In addition, a model of *Writable Iterator* must include +in its documentation the *set of value types* that it allows for +output. +---------------------------------------------------------------------------------------------+ |Writable Iterator Requirements (in addition to CopyConstructible) | @@ -370,11 +362,12 @@ semantics. |``access_category::type`` |Convertible to | | | |``writable_iterator_tag``| | +--------------------------------------+-------------------------+----------------------------+ - |``*a = v`` | |.. ** pre: The type of ``v``| - | | | is in the set | - | | | of value types of ``X`` | + |``*a = o`` | | pre: The type of ``o`` | + | | | is in the set of | + | | | value types of ``X`` | +--------------------------------------+-------------------------+----------------------------+ + Swappable Iterators [lib.swappable.iterators] --------------------------------------------- From bb7ac6bd84bfe62a5c8555979af028aa87babeb6 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 28 Aug 2003 16:52:02 +0000 Subject: [PATCH 202/265] Moved to much cleaner system of using BOOST_TT_BROKEN_COMPILER_SPEC for handling vc6/7 deficiencies with iterator_traits. Fixed a bug in iterator_facade which was causing incomplete types to be passed through is_convertible. Reinstated libs/utility/iterator_traits_test.cpp [SVN r19840] --- include/boost/iterator/iterator_facade.hpp | 10 +++- test/Jamfile | 1 + test/concept_tests.cpp | 2 - test/filter_iterator_test.cpp | 12 ++--- test/indirect_iterator_test.cpp | 59 +++------------------- test/iterator_adaptor_cc.cpp | 11 ---- test/iterator_adaptor_test.cpp | 8 +++ test/reverse_iterator_test.cpp | 15 +----- test/transform_iterator_test.cpp | 17 ++----- test/unit_tests.cpp | 9 ++-- 10 files changed, 39 insertions(+), 105 deletions(-) diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index 9ab70ad..3bdb040 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -37,9 +37,17 @@ namespace boost // explicitly in order to specify that the default should be used. struct use_default; +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // the incompleteness of use_default causes massive problems for + // is_convertible (naturally). This workaround is fortunately not + // needed for vc6/vc7. + template + struct is_convertible + : mpl::false_ {}; +# endif + namespace detail { - // // enable if for use in operator implementation. // diff --git a/test/Jamfile b/test/Jamfile index a4672aa..46ff34e 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -39,5 +39,6 @@ test-suite iterator [ run ../../utility/projection_iterator_example.cpp ] [ run ../../utility/reverse_iterator_example.cpp ] [ run ../../utility/transform_iterator_example.cpp ] + [ run ../../utility/iterator_traits_test.cpp ] ; diff --git a/test/concept_tests.cpp b/test/concept_tests.cpp index 64d2c05..5370f76 100644 --- a/test/concept_tests.cpp +++ b/test/concept_tests.cpp @@ -149,7 +149,6 @@ main() test = static_assert_same::value; (void)test; -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) boost::function_requires< boost_concepts::WritableLvalueIteratorConcept >(); boost::function_requires< @@ -159,7 +158,6 @@ main() boost_concepts::ReadableLvalueIteratorConcept >(); boost::function_requires< boost_concepts::RandomAccessTraversalConcept >(); -#endif boost::function_requires< boost_concepts::WritableLvalueIteratorConcept >(); diff --git a/test/filter_iterator_test.cpp b/test/filter_iterator_test.cpp index 16cd894..a00af95 100644 --- a/test/filter_iterator_test.cpp +++ b/test/filter_iterator_test.cpp @@ -7,12 +7,14 @@ #include #include #include +#include #include #include using boost::dummyT; - +BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT) + struct one_or_four { bool operator()(dummyT x) const @@ -21,14 +23,6 @@ struct one_or_four } }; -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -namespace boost { namespace detail -{ - template<> struct iterator_traits - : ptr_iter_traits {}; -}} -#endif - template struct undefined; // Test filter iterator diff --git a/test/indirect_iterator_test.cpp b/test/indirect_iterator_test.cpp index 43fa4ae..3f28948 100644 --- a/test/indirect_iterator_test.cpp +++ b/test/indirect_iterator_test.cpp @@ -26,6 +26,8 @@ #include #include +#include +#include #include #include @@ -36,35 +38,19 @@ // std container random-access iterators don't support mutable/const // interoperability (but may support const/mutable interop). -# define NO_MUTABLE_CONST_STD_DEQUE_ITERATOR_INTEROPERABILITY # define NO_MUTABLE_CONST_STD_SET_ITERATOR_INTEROPERABILITY #endif -#if defined(BOOST_MSVC_STD_ITERATOR) \ -|| defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - -// No working iterator_traits implementation, so we must use deque -# define RA_CONTAINER std::deque -# include - -# ifdef NO_MUTABLE_CONST_STD_DEQUE_ITERATOR_INTEROPERABILITY -# define NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY -# endif - -#else - -# define RA_CONTAINER std::vector -# include - -#endif struct my_iterator_tag : public std::random_access_iterator_tag { }; using boost::dummyT; - -typedef RA_CONTAINER storage; -typedef RA_CONTAINER pointer_ra_container; +BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT) +BOOST_TT_BROKEN_COMPILER_SPEC(boost::shared_ptr) + +typedef std::vector storage; +typedef std::vector pointer_ra_container; typedef std::set iterator_set; template @@ -78,36 +64,8 @@ struct indirect_iterator_pair_generator > const_iterator; }; -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -namespace boost { namespace detail -{ - template<> struct iterator_traits - : ptr_iter_traits {}; - - template<> struct iterator_traits - : ptr_iter_traits {}; - - template<> struct iterator_traits - : ptr_iter_traits {}; - - template<> struct iterator_traits - : ptr_iter_traits {}; - - template<> struct iterator_traits - : ptr_iter_traits {}; - - template<> struct iterator_traits - : ptr_iter_traits {}; - - template<> struct iterator_traits - : ptr_iter_traits {}; -}} -#endif - - void more_indirect_iterator_tests() { -# if 0 storage store(1000); std::generate(store.begin(), store.end(), rand); @@ -177,7 +135,6 @@ void more_indirect_iterator_tests() boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]); assert(std::equal(db, de, store.begin())); -#endif } int @@ -187,7 +144,7 @@ main() dummyT(3), dummyT(4), dummyT(5) }; const int N = sizeof(array)/sizeof(dummyT); - typedef RA_CONTAINER > shared_t; + typedef std::vector > shared_t; shared_t shared; // Concept checks diff --git a/test/iterator_adaptor_cc.cpp b/test/iterator_adaptor_cc.cpp index e08eabd..ba7e79b 100644 --- a/test/iterator_adaptor_cc.cpp +++ b/test/iterator_adaptor_cc.cpp @@ -4,17 +4,6 @@ #include #include -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -namespace boost { namespace detail -{ - template<> struct iterator_traits - : ptr_iter_traits {}; - - template<> struct iterator_traits - : ptr_iter_traits {}; -}} -#endif - int main() { { diff --git a/test/iterator_adaptor_test.cpp b/test/iterator_adaptor_test.cpp index 5c471d7..f59fc6e 100644 --- a/test/iterator_adaptor_test.cpp +++ b/test/iterator_adaptor_test.cpp @@ -16,6 +16,8 @@ #include #include +# include + #include #include #include @@ -28,6 +30,12 @@ struct my_iterator_tag : public std::random_access_iterator_tag { }; using boost::dummyT; +#if BOOST_WORKAROUND(BOOST_MSVC, == 1300) +typedef std::pair intpair; +BOOST_TT_BROKEN_COMPILER_SPEC(intpair) +BOOST_TT_BROKEN_COMPILER_SPEC(dummyT) +#endif + struct mult_functor { typedef int result_type; diff --git a/test/reverse_iterator_test.cpp b/test/reverse_iterator_test.cpp index 0137d97..cb069cd 100644 --- a/test/reverse_iterator_test.cpp +++ b/test/reverse_iterator_test.cpp @@ -11,19 +11,8 @@ using boost::dummyT; -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -namespace boost -{ - namespace detail - { - template<> struct iterator_traits - : ptr_iter_traits {}; - template<> struct iterator_traits - : ptr_iter_traits {}; - } -} -#endif - +BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT) + // Test reverse iterator int main() { diff --git a/test/transform_iterator_test.cpp b/test/transform_iterator_test.cpp index 8eb5121..fcbb3d9 100644 --- a/test/transform_iterator_test.cpp +++ b/test/transform_iterator_test.cpp @@ -24,21 +24,14 @@ #include +#if BOOST_WORKAROUND(BOOST_MSVC, == 1300) +typedef std::pair intpair; +BOOST_TT_BROKEN_COMPILER_SPEC(intpair) +#endif + #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION namespace boost { namespace detail { - template<> struct iterator_traits - : ptr_iter_traits {}; - - template<> struct iterator_traits*> - : ptr_iter_traits > {}; - - template<> struct iterator_traits - : ptr_iter_traits {}; - - template<> struct iterator_traits const*> - : ptr_iter_traits, std::pair const> {}; - template<> struct function_object_result { typedef int type; diff --git a/test/unit_tests.cpp b/test/unit_tests.cpp index 622d9a7..ed6c279 100644 --- a/test/unit_tests.cpp +++ b/test/unit_tests.cpp @@ -6,15 +6,12 @@ #include #include #include "static_assert_same.hpp" +#include + struct X { int a; }; -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -namespace boost { namespace detail { -template<> struct iterator_traits - : ptr_iter_traits {}; -}} -#endif +BOOST_TT_BROKEN_COMPILER_SPEC(X) struct Xiter : boost::iterator_adaptor { From f801c39a594dc3fd06b2921ea91d910e0415659d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 28 Aug 2003 20:18:51 +0000 Subject: [PATCH 203/265] Removed code-breaking change from boost/detail/iterator.hpp and corresponding workarounds from tests. Added permutation_iterator_test to the suite after fixing it up -- it was riddled with bugs! [SVN r19841] --- test/Jamfile | 2 ++ test/iterator_adaptor_test.cpp | 7 ----- test/permutation_iterator_test.cpp | 49 ++++++++++-------------------- test/transform_iterator_test.cpp | 5 --- 4 files changed, 18 insertions(+), 45 deletions(-) diff --git a/test/Jamfile b/test/Jamfile index 46ff34e..400126f 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -30,6 +30,8 @@ test-suite iterator [ run filter_iterator_test.cpp ] [ run reverse_iterator_test.cpp ] [ run counting_iterator_test.cpp ] + [ run permutation_iterator_test.cpp : : : # on + ] [ run ../../utility/iterator_adaptor_examples.cpp ] [ run ../../utility/counting_iterator_example.cpp ] diff --git a/test/iterator_adaptor_test.cpp b/test/iterator_adaptor_test.cpp index f59fc6e..79b9001 100644 --- a/test/iterator_adaptor_test.cpp +++ b/test/iterator_adaptor_test.cpp @@ -30,13 +30,6 @@ struct my_iterator_tag : public std::random_access_iterator_tag { }; using boost::dummyT; -#if BOOST_WORKAROUND(BOOST_MSVC, == 1300) -typedef std::pair intpair; -BOOST_TT_BROKEN_COMPILER_SPEC(intpair) -BOOST_TT_BROKEN_COMPILER_SPEC(dummyT) -#endif - - struct mult_functor { typedef int result_type; typedef int argument_type; diff --git a/test/permutation_iterator_test.cpp b/test/permutation_iterator_test.cpp index 0b05ba2..f409698 100644 --- a/test/permutation_iterator_test.cpp +++ b/test/permutation_iterator_test.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -23,8 +24,9 @@ void permutation_test() typedef std::list< int > index_type; const int element_range_size = 10; - const int index_size = 4; + const int index_size = 7; + BOOST_STATIC_ASSERT(index_size <= element_range_size); element_range_type elements( element_range_size ); for( element_range_type::iterator el_it = elements.begin(); el_it != elements.end(); ++el_it ) { *el_it = std::distance(elements.begin(), el_it); } @@ -34,57 +36,42 @@ void permutation_test() { *i_it = element_range_size - index_size + std::distance(indices.begin(), i_it); } std::reverse( indices.begin(), indices.end() ); -#ifdef BOOST_MSVC - - typedef boost::permutation_iterator< element_range_type::iterator - , index_type::iterator - , boost::use_default - , boost::use_default - , element_range_type::reference > permutation_type; - - permutation_type begin( elements.begin(), indices.begin() ); - permutation_type it = begin; - permutation_type end( elements.begin(), indices.end() ); - -#else - typedef boost::permutation_iterator< element_range_type::iterator, index_type::iterator > permutation_type; permutation_type begin = boost::make_permutation_iterator( elements.begin(), indices.begin() ); permutation_type it = begin; permutation_type end = boost::make_permutation_iterator( elements.begin(), indices.end() ); -#endif - BOOST_CHECK( it == begin ); BOOST_CHECK( it != end ); BOOST_CHECK( std::distance( begin, end ) == index_size ); - for( index_type::iterator i_it = indices.begin(); it != end; ++i_it, ++it ) + for( index_type::iterator i_it1 = indices.begin(); it != end; ++i_it1, ++it ) { - BOOST_CHECK( *it == elements[ *i_it ] ); + BOOST_CHECK( *it == elements[ *i_it1 ] ); } it = begin; - for( int i = 0; i < index_size ; i+=2, it+=2 ) + for( int i1 = 0; i1 < index_size - 1 ; i1+=2, it+=2 ) { - index_type::iterator i_it = indices.begin(); std::advance( i_it, i ); - BOOST_CHECK( *it == elements[ *i_it ] ); + index_type::iterator i_it2 = indices.begin(); + std::advance( i_it2, i1 ); + BOOST_CHECK( *it == elements[ *i_it2 ] ); } it = begin + (index_size); - BOOST_CHECK( it != begin ); - for( index_type::iterator i_it = --indices.end(); it-- != begin; --i_it ) + for( index_type::iterator i_it3 = indices.end(); it != begin; ) { - BOOST_CHECK( *it == elements[ *i_it ] ); + BOOST_CHECK( *--it == elements[ *--i_it3 ] ); } - it = begin + (index_size - 1); - for( int i = 0; i < index_size; i+=2, it-=2 ) + it = begin + index_size; + for( int i2 = 0; i2 < index_size - 1; i2+=2, --it ) { - index_type::iterator i_it = --indices.end(); std::advance( i_it, -i ); - BOOST_CHECK( *it == elements[ *i_it ] ); + index_type::iterator i_it4 = --indices.end(); + std::advance( i_it4, -i2 ); + BOOST_CHECK( *--it == elements[ *i_it4 ] ); } } @@ -93,9 +80,5 @@ void permutation_test() int test_main(int, char *[]) { permutation_test(); - - bool error_on_purpose = false; - //BOOST_CHECK( error_on_purpose ); - return 0; } diff --git a/test/transform_iterator_test.cpp b/test/transform_iterator_test.cpp index fcbb3d9..cc73846 100644 --- a/test/transform_iterator_test.cpp +++ b/test/transform_iterator_test.cpp @@ -24,11 +24,6 @@ #include -#if BOOST_WORKAROUND(BOOST_MSVC, == 1300) -typedef std::pair intpair; -BOOST_TT_BROKEN_COMPILER_SPEC(intpair) -#endif - #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION namespace boost { namespace detail { From 2b7ed5f7a86c0f7a437f4dab03f42483fc06f02d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 4 Sep 2003 21:15:38 +0000 Subject: [PATCH 204/265] Added traversal_category and access_category specializations for MPL lambda support [SVN r19921] --- .../boost/iterator/iterator_categories.hpp | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/include/boost/iterator/iterator_categories.hpp b/include/boost/iterator/iterator_categories.hpp index 23724b1..cbf1f2f 100644 --- a/include/boost/iterator/iterator_categories.hpp +++ b/include/boost/iterator/iterator_categories.hpp @@ -29,6 +29,9 @@ #include #include #include +#ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT +# include +#endif #include @@ -340,6 +343,29 @@ namespace boost { { }; +# ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT + // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work + // out well. Instantiating the nested apply template also + // requires instantiating iterator_traits on the + // placeholder. Instead we just specialize it as a metafunction + // class. +template <> + struct access_category + { + template + struct apply : access_category + {}; + }; + + template <> + struct traversal_category + { + template + struct apply : traversal_category + {}; + }; +# endif + # if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) template From abafc5d1be353d65e3f2f4719952482d6cfe449f Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 6 Sep 2003 14:24:01 +0000 Subject: [PATCH 205/265] Added missing lambda support for broken compilers [SVN r19936] --- include/boost/iterator/detail/categories.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/boost/iterator/detail/categories.hpp b/include/boost/iterator/detail/categories.hpp index 2e53fb6..5a2e7eb 100644 --- a/include/boost/iterator/detail/categories.hpp +++ b/include/boost/iterator/detail/categories.hpp @@ -21,6 +21,7 @@ # include # include # include +# include # include @@ -322,7 +323,9 @@ namespace boost , error_type > > - {}; + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2)) + }; # if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // Deal with ETI From 3f494098438924520bd15710b30d478a766783e6 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 8 Sep 2003 17:38:49 +0000 Subject: [PATCH 206/265] Use the import rule [SVN r19968] --- test/Jamfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Jamfile b/test/Jamfile index 400126f..a7bb4e3 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -6,8 +6,7 @@ subproject libs/iterator/test ; -SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; -include testing.jam ; +import testing ; test-suite iterator : @@ -32,6 +31,7 @@ test-suite iterator [ run counting_iterator_test.cpp ] [ run permutation_iterator_test.cpp : : : # on ] + [ run zip_iterator_test.cpp ] [ run ../../utility/iterator_adaptor_examples.cpp ] [ run ../../utility/counting_iterator_example.cpp ] From 2c89e2b15a43a619965b477e439188f13f417bd1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 9 Sep 2003 03:22:50 +0000 Subject: [PATCH 207/265] initial commit [SVN r19978] --- include/boost/iterator/zip_iterator.hpp | 680 ++++++++++++++++ test/zip_iterator_test.cpp | 982 ++++++++++++++++++++++++ 2 files changed, 1662 insertions(+) create mode 100755 include/boost/iterator/zip_iterator.hpp create mode 100755 test/zip_iterator_test.cpp diff --git a/include/boost/iterator/zip_iterator.hpp b/include/boost/iterator/zip_iterator.hpp new file mode 100755 index 0000000..7d7c41e --- /dev/null +++ b/include/boost/iterator/zip_iterator.hpp @@ -0,0 +1,680 @@ +// (C) Copyright David Abrahams and Thomas Becker 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. +// +// Compilers Tested: +// ================= +// Metrowerks Codewarrior Pro 7.2, 8.3 +// gcc 2.95.3 +// gcc 3.2 +// Microsoft VC 6sp5 (test fails due to some compiler bug) +// Microsoft VC 7 (works) +// Microsoft VC 7.1 +// Intel 5 +// Intel 6 +// Intel 7.1 +// Intel 8 +// Borland 5.5.1 (broken due to lack of support from Boost.Tuples) + +#ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_ + +#include +#include +#include +#include +#include // for enable_if_convertible +#include + +#include + +#if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407) +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + // Zip iterator forward declaration for zip_iterator_base + template + class zip_iterator; + + // One important design goal of the zip_iterator is to isolate all + // functionality whose implementation relies on the current tuple + // implementation. This goal has been achieved as follows: Inside + // the namespace detail there is a namespace tuple_impl_specific. + // This namespace encapsulates all functionality that is specific + // to the current Boost tuple implementation. More precisely, the + // namespace tuple_impl_specific provides the following tuple + // algorithms and meta-algorithms for the current Boost tuple + // implementation: + // + // tuple_meta_transform + // tuple_meta_accumulate + // tuple_transform + // tuple_for_each + // + // If the tuple implementation changes, all that needs to be + // replaced is the implementation of these four (meta-)algorithms. + // + // Unfortunately, some compilers, including Metrowerks Codewarrior + // 4.2.5.766 and gcc 3.3, were unable to handle the template + // code involved (Metrowerks: internal compiler error, gcc 3.3: + // segmentation fault). Therefore, rather regrettably, for those + // compilers, the encapsulation of the tuple implementation- + // specific code is not nearly as nice and clean as it should be. + // In order to emphasize this point, I have provided the entire + // namespace detail in this file twice: the first version is the + // clean one with the nice encapsulation, the second one is the + // dirty one. + // + + namespace detail + { + + // Functors to be used with tuple algorithms + // + template + class advance_iterator + { + public: + advance_iterator(DiffType step) : m_step(step) {} + + template + void operator()(Iterator& it) const + { it += m_step; } + + private: + DiffType m_step; + }; + // + struct increment_iterator + { + template + void operator()(Iterator& it) + { ++it; } + }; + // + struct decrement_iterator + { + template + void operator()(Iterator& it) + { --it; } + }; + // + struct dereference_iterator + { + template + struct apply + { +#if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + typedef typename + std::iterator_traits< + typename boost::remove_cv::type + >::reference + type; +#else + typedef typename + std::iterator_traits::reference + type; +#endif + }; + + template + typename apply::type operator()(Iterator& it) + { return *it; } + }; + + + // The namespace tuple_impl_specific provides two meta- + // algorithms and two algorithms for tuples. + // + namespace tuple_impl_specific + { + // Meta-transform algorithm for tuples + // + template + struct tuple_meta_transform; + + template + struct tuple_meta_transform_impl + { + typedef tuples::cons< + typename mpl::apply1< + typename mpl::lambda::type + , typename Tuple::head_type + >::type + , typename tuple_meta_transform< + typename Tuple::tail_type + , UnaryMetaFun + >::type + > type; + }; + + template + struct tuple_meta_transform + : mpl::apply_if< + boost::is_same + , mpl::identity + , tuple_meta_transform_impl + > + { + }; + + // Meta-accumulate algorithm for tuples. Note: The template + // parameter StartType corresponds to the initial value in + // ordinary accumulation. + // + template + struct tuple_meta_accumulate; + + template< + typename Tuple + , class BinaryMetaFun + , typename StartType + > + struct tuple_meta_accumulate_impl + { + typedef typename mpl::apply2< + typename mpl::lambda::type + , typename Tuple::head_type + , typename tuple_meta_accumulate< + typename Tuple::tail_type + , BinaryMetaFun + , StartType + >::type + >::type type; + }; + + template< + typename Tuple + , class BinaryMetaFun + , typename StartType + > + struct tuple_meta_accumulate + : mpl::apply_if< +#if BOOST_WORKAROUND(BOOST_MSVC, == 1200) + mpl::or_< +#endif + boost::is_same +#if BOOST_WORKAROUND(BOOST_MSVC, == 1200) + , boost::is_same + > +#endif + , mpl::identity + , tuple_meta_accumulate_impl< + Tuple + , BinaryMetaFun + , StartType + > + > + { + }; + +#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ + || ( \ + BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, != 0) && defined(_MSC_VER) \ + ) +// Not sure why intel's partial ordering fails in this case, but I'm +// assuming int's an MSVC bug-compatibility feature. + +# define BOOST_TUPLE_ALGO_DISPATCH +# define BOOST_TUPLE_ALGO(algo) algo##_impl +# define BOOST_TUPLE_ALGO_TERMINATOR , int +# define BOOST_TUPLE_ALGO_RECURSE , ... +#else +# define BOOST_TUPLE_ALGO(algo) algo +# define BOOST_TUPLE_ALGO_TERMINATOR +# define BOOST_TUPLE_ALGO_RECURSE +#endif + + // transform algorithm for tuples. The template parameter Fun + // must be a unary functor which is also a unary metafunction + // class that computes its return type based on its argument + // type. For example: + // + // struct to_ptr + // { + // template + // struct apply + // { + // typedef Arg* type; + // } + // + // template + // Arg* operator()(Arg x); + // }; + template + tuples::null_type BOOST_TUPLE_ALGO(tuple_transform) + (tuples::null_type const&, Fun BOOST_TUPLE_ALGO_TERMINATOR) + { return tuples::null_type(); } + + template + typename tuple_meta_transform< + Tuple + , Fun + >::type + + BOOST_TUPLE_ALGO(tuple_transform)( + const Tuple& t, + Fun f + BOOST_TUPLE_ALGO_RECURSE + ) + { + typedef typename tuple_meta_transform< + typename Tuple::tail_type + , Fun + >::type transformed_tail_type; + + return tuples::cons< + typename mpl::apply1::type + , transformed_tail_type + >( + f(boost::tuples::get<0>(t)), + tuple_transform(t.get_tail(), f) + ); + } + +#ifdef BOOST_TUPLE_ALGO_DISPATCH + template + typename tuple_meta_transform< + Tuple + , Fun + >::type + + tuple_transform( + const Tuple& t, + Fun f + ) + { + return tuple_transform_impl(t, f, 1); + } +#endif + + // for_each algorithm for tuples. + // + template + Fun BOOST_TUPLE_ALGO(tuple_for_each)( + tuples::null_type + , Fun f BOOST_TUPLE_ALGO_TERMINATOR + ) + { return f; } + + + template + Fun BOOST_TUPLE_ALGO(tuple_for_each)( + Tuple& t + , Fun f BOOST_TUPLE_ALGO_RECURSE) + { + f( t.get_head() ); + return tuple_for_each(t.get_tail(), f); + } + +#ifdef BOOST_TUPLE_ALGO_DISPATCH + template + Fun + tuple_for_each( + Tuple& t, + Fun f + ) + { + return tuple_for_each_impl(t, f, 1); + } +#endif + + // Equality of tuples. NOTE: "==" for tuples currently (7/2003) + // has problems under some compilers, so I just do my own. + // No point in bringing in a bunch of #ifdefs here. This is + // going to go away with the next tuple implementation anyway. + // + bool tuple_equal(tuples::null_type, tuples::null_type) + { return true; } + + template + bool tuple_equal( + Tuple1 const& t1, + Tuple2 const& t2 + ) + { + return t1.get_head() == t2.get_head() && + tuple_equal(t1.get_tail(), t2.get_tail()); + } + } + // + // end namespace tuple_impl_specific + + template + struct iterator_reference + { + typedef typename iterator_traits::reference type; + }; + +#ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT + // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work + // out well. Instantiating the nested apply template also + // requires instantiating iterator_traits on the + // placeholder. Instead we just specialize it as a metafunction + // class. + template<> + struct iterator_reference + { + template + struct apply : iterator_reference {}; + }; +#endif + + // Metafunction to obtain the type of the tuple whose element types + // are the reference types of an iterator tuple. + // + template + struct tuple_of_references + : tuple_impl_specific::tuple_meta_transform< + IteratorTuple, + iterator_reference + > + { + }; + + // Metafunction to obtain the minimal traversal tag in a tuple + // of iterators. + // + template + struct minimum_traversal_category_in_iterator_tuple + { + typedef typename tuple_impl_specific::tuple_meta_transform< + IteratorTuple + , traversal_category + >::type tuple_of_traversal_tags; + + typedef typename tuple_impl_specific::tuple_meta_accumulate< + tuple_of_traversal_tags + , minimum_category + , random_access_traversal_tag + >::type type; + }; + +#if BOOST_WORKAROUND(BOOST_MSVC, == 1200) // ETI workaround + template <> + struct minimum_traversal_category_in_iterator_tuple + { + typedef int type; + }; +#endif + + template + struct iterator_is_readable + : is_tag< + readable_iterator_tag + , typename access_category::type + > + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(1, iterator_is_readable, (Iterator)) + }; + +# ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT + // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work + // out well. Instantiating the nested apply template also + // requires instantiating iterator_traits on the + // placeholder. Instead we just specialize it as a metafunction + // class. + template <> + struct iterator_is_readable + { + template + struct apply : iterator_is_readable + {}; + }; +# endif + + // We need to call tuple_meta_accumulate with mpl::and_ as the + // accumulating functor. To this end, we need to wrap it into + // a struct that has exactly two arguments (that is, template + // parameters) and not five, like mpl::and_ does. + // + template + struct and_with_two_args + : mpl::and_ + { + }; + +# ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT + // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work + // out well. In this case I think it's an MPL bug + template<> + struct and_with_two_args + { + template + struct apply : mpl::and_ + {}; + }; +# endif + + // Metafunction to assert that all iterators in a tuple are + // readable. + // + // Probably not worth it, IMO. Why not a writable zip_iterator + // anyway? -- dwa. + // + template + struct all_iterators_in_tuple_readable + { + + typedef typename tuple_impl_specific::tuple_meta_transform< + IteratorTuple, + iterator_is_readable + >::type tuple_of_readability_bools; + + typedef typename tuple_impl_specific::tuple_meta_accumulate< + tuple_of_readability_bools, + and_with_two_args + , mpl::bool_ + >::type type; + }; + + /////////////////////////////////////////////////////////////////// + // + // Class zip_iterator_base + // + // Builds and exposes the iterator facade type from which the zip + // iterator will be derived. + // + template + struct zip_iterator_base + { + private: +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + // seems to give vc7's parser fits, and vc6 needs help here too + BOOST_STATIC_ASSERT( + detail::all_iterators_in_tuple_readable< + IteratorTuple + >::type::value + ); +#endif + // Reference type is the type of the tuple obtained from the + // iterators' reference types. + typedef typename + detail::tuple_of_references::type reference; + + // Value type is the same as reference type. + typedef reference value_type; + + // Difference type is the first iterator's difference type + typedef typename iterator_traits< + typename tuples::element<0, IteratorTuple>::type + >::difference_type difference_type; + + // Traversal catetgory is the minimum traversal category in the + // iterator tuple. + typedef typename + detail::minimum_traversal_category_in_iterator_tuple< + IteratorTuple + >::type traversal_category; + + // Access category is readable_iterator_tag. It has been + // asserted that all iterators in the tuple are readable. + typedef readable_iterator_tag access_category; + + public: + + // The iterator facade type from which the zip iterator will + // be derived. + typedef iterator_facade< + zip_iterator, + value_type, + access_category, + traversal_category, + reference, + difference_type + > type; + }; + + template <> + struct zip_iterator_base + { + typedef int type; + }; + } + + ///////////////////////////////////////////////////////////////////// + // + // zip_iterator class definition + // + template + class zip_iterator : + public detail::zip_iterator_base::type + { + + // Typedef super_t as our base class. + typedef typename + detail::zip_iterator_base::type super_t; + + // iterator_core_access is the iterator's best friend. + friend class iterator_core_access; + + public: + + // Construction + // ============ + + // Default constructor + zip_iterator() { } + + // Constructor from iterator tuple + zip_iterator(IteratorTuple iterator_tuple) + : m_iterator_tuple(iterator_tuple) + { } + + // Copy constructor + template + zip_iterator( + const zip_iterator& other, + typename enable_if_convertible< + OtherIteratorTuple, + IteratorTuple + >::type* = 0 + ) : m_iterator_tuple(other.get_iterator_tuple()) + {} + + // Get method for the iterator tuple. + const IteratorTuple& get_iterator_tuple() const + { return m_iterator_tuple; } + + private: + + // Implementation of Iterator Operations + // ===================================== + + // Dereferencing returns a tuple built from the dereferenced + // iterators in the iterator tuple. + typename super_t::reference dereference() const + { + return detail::tuple_impl_specific::tuple_transform( + get_iterator_tuple(), + detail::dereference_iterator() + ); + } + + // Two zip iterators are equal if all iterators in the iterator + // tuple are equal. NOTE: It should be possible to implement this + // as + // + // return get_iterator_tuple() == other.get_iterator_tuple(); + // + // but equality of tuples currently (7/2003) does not compile + // under several compilers. No point in bringing in a bunch + // of #ifdefs here. + // + template + bool equal(const zip_iterator& other) const + { + return detail::tuple_impl_specific::tuple_equal( + get_iterator_tuple(), + other.get_iterator_tuple() + ); + } + + // Advancing a zip iterator means to advance all iterators in the + // iterator tuple. + void advance(typename super_t::difference_type n) + { + detail::tuple_impl_specific::tuple_for_each( + m_iterator_tuple, + detail::advance_iterator(n) + ); + } + // Incrementing a zip iterator means to increment all iterators in + // the iterator tuple. + void increment() + { + detail::tuple_impl_specific::tuple_for_each( + m_iterator_tuple, + detail::increment_iterator() + ); + } + + // Decrementing a zip iterator means to decrement all iterators in + // the iterator tuple. + void decrement() + { + detail::tuple_impl_specific::tuple_for_each( + m_iterator_tuple, + detail::decrement_iterator() + ); + } + + // Distance is calculated using the first iterator in the tuple. + template + typename super_t::difference_type distance_to( + const zip_iterator& other + ) const + { + return boost::tuples::get<0>(other.get_iterator_tuple()) - + boost::tuples::get<0>(this->get_iterator_tuple()); + } + + // Data Members + // ============ + + // The iterator tuple. + IteratorTuple m_iterator_tuple; + + }; + + // Make function for zip iterator + // + template + zip_iterator + make_zip_iterator(IteratorTuple t) + { return zip_iterator(t); } + +} + +#endif diff --git a/test/zip_iterator_test.cpp b/test/zip_iterator_test.cpp new file mode 100755 index 0000000..d6fcc2b --- /dev/null +++ b/test/zip_iterator_test.cpp @@ -0,0 +1,982 @@ +// (C) Copyright Dave Abrahams and Thomas Becker 2003. 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. +// + +// File: +// ===== +// zip_iterator_test_main.cpp + +// Author: +// ======= +// Thomas Becker + +// Created: +// ======== +// Jul 15, 2003 + +// Purpose: +// ======== +// Test driver for zip_iterator.hpp + +// Compilers Tested: +// ================= +// Metrowerks Codewarrior Pro 7.2, 8.3 +// gcc 2.95.3 +// gcc 3.2 +// Microsoft VC 6sp5 (test fails due to some compiler bug) +// Microsoft VC 7 (works) +// Microsoft VC 7.1 +// Intel 5 +// Intel 6 +// Intel 7.1 +// Intel 8 +// Borland 5.5.1 (broken due to lack of support from Boost.Tuples) + +///////////////////////////////////////////////////////////////////////////// +// +// Includes +// +///////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Uncomment to see static assert. +// #define PROVOKE_STATIC_ASSERT + +///////////////////////////////////////////////////////////////////////////// +// +// Fake iterator for testing zip iterator categories +// +///////////////////////////////////////////////////////////////////////////// + +class fake_writable_iterator +{ +public: + typedef int& reference; + typedef int value_type; + typedef int* pointer; + typedef ptrdiff_t difference_type; + typedef boost::iterator_tag< + boost::writable_iterator_tag, + boost::forward_traversal_tag + > iterator_category; +}; + +///////////////////////////////////////////////////////////////////////////// +// +// Das Main Funktion +// +///////////////////////////////////////////////////////////////////////////// + +int main( void ) +{ + + std::cout << "\n" + << "***********************************************\n" + << "* *\n" + << "* Test driver for boost::zip_iterator *\n" + << "* Copyright Thomas Becker 2003 *\n" + << "* *\n" + << "***********************************************\n\n" + << std::flush; + + size_t num_successful_tests = 0; + size_t num_failed_tests = 0; + + ///////////////////////////////////////////////////////////////////////////// + // + // Make sure tuples are supported + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Basic tuple support: " + << std::flush; + + typedef boost::tuples::tuple mytuple; + mytuple t1; + boost::tuples::get<0>(t1) = 42; + boost::tuples::get<1>(t1) = 42.1; + + if( 2 == boost::tuples::length::value && + 42 == boost::tuples::get<0>(t1) && + 42.1 == boost::tuples::get<1>(t1) + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Make sure iterator adaptor is supported + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Basic iterator adaptor support: " + << std::flush; + + std::set s; + s.insert(42); + s.insert(43); + s.insert(44); + + typedef boost::transform_iterator< + std::binder1st >, + std::set::iterator + > + add_seven_iterator; + + typedef boost::transform_iterator< + std::binder1st >, + std::set::const_iterator + > + const_add_seven_iterator; + + add_seven_iterator set_run(s.begin(), std::bind1st(std::plus(), 7)); + add_seven_iterator set_end(s.end(), std::bind1st(std::plus(), 7)); + + const_add_seven_iterator const_set_run(s.begin(), std::bind1st(std::plus(), 7)); +// set_run = const_set_run; // Error: can't convert from const to non-const + const_set_run = set_run; + + if( 49 == *set_run && + 50 == *++set_run && + 51 == *++set_run && + set_end == ++set_run && + 49 == *const_set_run && + 50 == *++const_set_run && + 51 == *++const_set_run && + set_end == ++const_set_run + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator construction and dereferencing + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator construction and dereferencing: " + << std::flush; + + std::vector vect1(3); + vect1[0] = 42.; + vect1[1] = 43.; + vect1[2] = 44.; + + std::set intset; + intset.insert(52); + intset.insert(53); + intset.insert(54); + // + + boost::zip_iterator< + boost::tuples::tuple< + std::set::iterator + , std::vector::iterator + > + > + zip_it_mixed( + boost::make_tuple( + intset.begin() + , vect1.begin() + ) + ); + + boost::tuples::tuple val_tuple( + *zip_it_mixed); + + boost::tuples::tuple ref_tuple( + *zip_it_mixed); + + double dblOldVal = boost::tuples::get<1>(ref_tuple); + boost::tuples::get<1>(ref_tuple) -= 41.; + + if( 52 == boost::tuples::get<0>(val_tuple) && + 42. == boost::tuples::get<1>(val_tuple) && + 52 == boost::tuples::get<0>(ref_tuple) && + 1. == boost::tuples::get<1>(ref_tuple) && + 1. == *vect1.begin() + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + // Undo change to vect1 + boost::tuples::get<1>(ref_tuple) = dblOldVal; + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator with 12 components + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterators with 12 components: " + << std::flush; + + // Declare 12 containers + // + std::list li1; + li1.push_back(1); + std::set se1; + se1.insert(2); + std::vector ve1; + ve1.push_back(3); + // + std::list li2; + li2.push_back(4); + std::set se2; + se2.insert(5); + std::vector ve2; + ve2.push_back(6); + // + std::list li3; + li3.push_back(7); + std::set se3; + se3.insert(8); + std::vector ve3; + ve3.push_back(9); + // + std::list li4; + li4.push_back(10); + std::set se4; + se4.insert(11); + std::vector ve4; + ve4.push_back(12); + + // typedefs for cons lists of iterators. + typedef boost::tuples::cons< + std::set::iterator, + boost::tuples::tuple< + std::vector::iterator, + std::list::iterator, + std::set::iterator, + std::vector::iterator, + std::list::iterator, + std::set::iterator, + std::vector::iterator, + std::list::iterator, + std::set::iterator, + std::vector::const_iterator + >::inherited + > cons_11_its_type; + // + typedef boost::tuples::cons< + std::list::const_iterator, + cons_11_its_type + > cons_12_its_type; + + // typedefs for cons lists for dereferencing the zip iterator + // made from the cons list above. + typedef boost::tuples::cons< + const int&, + boost::tuples::tuple< + int&, + int&, + const int&, + int&, + int&, + const int&, + int&, + int&, + const int&, + const int& + >::inherited + > cons_11_refs_type; + // + typedef boost::tuples::cons< + const int&, + cons_11_refs_type + > cons_12_refs_type; + + // typedef for zip iterator with 12 elements + typedef boost::zip_iterator zip_it_12_type; + + // Declare a 12-element zip iterator. + zip_it_12_type zip_it_12( + cons_12_its_type( + li1.begin(), + cons_11_its_type( + se1.begin(), + boost::make_tuple( + ve1.begin(), + li2.begin(), + se2.begin(), + ve2.begin(), + li3.begin(), + se3.begin(), + ve3.begin(), + li4.begin(), + se4.begin(), + ve4.begin() + ) + ) + ) + ); + + // Dereference, mess with the result a little. + cons_12_refs_type zip_it_12_dereferenced(*zip_it_12); + boost::tuples::get<9>(zip_it_12_dereferenced) = 42; + + // Make a copy and move it a little to force some instantiations. + zip_it_12_type zip_it_12_copy(zip_it_12); + ++zip_it_12_copy; + + if( boost::tuples::get<11>(zip_it_12.get_iterator_tuple()) == ve4.begin() && + boost::tuples::get<11>(zip_it_12_copy.get_iterator_tuple()) == ve4.end() && + 1 == boost::tuples::get<0>(zip_it_12_dereferenced) && + 12 == boost::tuples::get<11>(zip_it_12_dereferenced) && + 42 == *(li4.begin()) + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator incrementing and dereferencing + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator ++ and *: " + << std::flush; + + std::vector vect2(3); + vect2[0] = 2.2; + vect2[1] = 3.3; + vect2[2] = 4.4; + + boost::zip_iterator< + boost::tuples::tuple< + std::vector::const_iterator, + std::vector::const_iterator + > + > + zip_it_begin( + boost::make_tuple( + vect1.begin(), + vect2.begin() + ) + ); + + boost::zip_iterator< + boost::tuples::tuple< + std::vector::const_iterator, + std::vector::const_iterator + > + > + zip_it_run( + boost::make_tuple( + vect1.begin(), + vect2.begin() + ) + ); + + boost::zip_iterator< + boost::tuples::tuple< + std::vector::const_iterator, + std::vector::const_iterator + > + > + zip_it_end( + boost::make_tuple( + vect1.end(), + vect2.end() + ) + ); + + if( zip_it_run == zip_it_begin && + 42. == boost::tuples::get<0>(*zip_it_run) && + 2.2 == boost::tuples::get<1>(*zip_it_run) && + 43. == boost::tuples::get<0>(*(++zip_it_run)) && + 3.3 == boost::tuples::get<1>(*zip_it_run) && + 44. == boost::tuples::get<0>(*(++zip_it_run)) && + 4.4 == boost::tuples::get<1>(*zip_it_run) && + zip_it_end == ++zip_it_run + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator decrementing and dereferencing + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator -- and *: " + << std::flush; + + if( zip_it_run == zip_it_end && + zip_it_end == zip_it_run-- && + 44. == boost::tuples::get<0>(*zip_it_run) && + 4.4 == boost::tuples::get<1>(*zip_it_run) && + 43. == boost::tuples::get<0>(*(--zip_it_run)) && + 3.3 == boost::tuples::get<1>(*zip_it_run) && + 42. == boost::tuples::get<0>(*(--zip_it_run)) && + 2.2 == boost::tuples::get<1>(*zip_it_run) && + zip_it_begin == zip_it_run + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator copy construction and equality + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator copy construction and equality: " + << std::flush; + + boost::zip_iterator< + boost::tuples::tuple< + std::vector::const_iterator, + std::vector::const_iterator + > + > zip_it_run_copy(zip_it_run); + + if(zip_it_run == zip_it_run && zip_it_run == zip_it_run_copy) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator inequality + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator inequality: " + << std::flush; + + if(!(zip_it_run != zip_it_run_copy) && zip_it_run != ++zip_it_run_copy) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator less than + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator less than: " + << std::flush; + + // Note: zip_it_run_copy == zip_it_run + 1 + // + if( zip_it_run < zip_it_run_copy && + !( zip_it_run < --zip_it_run_copy) && + zip_it_run == zip_it_run_copy + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator less than or equal + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "zip iterator less than or equal: " + << std::flush; + + // Note: zip_it_run_copy == zip_it_run + // + ++zip_it_run; + zip_it_run_copy += 2; + + if( zip_it_run <= zip_it_run_copy && + zip_it_run <= --zip_it_run_copy && + !( zip_it_run <= --zip_it_run_copy) && + zip_it_run <= zip_it_run + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator greater than + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator greater than: " + << std::flush; + + // Note: zip_it_run_copy == zip_it_run - 1 + // + if( zip_it_run > zip_it_run_copy && + !( zip_it_run > ++zip_it_run_copy) && + zip_it_run == zip_it_run_copy + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator greater than or equal + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator greater than or equal: " + << std::flush; + + ++zip_it_run; + + // Note: zip_it_run == zip_it_run_copy + 1 + // + if( zip_it_run >= zip_it_run_copy && + --zip_it_run >= zip_it_run_copy && + ! (zip_it_run >= ++zip_it_run_copy) + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator + int + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator + int: " + << std::flush; + + // Note: zip_it_run == zip_it_run_copy - 1 + // + zip_it_run = zip_it_run + 2; + ++zip_it_run_copy; + + if( zip_it_run == zip_it_run_copy && zip_it_run == zip_it_begin + 3 ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator - int + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator - int: " + << std::flush; + + // Note: zip_it_run == zip_it_run_copy, and both are at end position + // + zip_it_run = zip_it_run - 2; + --zip_it_run_copy; + --zip_it_run_copy; + + if( zip_it_run == zip_it_run_copy && (zip_it_run - 1) == zip_it_begin ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator += + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator +=: " + << std::flush; + + // Note: zip_it_run == zip_it_run_copy, and both are at begin + 1 + // + zip_it_run += 2; + if( zip_it_run == zip_it_begin + 3 ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator -= + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator -=: " + << std::flush; + + // Note: zip_it_run is at end position, zip_it_run_copy is at + // begin plus one. + // + zip_it_run -= 2; + if( zip_it_run == zip_it_run_copy ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator getting member iterators + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator member iterators: " + << std::flush; + + // Note: zip_it_run and zip_it_run_copy are both at + // begin plus one. + // + if( boost::tuples::get<0>(zip_it_run.get_iterator_tuple()) == vect1.begin() + 1 && + boost::tuples::get<1>(zip_it_run.get_iterator_tuple()) == vect2.begin() + 1 + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Making zip iterators + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Making zip iterators: " + << std::flush; + + std::vector > + vect_of_tuples(3); + + std::copy( + boost::make_zip_iterator( + boost::make_tuple( + vect1.begin(), + vect2.begin() + ) + ), + boost::make_zip_iterator( + boost::make_tuple( + vect1.end(), + vect2.end() + ) + ), + vect_of_tuples.begin() + ); + + if( 42. == boost::tuples::get<0>(*vect_of_tuples.begin()) && + 2.2 == boost::tuples::get<1>(*vect_of_tuples.begin()) && + 43. == boost::tuples::get<0>(*(vect_of_tuples.begin() + 1)) && + 3.3 == boost::tuples::get<1>(*(vect_of_tuples.begin() + 1)) && + 44. == boost::tuples::get<0>(*(vect_of_tuples.begin() + 2)) && + 4.4 == boost::tuples::get<1>(*(vect_of_tuples.begin() + 2)) + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator non-const --> const conversion + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator non-const to const conversion: " + << std::flush; + + boost::zip_iterator< + boost::tuples::tuple< + std::set::const_iterator, + std::vector::const_iterator + > + > + zip_it_const( + boost::make_tuple( + intset.begin(), + vect2.begin() + ) + ); + // + boost::zip_iterator< + boost::tuples::tuple< + std::set::iterator, + std::vector::const_iterator + > + > + zip_it_half_const( + boost::make_tuple( + intset.begin(), + vect2.begin() + ) + ); + // + boost::zip_iterator< + boost::tuples::tuple< + std::set::iterator, + std::vector::iterator + > + > + zip_it_non_const( + boost::make_tuple( + intset.begin(), + vect2.begin() + ) + ); + + zip_it_half_const = ++zip_it_non_const; + zip_it_const = zip_it_half_const; + ++zip_it_const; +// zip_it_non_const = ++zip_it_const; // Error: can't convert from const to non-const + + if( 54 == boost::tuples::get<0>(*zip_it_const) && + 4.4 == boost::tuples::get<1>(*zip_it_const) && + 53 == boost::tuples::get<0>(*zip_it_half_const) && + 3.3 == boost::tuples::get<1>(*zip_it_half_const) + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator categories + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator categories: " + << std::flush; + + // The big iterator of the previous test has vector, list, and set iterators. + // Therefore, it must be bidirectional, but not random access. + bool bBigItIsBidirectionalIterator = boost::is_same< + boost::bidirectional_traversal_tag, + boost::traversal_category::type + >::value; + // + bool bBigItIsRandomAccessIterator = boost::is_same< + boost::random_access_traversal_tag, + boost::traversal_category::type + >::value; + // + bool bBigItIsReadableIterator = boost::is_same< + boost::readable_iterator_tag, + boost::access_category::type + >::value; + // + bool bBigItIsReadableLValueIterator = boost::is_same< + boost::readable_lvalue_iterator_tag, + boost::access_category::type + >::value; + + // A combining iterator with all vector iterators must have random access + // traversal. + // + typedef boost::zip_iterator< + boost::tuples::tuple< + std::vector::const_iterator, + std::vector::const_iterator + > + > all_vects_type; + + bool bAllVectsIsRandomAccessIterator = boost::is_same< + boost::random_access_traversal_tag, + boost::traversal_category::type + >::value; + // + bool bAllVectsIsReadableIterator = boost::is_same< + boost::readable_iterator_tag, + boost::access_category::type + >::value; + // + bool bAllVectsIsReadableLValueIterator = boost::is_same< + boost::readable_lvalue_iterator_tag, + boost::access_category::type + >::value; + + // Test if the meta function all_iterators_readable, which is used + // for compile-time asserting, works. + // + bool bAllIteratorsReadable1 = + boost::detail::all_iterators_in_tuple_readable< + boost::tuples::tuple< + std::vector::const_iterator, + std::set::iterator + > + >::type::value; + + bool bAllIteratorsReadable2 = + boost::detail::all_iterators_in_tuple_readable< + boost::tuples::tuple< + std::vector::const_iterator, + fake_writable_iterator, + std::set::iterator + > + >::type::value; + + // Compile-time assert because of non-readable iterator. + // +#ifdef PROVOKE_STATIC_ASSERT + typedef boost::zip_iterator< + boost::tuples::tuple< + fake_writable_iterator + > + >no_compile_type; + + no_compile_type no_compile; +#endif + + // The big test. + if( bBigItIsBidirectionalIterator && + ! bBigItIsRandomAccessIterator && + bBigItIsReadableIterator && + ! bBigItIsReadableLValueIterator && + bAllVectsIsRandomAccessIterator && + ! bAllVectsIsReadableLValueIterator && + bAllVectsIsReadableIterator && + bAllIteratorsReadable1 && + ! bAllIteratorsReadable2 + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests = 0; + std::cout << "not OK" << std::endl; + } + + // Done + // + std::cout << "\nTest Result:" + << "\n============" + << "\nNumber of successful tests: " << static_cast(num_successful_tests) + << "\nNumber of failed tests: " << static_cast(num_failed_tests) + << std::endl; + + return 0; +} + From abf83900200904edcb119dcbfb7807348f2207f5 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 14 Sep 2003 01:53:59 +0000 Subject: [PATCH 208/265] Fix the implementation of operator_arrow_result so that it checks the reference type instead of the category. [SVN r20046] --- include/boost/iterator/iterator_facade.hpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index 3bdb040..79795ad 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -166,17 +166,14 @@ namespace boost // A metafunction that gets the result type for operator->. Also // has a static function make() which builds the result from a // Reference - template + template struct operator_arrow_result { // CWPro8.3 won't accept "operator_arrow_result::type", and we // need that type below, so metafunction forwarding would be a // losing proposition here. typedef typename mpl::if_< - is_tag< - readable_lvalue_iterator_tag - , typename access_category_tag::type - > + is_reference , Pointer , operator_arrow_proxy >::type type; @@ -190,16 +187,15 @@ namespace boost # if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // Deal with ETI template<> - struct operator_arrow_result + struct operator_arrow_result { typedef int type; }; # endif // - // Facade is actually an iterator. We require Facade here - // so that we do not have to go through iterator_traits - // to access the traits + // Iterator is actually an iterator_facade, so we do not have to + // go through iterator_traits to access the traits. // template class operator_brackets_proxy @@ -422,7 +418,6 @@ namespace boost typename detail::operator_arrow_result< value_type - , iterator_category , reference , pointer >::type @@ -430,7 +425,6 @@ namespace boost { return detail::operator_arrow_result< value_type - , iterator_category , reference , pointer >::make(*this->derived()); From cbeb7f0632f898e70301b0e92fc9064455c8057e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 14 Sep 2003 02:17:41 +0000 Subject: [PATCH 209/265] fixed up copyrights, some small progress on new adaptor category choice semantics [SVN r20047] --- doc/counting_iterator.html | 14 ++++-- doc/counting_iterator.rst | 2 +- doc/facade-and-adaptor.html | 61 ++++++++++++++----------- doc/facade-and-adaptor.rst | 2 +- doc/filter_iterator.html | 14 ++++-- doc/filter_iterator.rst | 2 +- doc/function_output_iterator.html | 14 ++++-- doc/function_output_iterator.rst | 2 +- doc/index.html | 35 +++++++++------ doc/index.rst | 25 ++++++----- doc/indirect_iterator.html | 14 ++++-- doc/indirect_iterator.rst | 2 +- doc/iterator_adaptor.html | 61 ++++++++++++++----------- doc/iterator_adaptor.rst | 2 +- doc/iterator_adaptor_ref.rst | 44 +++++++++--------- doc/iterator_facade.html | 14 ++++-- doc/iterator_facade.rst | 2 +- doc/new-iter-concepts.html | 74 +++++++++++++++++++------------ doc/new-iter-concepts.rst | 2 +- doc/permutation_iterator.html | 14 ++++-- doc/permutation_iterator.rst | 2 +- doc/reverse_iterator.html | 14 ++++-- doc/reverse_iterator.rst | 2 +- doc/transform_iterator.rst | 2 +- 24 files changed, 253 insertions(+), 167 deletions(-) diff --git a/doc/counting_iterator.html b/doc/counting_iterator.html index 4465a98..6fd0e36 100644 --- a/doc/counting_iterator.html +++ b/doc/counting_iterator.html @@ -3,13 +3,13 @@ - + Counting Iterator - - + +
@@ -29,7 +29,7 @@ Railway Operation and Construction Date: 2003-08-05 Copyright: -Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved @@ -140,5 +140,11 @@ object copy constructed from x
+ + diff --git a/doc/counting_iterator.rst b/doc/counting_iterator.rst index d6aedf7..25fb3b3 100644 --- a/doc/counting_iterator.rst +++ b/doc/counting_iterator.rst @@ -8,7 +8,7 @@ Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com .. _`Open Systems Lab`: http://www.osl.iu.edu diff --git a/doc/facade-and-adaptor.html b/doc/facade-and-adaptor.html index 3750a32..aa0cde4 100755 --- a/doc/facade-and-adaptor.html +++ b/doc/facade-and-adaptor.html @@ -3,13 +3,13 @@ - + Iterator Facade and Adaptor - - + +
@@ -31,7 +31,7 @@ Railway Operation and Construction Number:This document is a revised version of the official N1476=03-0059 Copyright: -Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved @@ -961,15 +961,15 @@ class iterator_adaptor

iterator_adaptor requirements

The Derived template parameter must be a derived class of -iterator_adaptor. The Base type must implement the expressions -involving m_iterator in the specifications of those private member -functions of iterator_adaptor that are not redefined by the -Derived class and that are needed to model the concept -corresponding to the chosen Category according to the requirements -of iterator_facade. The rest of the template parameters specify -the types for the member typedefs in iterator_facade. The -following pseudo-code specifies the traits types for -iterator_adaptor.

+iterator_adaptor. The Base type must implement the +expressions involving m_iterator in the specifications of those +private member functions of iterator_adaptor that are not +redefined by the Derived class and that are needed to model the +concept corresponding to the iterator_adaptor's category +typedef according to the requirements of iterator_facade. The +rest of the template parameters specify the types for the member +typedefs in iterator_facade. The following pseudo-code +specifies the traits types for iterator_adaptor.

 if (Value == use_default)
     value_type = iterator_traits<Base>::value_type;
@@ -991,26 +991,29 @@ else
 
 if (Category == use_default)
     iterator_category = iterator_tag< 
-        access_category< 
-            iterator< iterator_traits<Base>::iterator_category,
-                      Value,
-                      Distance,
-                      Value*,
-                      Reference > >,
-        traversal_category<
-            iterator< iterator_traits<Base>::iterator_category,
-                      Value,
-                      Distance,
-                      Value*,
-                      Reference > >
+        access_category< Base >,
+        traversal_category< Base >
+    >
+else if (Category is an access tag)
+    iterator_category = iterator_tag<
+        Category
+    ...
+
+else if (Category is a traversal tag)
+    ...
 else
     iterator_category = Category;
+    // Actually the above is wrong.  See the use of
+    // access_category_tag and
+    // new_category_to_access/iter_category_to_access.
 
+ iterator_category = Category; + +Fix this up!! -->

iterator_adaptor public operations

@@ -1841,5 +1844,11 @@ LocalWords: OtherIncrementable Coplien -->
+ + diff --git a/doc/facade-and-adaptor.rst b/doc/facade-and-adaptor.rst index a2d0493..e06567b 100644 --- a/doc/facade-and-adaptor.rst +++ b/doc/facade-and-adaptor.rst @@ -9,7 +9,7 @@ Railway Operation and Construction`_ :date: $Date$ :Number: **This document is a revised version of the official** N1476=03-0059 -:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com .. _`Open Systems Lab`: http://www.osl.iu.edu diff --git a/doc/filter_iterator.html b/doc/filter_iterator.html index a0fa47c..4133ae5 100644 --- a/doc/filter_iterator.html +++ b/doc/filter_iterator.html @@ -3,13 +3,13 @@ - +Filter Iterator - - + +
@@ -29,7 +29,7 @@ Railway Operation and Construction
- +
Date: 2003-08-05
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
@@ -186,5 +186,11 @@ filter_iterator(
+ + diff --git a/doc/filter_iterator.rst b/doc/filter_iterator.rst index 06a7c5f..acd770e 100644 --- a/doc/filter_iterator.rst +++ b/doc/filter_iterator.rst @@ -8,7 +8,7 @@ Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com .. _`Open Systems Lab`: http://www.osl.iu.edu diff --git a/doc/function_output_iterator.html b/doc/function_output_iterator.html index e3e1ba3..30d4559 100644 --- a/doc/function_output_iterator.html +++ b/doc/function_output_iterator.html @@ -3,13 +3,13 @@ - + Function Output Iterator - - + +
@@ -29,7 +29,7 @@ Railway Operation and Construction Date: 2003-08-05 Copyright: -Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved @@ -155,5 +155,11 @@ return *this;
+ + diff --git a/doc/function_output_iterator.rst b/doc/function_output_iterator.rst index 33ea80e..d1740fb 100644 --- a/doc/function_output_iterator.rst +++ b/doc/function_output_iterator.rst @@ -8,7 +8,7 @@ Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com .. _`Open Systems Lab`: http://www.osl.iu.edu diff --git a/doc/index.html b/doc/index.html index 6940f28..37421eb 100755 --- a/doc/index.html +++ b/doc/index.html @@ -3,9 +3,9 @@ - + The Boost Iterator Library Boost - + @@ -177,5 +178,11 @@ LocalWords: incrementable xxx min prev inplace png oldeqnew AccessTag struct LocalWords: TraversalTag typename lvalues DWA Hmm JGS --> + + diff --git a/doc/index.rst b/doc/index.rst index d8961a4..13da6f7 100755 --- a/doc/index.rst +++ b/doc/index.rst @@ -17,7 +17,7 @@ __ ../../../index.htm Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:copyright: Copyright Dave Abrahams, Jeremy Siek, Thomas Witt 2003. All rights reserved +:copyright: Copyright David Abrahams, Jeremy Siek, Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com .. _`Open Systems Lab`: http://www.osl.iu.edu @@ -37,7 +37,7 @@ __ ../../../index.htm report. The components of the Boost Iterator Library replace the older Boost Iterator Adaptor Library. -.. _concepts: ../../more/generic_programming.html +.. _concepts: ../../../more/generic_programming.html#concept .. contents:: **Table of Contents** @@ -52,16 +52,17 @@ __ ../../../index.htm The iterator categories defined in C++98 are extremely limiting because they bind together two orthogonal concepts: traversal and element access. For example, because a random access iterator is -required to return a reference (and not a proxy) when dereferenced, it -is impossible to capture the capabilities of -``vector::iterator`` using the C++98 categories. The infamous -"``vector`` is not a container, and its iterators aren't random -access iterators", debacle about which Herb Sutter wrote two papers -for the standards comittee (n1185_ and n1211_), and a `Guru of the -Week`__. New-style iterators go well beyond patching up -``vector``, though. There are lots of other iterators already -in use which can't be adequately represented by the existing concepts. -For details about the new iterator concepts, see our +required to return a reference (and not a proxy) when dereferenced, +it is impossible to capture the capabilities of +``vector::iterator`` using the C++98 categories. This is the +infamous "``vector`` is not a container, and its iterators +aren't random access iterators", debacle about which Herb Sutter +wrote two papers for the standards comittee (n1185_ and n1211_), +and a `Guru of the Week`__. New-style iterators go well beyond +patching up ``vector``, though: there are lots of other +iterators already in use which can't be adequately represented by +the existing concepts. For details about the new iterator +concepts, see our .. _n1185: http://www.gotw.ca/publications/N1185.pdf .. _n1211: http://www.gotw.ca/publications/N1211.pdf diff --git a/doc/indirect_iterator.html b/doc/indirect_iterator.html index cff848f..9bbc80b 100644 --- a/doc/indirect_iterator.html +++ b/doc/indirect_iterator.html @@ -3,13 +3,13 @@ - + Indirect Iterator - - + +
@@ -29,7 +29,7 @@ Railway Operation and Construction Date: 2003-08-05 Copyright: -Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved @@ -159,5 +159,11 @@ indirect_iterator(
+ + diff --git a/doc/indirect_iterator.rst b/doc/indirect_iterator.rst index 7d19ba2..3ea8dcb 100644 --- a/doc/indirect_iterator.rst +++ b/doc/indirect_iterator.rst @@ -8,7 +8,7 @@ Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com .. _`Open Systems Lab`: http://www.osl.iu.edu diff --git a/doc/iterator_adaptor.html b/doc/iterator_adaptor.html index 641ac85..d34598e 100644 --- a/doc/iterator_adaptor.html +++ b/doc/iterator_adaptor.html @@ -3,13 +3,13 @@ - + Iterator Adaptor - - + +
@@ -29,7 +29,7 @@ Railway Operation and Construction Date: 2003-08-05 Copyright: -Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved @@ -146,15 +146,15 @@ class iterator_adaptor

iterator_adaptor requirements

The Derived template parameter must be a derived class of -iterator_adaptor. The Base type must implement the expressions -involving m_iterator in the specifications of those private member -functions of iterator_adaptor that are not redefined by the -Derived class and that are needed to model the concept -corresponding to the chosen Category according to the requirements -of iterator_facade. The rest of the template parameters specify -the types for the member typedefs in iterator_facade. The -following pseudo-code specifies the traits types for -iterator_adaptor.

+iterator_adaptor. The Base type must implement the +expressions involving m_iterator in the specifications of those +private member functions of iterator_adaptor that are not +redefined by the Derived class and that are needed to model the +concept corresponding to the iterator_adaptor's category +typedef according to the requirements of iterator_facade. The +rest of the template parameters specify the types for the member +typedefs in iterator_facade. The following pseudo-code +specifies the traits types for iterator_adaptor.

 if (Value == use_default)
     value_type = iterator_traits<Base>::value_type;
@@ -176,26 +176,29 @@ else
 
 if (Category == use_default)
     iterator_category = iterator_tag< 
-        access_category< 
-            iterator< iterator_traits<Base>::iterator_category,
-                      Value,
-                      Distance,
-                      Value*,
-                      Reference > >,
-        traversal_category<
-            iterator< iterator_traits<Base>::iterator_category,
-                      Value,
-                      Distance,
-                      Value*,
-                      Reference > >
+        access_category< Base >,
+        traversal_category< Base >
+    >
+else if (Category is an access tag)
+    iterator_category = iterator_tag<
+        Category
+    ...
+
+else if (Category is a traversal tag)
+    ...
 else
     iterator_category = Category;
+    // Actually the above is wrong.  See the use of
+    // access_category_tag and
+    // new_category_to_access/iter_category_to_access.
 
+ iterator_category = Category; + +Fix this up!! -->

iterator_adaptor public operations

@@ -322,5 +325,11 @@ typename iterator_adaptor::difference_type distance_to(
+ + diff --git a/doc/iterator_adaptor.rst b/doc/iterator_adaptor.rst index d46f4fd..e64e93a 100644 --- a/doc/iterator_adaptor.rst +++ b/doc/iterator_adaptor.rst @@ -8,7 +8,7 @@ Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com .. _`Open Systems Lab`: http://www.osl.iu.edu diff --git a/doc/iterator_adaptor_ref.rst b/doc/iterator_adaptor_ref.rst index 62c1d78..69c6aa7 100644 --- a/doc/iterator_adaptor_ref.rst +++ b/doc/iterator_adaptor_ref.rst @@ -47,15 +47,15 @@ __ : --------------------------------- The ``Derived`` template parameter must be a derived class of -``iterator_adaptor``. The ``Base`` type must implement the expressions -involving ``m_iterator`` in the specifications of those private member -functions of ``iterator_adaptor`` that are not redefined by the -``Derived`` class and that are needed to model the concept -corresponding to the chosen ``Category`` according to the requirements -of ``iterator_facade``. The rest of the template parameters specify -the types for the member typedefs in ``iterator_facade``. The -following pseudo-code specifies the traits types for -``iterator_adaptor``. +``iterator_adaptor``. The ``Base`` type must implement the +expressions involving ``m_iterator`` in the specifications of those +private member functions of ``iterator_adaptor`` that are not +redefined by the ``Derived`` class and that are needed to model the +concept corresponding to the ``iterator_adaptor``\ 's ``category`` +typedef according to the requirements of ``iterator_facade``. The +rest of the template parameters specify the types for the member +typedefs in ``iterator_facade``. The following pseudo-code +specifies the traits types for ``iterator_adaptor``. :: @@ -79,20 +79,21 @@ following pseudo-code specifies the traits types for if (Category == use_default) iterator_category = iterator_tag< - access_category< - iterator< iterator_traits::iterator_category, - Value, - Distance, - Value*, - Reference > >, - traversal_category< - iterator< iterator_traits::iterator_category, - Value, - Distance, - Value*, - Reference > > + access_category< Base >, + traversal_category< Base > + > + else if (Category is an access tag) + iterator_category = iterator_tag< + Category + ... + + else if (Category is a traversal tag) + ... else iterator_category = Category; + // Actually the above is wrong. See the use of + // access_category_tag and + // new_category_to_access/iter_category_to_access. .. Replaced with new semantics --thw @@ -101,6 +102,7 @@ following pseudo-code specifies the traits types for else iterator_category = Category; + Fix this up!! ``iterator_adaptor`` public operations diff --git a/doc/iterator_facade.html b/doc/iterator_facade.html index 64c6764..84f7e25 100644 --- a/doc/iterator_facade.html +++ b/doc/iterator_facade.html @@ -3,13 +3,13 @@ - +Iterator Facade - - + +
@@ -29,7 +29,7 @@ Railway Operation and Construction
- +
Date: 2003-08-05
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
@@ -570,5 +570,11 @@ return tmp -= n; + + diff --git a/doc/iterator_facade.rst b/doc/iterator_facade.rst index 379e942..473d095 100644 --- a/doc/iterator_facade.rst +++ b/doc/iterator_facade.rst @@ -8,7 +8,7 @@ Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com .. _`Open Systems Lab`: http://www.osl.iu.edu diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index fd98e5f..8202cf7 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -3,13 +3,13 @@ - +New Iterator Concepts - - - + + +
@@ -25,11 +25,11 @@
- + - +
Organization: Boost Consulting, Indiana University Open Systems Lab, University of Hanover Institute for Transport Railway Operation and Construction
Date:2003-07-13
2003-08-14
Number:This document is a revised version of the official N1477=03-0060
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
@@ -373,29 +373,39 @@ Equivalent to (*a).m

Writable Iterators [lib.writable.iterators]

A class or built-in type X models the Writable Iterator concept if the following expressions are valid and respect the stated -semantics.

- +semantics. In addition, a model of Writable Iterator must include +in its documentation the set of value types that it allows for +output.

+
+
+++++ + + + + + + + + + + + + + + + + + + +
Writable Iterator Requirements (in addition to CopyConstructible)
ExpressionReturn TypePrecondition
access_category<X>::typeConvertible to +writable_iterator_tag 
*a = o pre: The type of o +is in the set of +value types of X
+

Swappable Iterators [lib.swappable.iterators]

@@ -932,5 +942,11 @@ LocalWords: TraversalTag typename lvalues DWA Hmm JGS -->
+ + diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index ff39358..a636584 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -7,7 +7,7 @@ :organization: `Boost Consulting`_, Indiana University `Open Systems Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ :Number: **This document is a revised version of the official** N1477=03-0060 -:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com .. _`Open Systems Lab`: http://www.osl.iu.edu diff --git a/doc/permutation_iterator.html b/doc/permutation_iterator.html index 8d74da7..4549786 100644 --- a/doc/permutation_iterator.html +++ b/doc/permutation_iterator.html @@ -3,13 +3,13 @@ - + Permutation Iterator - - + +
@@ -28,7 +28,7 @@ Lab Date: 2003-08-05 Copyright: -Copyright Toon Knapen, Dave Abrahams, Roland Richter, and Jeremy Siek 2003. All rights reserved +Copyright Toon Knapen, David Abrahams, Roland Richter, and Jeremy Siek 2003. All rights reserved @@ -118,5 +118,11 @@ ForwardIterator instead of amortized constant time.

+ + diff --git a/doc/permutation_iterator.rst b/doc/permutation_iterator.rst index 3d75608..d506b78 100644 --- a/doc/permutation_iterator.rst +++ b/doc/permutation_iterator.rst @@ -7,7 +7,7 @@ :organization: `Boost Consulting`_, Indiana University `Open Systems Lab`_ :date: $Date$ -:copyright: Copyright Toon Knapen, Dave Abrahams, Roland Richter, and Jeremy Siek 2003. All rights reserved +:copyright: Copyright Toon Knapen, David Abrahams, Roland Richter, and Jeremy Siek 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com .. _`Open Systems Lab`: http://www.osl.iu.edu diff --git a/doc/reverse_iterator.html b/doc/reverse_iterator.html index 60d1521..3aba842 100644 --- a/doc/reverse_iterator.html +++ b/doc/reverse_iterator.html @@ -3,13 +3,13 @@ - +Reverse Iterator - - + +
@@ -29,7 +29,7 @@ Railway Operation and Construction
- +
Date: 2003-08-05
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
@@ -133,5 +133,11 @@ reverse_iterator(
+ + diff --git a/doc/reverse_iterator.rst b/doc/reverse_iterator.rst index 44b9101..5265076 100644 --- a/doc/reverse_iterator.rst +++ b/doc/reverse_iterator.rst @@ -8,7 +8,7 @@ Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com .. _`Open Systems Lab`: http://www.osl.iu.edu diff --git a/doc/transform_iterator.rst b/doc/transform_iterator.rst index 6f8be45..021532d 100644 --- a/doc/transform_iterator.rst +++ b/doc/transform_iterator.rst @@ -8,7 +8,7 @@ Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com .. _`Open Systems Lab`: http://www.osl.iu.edu From 4968b50fc2b47a66da1e8d7459b5fbaa99662480 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 19 Sep 2003 18:44:53 +0000 Subject: [PATCH 210/265] Remove outdated comment; use boost::detail::iterator_traits instead of std::iterator_traits exclusively. [SVN r20117] --- include/boost/iterator/zip_iterator.hpp | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/include/boost/iterator/zip_iterator.hpp b/include/boost/iterator/zip_iterator.hpp index 7d7c41e..cc12591 100755 --- a/include/boost/iterator/zip_iterator.hpp +++ b/include/boost/iterator/zip_iterator.hpp @@ -26,6 +26,7 @@ #include #include // for enable_if_convertible #include +#include #include @@ -64,18 +65,6 @@ namespace boost { // // If the tuple implementation changes, all that needs to be // replaced is the implementation of these four (meta-)algorithms. - // - // Unfortunately, some compilers, including Metrowerks Codewarrior - // 4.2.5.766 and gcc 3.3, were unable to handle the template - // code involved (Metrowerks: internal compiler error, gcc 3.3: - // segmentation fault). Therefore, rather regrettably, for those - // compilers, the encapsulation of the tuple implementation- - // specific code is not nearly as nice and clean as it should be. - // In order to emphasize this point, I have provided the entire - // namespace detail in this file twice: the first version is the - // clean one with the nice encapsulation, the second one is the - // dirty one. - // namespace detail { @@ -117,13 +106,13 @@ namespace boost { { #if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407) typedef typename - std::iterator_traits< + iterator_traits< typename boost::remove_cv::type >::reference type; #else typedef typename - std::iterator_traits::reference + iterator_traits::reference type; #endif }; From d9b4e41d5a5040c21c434eb2040b704a1cddd2df Mon Sep 17 00:00:00 2001 From: Thomas Witt Date: Sat, 20 Sep 2003 21:30:10 +0000 Subject: [PATCH 211/265] Made transform_iterator documentation refer to result_of. [SVN r20123] --- doc/transform_iterator_ref.rst | 40 ++++++++++++++++------------------ 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/doc/transform_iterator_ref.rst b/doc/transform_iterator_ref.rst index bb59c1e..2a6cd58 100644 --- a/doc/transform_iterator_ref.rst +++ b/doc/transform_iterator_ref.rst @@ -1,6 +1,6 @@ :: - template @@ -10,50 +10,48 @@ friend class iterator_core_access; public: transform_iterator(); - transform_iterator(Iterator const& x, AdaptableUnaryFunction f); + transform_iterator(Iterator const& x, UnaryFunction f); template transform_iterator( - transform_iterator const& t + transform_iterator const& t , typename enable_if_convertible::type* = 0 // exposition ); - AdaptableUnaryFunction functor() const; + UnaryFunction functor() const; private: typename transform_iterator::value_type dereference() const; - AdaptableUnaryFunction m_f; + UnaryFunction m_f; }; ``transform_iterator`` requirements ................................... -The type ``AdaptableUnaryFunction`` must be Assignable, Copy -Constructible, and the expression ``f(x)`` must be valid where ``f`` -is an object of type ``AdaptableUnaryFunction``, ``x`` is an object of -type ``AdaptableUnaryFunction::argument_type``, and where the type of -``f(x)`` must be ``AdaptableUnaryFunction::result_type``. +The type ``UnaryFunction`` must be Assignable, Copy Constructible, and +the expression ``f(*i)`` must be valid where ``f`` is an object of +type ``UnaryFunction``, ``i`` is an object of type ``Iterator``, and +where the type of ``f(*i)`` must be +``result_of::reference)>::type``. The type ``Iterator`` must at least model Readable Iterator. The resulting ``transform_iterator`` models the most refined of the following options that is also modeled by ``Iterator``. - * Writable Lvalue Iterator if the ``result_type`` of the - ``AdaptableUnaryFunction`` is a non-const reference. + * Writable Lvalue Iterator if ``result_of::reference)>::type`` is a non-const reference. - * Readable Lvalue Iterator if the ``result_type`` is a const + * Readable Lvalue Iterator if ``result_of::reference)>::type`` is a const reference. * Readable Iterator otherwise. -The ``transform_iterator`` models the most refined standard traversal +The ``transform_iterator`` models the traversal concept that is modeled by ``Iterator``. -The ``value_type`` of ``transform_iterator`` is -``remove_reference::type``. The ``reference`` type is -``result_type``. - +The ``reference`` type of ``transform_iterator`` is +``result_of::reference)>::type``. +The ``value_type`` is ``remove_cv >::type``. ``transform_iterator`` public operations ........................................ @@ -65,7 +63,7 @@ The ``value_type`` of ``transform_iterator`` is and ``m_iterator`` default constructed. -``transform_iterator(Iterator const& x, AdaptableUnaryFunction f);`` +``transform_iterator(Iterator const& x, UnaryFunction f);`` :Returns: An instance of ``transform_iterator`` with ``m_f`` initialized to ``f`` and ``m_iterator`` initialized to ``x``. @@ -75,14 +73,14 @@ The ``value_type`` of ``transform_iterator`` is template transform_iterator( - transform_iterator const& t + transform_iterator const& t , typename enable_if_convertible::type* = 0 // exposition ); :Returns: An instance of ``transform_iterator`` that is a copy of ``t``. :Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. -``AdaptableUnaryFunction functor() const;`` +``UnaryFunction functor() const;`` :Returns: ``m_f`` From 85873e924a29b981281d881a043075e3fb409eb7 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sat, 20 Sep 2003 23:43:30 +0000 Subject: [PATCH 212/265] some minor edits [SVN r20124] --- doc/new-iter-concepts.html | 47 +++++++++++++++++++------------------- doc/new-iter-concepts.rst | 11 +++++++-- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index 8202cf7..2bcf044 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -3,13 +3,13 @@ - + New Iterator Concepts - + - +
@@ -25,7 +25,7 @@ Organization: Boost Consulting, Indiana University Open Systems Lab, University of Hanover Institute for Transport Railway Operation and Construction Date: -2003-08-14 +2003-09-14 Number:This document is a revised version of the official N1477=03-0060 Copyright: @@ -92,7 +92,7 @@ geared towards iterator traversal (hence the category names), while requirements that address value access sneak in at various places. The following table gives a summary of the current value access requirements in the iterator categories.

- +
@@ -326,7 +326,7 @@ for the value type T if the fo respect the stated semantics. U is the type of any specified member of type T.

-
+
@@ -377,7 +377,7 @@ semantics. In addition, a model of Writable Iterator must include in its documentation the set of value types that it allows for output.

-
+
@@ -413,7 +413,7 @@ value types of X if the following expressions are valid and respect the stated semantics.

-
+
@@ -445,7 +445,7 @@ semantics.

The Readable Lvalue Iterator concept adds the requirement that the reference type be a reference to the value type of the iterator.

-
+
@@ -482,7 +482,7 @@ cv-qualificationreference type be a non-const reference to the value type of the iterator.

-
+
@@ -518,7 +518,7 @@ type X,
-
+
@@ -555,7 +555,7 @@ semantics.

concept if the following expressions are valid and respect the stated semantics.

-
+
@@ -600,7 +600,7 @@ its domain concept if the following expressions are valid and respect the stated semantics.

-
+
@@ -646,7 +646,7 @@ the distance between iterators Iterator concept if the following expressions are valid and respect the stated semantics.

-
+
@@ -690,7 +690,7 @@ the stated semantics. In the table below, iterator_traits<X>::difference_type and n represents a constant object of type Distance.

-
+
@@ -817,7 +817,8 @@ struct readable_writable_iterator_tag : virtual readable_iterator_tag , virtual writable_iterator_tag , virtual swappable_iterator_tag { }; -struct readable_lvalue_iterator_tag { }; +struct readable_lvalue_iterator_tag + : virtual readable_iterator_tag { }; struct writable_lvalue_iterator_tag : virtual public readable_writable_iterator_tag , virtual public readable_lvalue_iterator_tag { }; @@ -836,7 +837,7 @@ struct input_output_iterator_tag : input_iterator_tag, output_iterator_tag {};

Addition to [lib.iterator.traits]

The iterator_tag class template is an iterator category tag that encodes the access and traversal tags in addition to being compatible -with the original iterator tags. The iterator_tag class inherits +with the original iterator tags. The iterator_tag class inherits from one of the original iterator tags according to the following pseudo-code.

@@ -869,6 +870,12 @@ inherit-category(access-tag, traversal-tag) =
      else
          return null_category_tag;
 
+

If the argument for the template parameter AccessTag is not +convertible to one or more of: readable_iterator_tag, +writable_iterator_tag, swappable_iterator_tag, or if the +argument for TraversalTag is not convertible to +incrementable_iterator_tag then the behavior of iterator_tag +is not defined.

The access_category and traversal_category class templates are traits classes. For iterators whose iterator_traits<Iter>::iterator_category type is iterator_tag, @@ -942,11 +949,5 @@ LocalWords: TraversalTag typename lvalues DWA Hmm JGS --> -

- diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index a636584..e721c3a 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -625,7 +625,8 @@ Addition to [lib.iterator.synopsis] : virtual readable_iterator_tag , virtual writable_iterator_tag , virtual swappable_iterator_tag { }; - struct readable_lvalue_iterator_tag { }; + struct readable_lvalue_iterator_tag + : virtual readable_iterator_tag { }; struct writable_lvalue_iterator_tag : virtual public readable_writable_iterator_tag , virtual public readable_lvalue_iterator_tag { }; @@ -644,7 +645,7 @@ Addition to [lib.iterator.traits] The ``iterator_tag`` class template is an iterator category tag that encodes the access and traversal tags in addition to being compatible -with the original iterator tags. The ``iterator_tag`` class inherits +with the original iterator tags. The ``iterator_tag`` class inherits from one of the original iterator tags according to the following pseudo-code. @@ -679,6 +680,12 @@ pseudo-code. else return null_category_tag; +If the argument for the template parameter ``AccessTag`` is not +convertible to one or more of: ``readable_iterator_tag``, +``writable_iterator_tag``, ``swappable_iterator_tag``, or if the +argument for ``TraversalTag`` is not convertible to +``incrementable_iterator_tag`` then the behavior of ``iterator_tag`` +is not defined. The ``access_category`` and ``traversal_category`` class templates are traits classes. For iterators whose From 1c41a7d0ec94c1cdc7f8e57392e4424494ca4286 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 21 Sep 2003 00:30:15 +0000 Subject: [PATCH 213/265] some edits based on comments from Howard Hinnant [SVN r20125] --- doc/new-iter-concepts.html | 58 +++++++++++++++++++++----------------- doc/new-iter-concepts.rst | 31 ++++++++++++-------- 2 files changed, 51 insertions(+), 38 deletions(-) diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index 2bcf044..0df8278 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -3,11 +3,11 @@ - + New Iterator Concepts - + @@ -25,7 +25,7 @@
- + @@ -92,7 +92,7 @@ geared towards iterator traversal (hence the category names), while requirements that address value access sneak in at various places. The following table gives a summary of the current value access requirements in the iterator categories.

-
Organization: Boost Consulting, Indiana University Open Systems Lab, University of Hanover Institute for Transport Railway Operation and Construction
Date:2003-09-14
2003-09-20
Number:This document is a revised version of the official N1477=03-0060
Copyright:
+
@@ -121,9 +121,10 @@ categorized. For example, vector<bool&g random access iterator, but the return type is not bool& (see issue 96 and Herb Sutter's paper J16/99-0008 = WG21 N1185). Therefore, the iterators of vector<bool> only meet the -requirements of input iterator and output iterator. This is so -nonintuitive that at least one implementation erroneously assigns -random_access_iterator_tag as its iterator_category.

+requirements of input iterator and output iterator. This is so +nonintuitive that the C++ standard contradicts itself on this point. +In paragraph 23.2.4/1 it says that a vector is a sequence that +supports random access iterators.

Another difficult-to-categorize iterator is the transform iterator, an adaptor which applies a unary function object to the dereferenced value of the some underlying iterator (see transform_iterator). @@ -218,11 +219,11 @@ Bidirectional Iterator (2) -> Bidirectional Traversal Iterator and Writable I

stable_partition, inplace_merge
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator
reverse_copy
-
Random Access Iterator -> Random Access Traversal Iterator and Readable and Swappable Iterator
+
Random Access Iterator -> Random Access Traversal Iterator and Readable and Writable Iterator
random_shuffle, sort, stable_sort, partial_sort, nth_element, push_heap, pop_heap make_heap, sort_heap
Input Iterator (2) -> Incrementable Iterator and Readable Iterator
-
equal
+
equal, mismatch
Input Iterator (2) -> Incrementable Iterator and Readable Iterator
transform
@@ -266,11 +267,17 @@ given in the following diagram.

oldeqnew.png

Like the old iterator requirements, we provide tags for purposes of dispatching. There are two hierarchies of tags, one for the access -concepts and one for the traversal concepts. We provide an access -mechanism for mapping iterator types to these new tags. Our design -reuses iterator_traits<Iter>::iterator_category as the access -mechanism. To enable this, a pair of access and traversal tags are -combined into a single type using the following iterator_tag class.

+concepts and one for the traversal concepts. The tags are related via +inheritance so that a tag is convertible to another tag if the concept +associated with the first tag is a refinement of the second tag. We +use virtual inheritance of the diamonds in the current hierarchy, and +because of possible diamonds that could be created when programmers +define new iterator concepts and the corresponding tags.

+

We provide an access mechanism for mapping iterator types to the new +tags. Our design reuses iterator_traits<Iter>::iterator_category +as the access mechanism. To enable this, a pair of access and +traversal tags are combined into a single type using the following +iterator_tag class.

 template <class AccessTag, class TraversalTag>
 struct iterator_tag : /* appropriate old category or categories */
@@ -326,7 +333,7 @@ for the value type T if the fo
 respect the stated semantics. U is the type of any specified
 member of type T.

-
+
@@ -377,7 +384,7 @@ semantics. In addition, a model of Writable Iterator must include in its documentation the set of value types that it allows for output.

-
+
@@ -413,7 +420,7 @@ value types of X if the following expressions are valid and respect the stated semantics.

-
+
@@ -445,7 +452,7 @@ semantics.

The Readable Lvalue Iterator concept adds the requirement that the reference type be a reference to the value type of the iterator.

-
+
@@ -482,7 +489,7 @@ cv-qualification reference type be a non-const reference to the value type of the iterator.

-
+
@@ -518,7 +525,7 @@ type X,
-
+
@@ -555,7 +562,7 @@ semantics.

concept if the following expressions are valid and respect the stated semantics.

-
+
@@ -600,7 +607,7 @@ its domain concept if the following expressions are valid and respect the stated semantics.

-
+
@@ -646,7 +653,7 @@ the distance between iterators Iterator concept if the following expressions are valid and respect the stated semantics.

-
+
@@ -690,7 +697,7 @@ the stated semantics. In the table below, iterator_traits<X>::difference_type and n represents a constant object of type Distance.

-
+
@@ -874,8 +881,7 @@ inherit-category(access-tag, traversal-tag) = convertible to one or more of: readable_iterator_tag, writable_iterator_tag, swappable_iterator_tag, or if the argument for TraversalTag is not convertible to -incrementable_iterator_tag then the behavior of iterator_tag -is not defined.

+incrementable_iterator_tag then the programm is ill-formed.

The access_category and traversal_category class templates are traits classes. For iterators whose iterator_traits<Iter>::iterator_category type is iterator_tag, diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index e721c3a..8a6a293 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -65,9 +65,10 @@ categorized. For example, ``vector::iterator`` is almost a random access iterator, but the return type is not ``bool&`` (see `issue 96`_ and Herb Sutter's paper J16/99-0008 = WG21 N1185). Therefore, the iterators of ``vector`` only meet the -requirements of input iterator and output iterator. This is so -nonintuitive that at least one implementation erroneously assigns -``random_access_iterator_tag`` as its ``iterator_category``. +requirements of input iterator and output iterator. This is so +nonintuitive that the C++ standard contradicts itself on this point. +In paragraph 23.2.4/1 it says that a ``vector`` is a sequence that +supports random access iterators. .. _issue 96: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#96 @@ -188,12 +189,12 @@ Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator ``reverse_copy`` -Random Access Iterator -> Random Access Traversal Iterator and Readable and Swappable Iterator +Random Access Iterator -> Random Access Traversal Iterator and Readable and Writable Iterator ``random_shuffle, sort, stable_sort, partial_sort, nth_element, push_heap, pop_heap make_heap, sort_heap`` Input Iterator (2) -> Incrementable Iterator and Readable Iterator - ``equal`` + ``equal, mismatch`` Input Iterator (2) -> Incrementable Iterator and Readable Iterator ``transform`` @@ -247,11 +248,18 @@ given in the following diagram. Like the old iterator requirements, we provide tags for purposes of dispatching. There are two hierarchies of tags, one for the access -concepts and one for the traversal concepts. We provide an access -mechanism for mapping iterator types to these new tags. Our design -reuses ``iterator_traits::iterator_category`` as the access -mechanism. To enable this, a pair of access and traversal tags are -combined into a single type using the following `iterator_tag` class. +concepts and one for the traversal concepts. The tags are related via +inheritance so that a tag is convertible to another tag if the concept +associated with the first tag is a refinement of the second tag. We +use virtual inheritance of the diamonds in the current hierarchy, and +because of possible diamonds that could be created when programmers +define new iterator concepts and the corresponding tags. + +We provide an access mechanism for mapping iterator types to the new +tags. Our design reuses ``iterator_traits::iterator_category`` +as the access mechanism. To enable this, a pair of access and +traversal tags are combined into a single type using the following +`iterator_tag` class. :: @@ -684,8 +692,7 @@ If the argument for the template parameter ``AccessTag`` is not convertible to one or more of: ``readable_iterator_tag``, ``writable_iterator_tag``, ``swappable_iterator_tag``, or if the argument for ``TraversalTag`` is not convertible to -``incrementable_iterator_tag`` then the behavior of ``iterator_tag`` -is not defined. +``incrementable_iterator_tag`` then the programm is ill-formed. The ``access_category`` and ``traversal_category`` class templates are traits classes. For iterators whose From fd29e538edd8cd180ebfa80b9baaece7a3713e9a Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 21 Sep 2003 09:17:31 +0000 Subject: [PATCH 214/265] Minor grammatical correction + comment [SVN r20130] --- doc/new-iter-concepts.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 8a6a293..230cfcb 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -701,7 +701,7 @@ the ``access_category`` and ``traversal_category`` traits access the ``access`` and ``traversal`` member types within ``iterator_tag``. For iterators whose ``iterator_traits::iterator_category`` type is not ``iterator_tag`` and instead is a tag convertible to one of the -original tags, the appropriate traversal and access tags is deduced. +original tags, the appropriate traversal and access tags are deduced. The following pseudo-code describes the algorithm. :: @@ -763,6 +763,7 @@ category tags for pointer types. }; +.. We need to document the requirements for the type parameters of iterator_tag. .. LocalWords: Abrahams Siek Witt const bool Sutter's WG int UL LI href Lvalue From 5339d7a9d41045cc439a25b53bf97de1363286c2 Mon Sep 17 00:00:00 2001 From: Thomas Witt Date: Sun, 21 Sep 2003 11:13:46 +0000 Subject: [PATCH 215/265] Reverted change to traversal category. [SVN r20131] --- doc/transform_iterator_ref.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/transform_iterator_ref.rst b/doc/transform_iterator_ref.rst index 2a6cd58..e6628bc 100644 --- a/doc/transform_iterator_ref.rst +++ b/doc/transform_iterator_ref.rst @@ -46,7 +46,7 @@ following options that is also modeled by ``Iterator``. * Readable Iterator otherwise. -The ``transform_iterator`` models the traversal +The ``transform_iterator`` models the most refined standard traversal concept that is modeled by ``Iterator``. The ``reference`` type of ``transform_iterator`` is From d958a5bc82b36de3a8e20d86e36402e54faca445 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 22 Sep 2003 04:57:00 +0000 Subject: [PATCH 216/265] change to lvalue stuff and changing access tag to enum and bits [SVN r20145] --- doc/new-iter-concepts.rst | 175 +++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 98 deletions(-) diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 230cfcb..157bf28 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -209,13 +209,7 @@ set of concepts handles the syntax and semantics of value access: - Readable Iterator - Writable Iterator - Swappable Iterator -- Readable Lvalue Iterator -- Writable Lvalue Iterator - -The refinement relationships among these iterator concepts are given -in the following diagram. - -.. image:: access.png +- Lvalue Iterator The access concepts describe requirements related to ``operator*`` and ``operator->``, including the ``value_type``, ``reference``, and @@ -250,10 +244,11 @@ Like the old iterator requirements, we provide tags for purposes of dispatching. There are two hierarchies of tags, one for the access concepts and one for the traversal concepts. The tags are related via inheritance so that a tag is convertible to another tag if the concept -associated with the first tag is a refinement of the second tag. We -use virtual inheritance of the diamonds in the current hierarchy, and -because of possible diamonds that could be created when programmers -define new iterator concepts and the corresponding tags. +associated with the first tag is a refinement of the second tag. +There is not a tag for Lvalue Iterator because one can easily deduce +whether an iterator is an Lvalue Iterator by checking whether +``iterator_traits::reference`` is a real reference. + We provide an access mechanism for mapping iterator types to the new tags. Our design reuses ``iterator_traits::iterator_category`` @@ -263,7 +258,7 @@ traversal tags are combined into a single type using the following :: - template + template struct iterator_tag : /* appropriate old category or categories */ { typedef AccessTag access; @@ -340,8 +335,7 @@ member of type ``T``. |``iterator_traits::reference`` |Convertible to | | | |``iterator_traits::value_type``| | +--------------------------------------+----------------------------------+-----------------------------------------+ - |``access_category::type`` |Convertible to | | - | |``readable_iterator_tag`` | | + |``is_readable::type`` |``truetype`` | | +--------------------------------------+----------------------------------+-----------------------------------------+ |``*a`` |``iterator_traits::reference`` |pre: ``a`` is dereferenceable. If ``a == | | | |b`` then ``*a`` is equivalent to ``*b`` | @@ -367,8 +361,7 @@ output. +--------------------------------------+-------------------------+----------------------------+ |Expression |Return Type |Precondition | +======================================+=========================+============================+ - |``access_category::type`` |Convertible to | | - | |``writable_iterator_tag``| | + |``is_writable::type`` |``true_type`` | | +--------------------------------------+-------------------------+----------------------------+ |``*a = o`` | | pre: The type of ``o`` | | | | is in the set of | @@ -389,6 +382,8 @@ semantics. +------------------------------------+-------------+---------------------------------------------+ |Expression |Return Type |Postcondition | +====================================+=============+=============================================+ + |``is_swappable::type`` |``true_type``| | + +------------------------------------+-------------+---------------------------------------------+ |``iter_swap(a, b)`` |``void`` |post: the pointed to values are exchanged | +------------------------------------+-------------+---------------------------------------------+ @@ -396,14 +391,14 @@ semantics. is also a model of *Swappable Iterator*. *--end note*] -Readable Lvalue Iterators [lib.readable.lvalue.iterators] ---------------------------------------------------------- +Lvalue Iterators [lib.lvalue.iterators] +--------------------------------------- -The *Readable Lvalue Iterator* concept adds the requirement that the +The *Lvalue Iterator* concept adds the requirement that the ``reference`` type be a reference to the value type of the iterator. +----------------------------------------------------------------------------------------------------------+ - |Readable Lvalue Iterator Requirements (in addition to Readable Iterator) | + | Lvalue Iterator Requirements | +------------------------------------+---------------------------------+-----------------------------------+ |Expression |Return Type |Assertion | +====================================+=================================+===================================+ @@ -412,29 +407,6 @@ The *Readable Lvalue Iterator* concept adds the requirement that the | | |where *cv* is an optional | | | |cv-qualification | +------------------------------------+---------------------------------+-----------------------------------+ - |``access_category::type`` |Convertible to | | - | |``readable_lvalue_iterator_tag`` | | - +------------------------------------+---------------------------------+-----------------------------------+ - - -Writable Lvalue Iterators [lib.writable.lvalue.iterators] ---------------------------------------------------------- - -The *Writable Lvalue Iterator* concept adds the requirement that the -``reference`` type be a non-const reference to the value type of the -iterator. - - - +--------------------------------------------------------------------------------------+ - | Writable Lvalue Iterator Requirements (in addition to Readable Lvalue Iterator) | - +--------------------------------------+-----------------------------------------------+ - | Expression | Return Type | - +======================================+===============================================+ - |``iterator_traits::reference`` |``iterator_traits::value_type&`` | - +--------------------------------------+-----------------------------------------------+ - |``access_category::type`` |Convertible to ``writable_lvalue_iterator_tag``| - | | | - +--------------------------------------+-----------------------------------------------+ Iterator Traversal Concepts [lib.iterator.traversal] @@ -614,31 +586,24 @@ constant object of type ``Distance``. Addition to [lib.iterator.synopsis] =================================== + :: // lib.iterator.traits, traits and tags - template struct access_category; + template struct is_readable; + template struct is_writable; + template struct is_swappable; template struct traversal_category; - template + enum iterator_access { readable_iterator = 1, writable_iterator = 2, + swappable_iterator = 4, lvalue_iterator = 8 }; + + template struct iterator_tag : /* appropriate old category or categories */ { - typedef AccessTag access; + static const iterator_access access = x; typedef TraversalTag traversal; }; - struct readable_iterator_tag { }; - struct writable_iterator_tag { }; - struct swappable_iterator_tag { }; - struct readable_writable_iterator_tag - : virtual readable_iterator_tag - , virtual writable_iterator_tag - , virtual swappable_iterator_tag { }; - struct readable_lvalue_iterator_tag - : virtual readable_iterator_tag { }; - struct writable_lvalue_iterator_tag - : virtual public readable_writable_iterator_tag - , virtual public readable_lvalue_iterator_tag { }; - struct incrementable_iterator_tag { }; struct single_pass_iterator_tag : incrementable_iterator_tag { }; struct forward_traversal_tag : single_pass_iterator_tag { }; @@ -652,15 +617,15 @@ Addition to [lib.iterator.traits] ================================= The ``iterator_tag`` class template is an iterator category tag that -encodes the access and traversal tags in addition to being compatible +encodes the access enum and traversal tag in addition to being compatible with the original iterator tags. The ``iterator_tag`` class inherits from one of the original iterator tags according to the following pseudo-code. :: - inherit-category(access-tag, traversal-tag) = - if (access-tag is convertible to readable_lvalue_iterator_tag) { + inherit-category(access, traversal-tag) = + if (access & lvalue_iterator) { if (traversal-tag is convertible to random_access_traversal_tag) return random_access_iterator_tag; else if (traversal-tag is convertible to bidirectional_traversal_tag) @@ -672,55 +637,67 @@ pseudo-code. return input_output_iterator_tag; else return input_iterator_tag; - else if (access-tag is convertible to writable_iterator_tag) + else if (access & writable_iterator) return output_iterator_tag; else return null_category_tag; - } else if (access-tag is convertible to readable_writable_iterator_tag + } else if ((access & readable_iterator) and (access & writable_iterator) and traversal-tag is convertible to single_pass_iterator_tag) return input_output_iterator_tag; - else if (access-tag is convertible to readable_iterator_tag + else if (access & readable_iterator and traversal-tag is convertible to single_pass_iterator_tag) return input_iterator_tag; - else if (access-tag is convertible to writable_iterator_tag + else if (access & writable_iterator and traversal-tag is convertible to incrementable_iterator_tag) return output_iterator_tag; else return null_category_tag; -If the argument for the template parameter ``AccessTag`` is not -convertible to one or more of: ``readable_iterator_tag``, -``writable_iterator_tag``, ``swappable_iterator_tag``, or if the -argument for ``TraversalTag`` is not convertible to +If the argument for ``TraversalTag`` is not convertible to ``incrementable_iterator_tag`` then the programm is ill-formed. -The ``access_category`` and ``traversal_category`` class templates are -traits classes. For iterators whose -``iterator_traits::iterator_category`` type is ``iterator_tag``, -the ``access_category`` and ``traversal_category`` traits access the -``access`` and ``traversal`` member types within ``iterator_tag``. -For iterators whose ``iterator_traits::iterator_category`` type -is not ``iterator_tag`` and instead is a tag convertible to one of the -original tags, the appropriate traversal and access tags are deduced. -The following pseudo-code describes the algorithm. +The ``is_readable``, ``is_writable``, ``is_swappable``, and +``traversal_category`` class templates are traits classes. For +iterators whose ``iterator_traits::iterator_category`` type is +``iterator_tag``, these traits obtain the ``access`` enum and +``traversal`` member type from within ``iterator_tag``. For iterators +whose ``iterator_traits::iterator_category`` type is not +``iterator_tag`` and instead is a tag convertible to one of the +original tags, the appropriate traversal tag and access bits are +deduced. The following pseudo-code describes the algorithm. :: - access-category(Iterator) = + is-readable(Iterator) = cat = iterator_traits::iterator_category; if (cat == iterator_tag) - return Access; + return Access % readable_iterator; + else if (cat is convertible to input_iterator_tag) + return true; + else + return false; + + is-writable(Iterator) = + cat = iterator_traits::iterator_category; + if (cat == iterator_tag) + return Access % writable_iterator; + else if (cat is convertible to forward_iterator_tag + or output_iterator_tag) + return true; + else + return false; + + is-swappable(Iterator) = + cat = iterator_traits::iterator_category; + if (cat == iterator_tag) + return Access % swappable_iterator; else if (cat is convertible to forward_iterator_tag) { if (iterator_traits::reference is a const reference) - return readable_lvalue_iterator_tag; + return false; else - return writable_lvalue_iterator_tag; - } else if (cat is convertible to input_iterator_tag) - return readable_iterator_tag; - else if (cat is convertible to output_iterator_tag) - return writable_iterator_tag; - else - return null_category_tag; + return true; + } else + return false; traversal-category(Iterator) = cat = iterator_traits::iterator_category; @@ -746,15 +723,18 @@ category tags for pointer types. :: template - struct access_category - { - typedef readable_lvalue_iterator_tag type; - }; + struct is_readable { typedef true_type type; }; template - struct access_category - { - typedef writable_lvalue_iterator_tag type; - }; + struct is_writable { typedef false_type type; }; + template + struct is_swappable { typedef false_type type; }; + + template + struct is_readable { typedef true_type type; }; + template + struct is_writable { typedef true_type type; }; + template + struct is_swappable { typedef true_type type; }; template struct traversal_category @@ -763,7 +743,6 @@ category tags for pointer types. }; -.. We need to document the requirements for the type parameters of iterator_tag. .. LocalWords: Abrahams Siek Witt const bool Sutter's WG int UL LI href Lvalue From 50ab6355935b269e8f326b13f036d717468552c1 Mon Sep 17 00:00:00 2001 From: Thomas Witt Date: Mon, 22 Sep 2003 08:43:20 +0000 Subject: [PATCH 217/265] Changed email address. [SVN r20148] --- doc/facade-and-adaptor.rst | 2 +- doc/new-iter-concepts.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/facade-and-adaptor.rst b/doc/facade-and-adaptor.rst index e06567b..9ed64a1 100644 --- a/doc/facade-and-adaptor.rst +++ b/doc/facade-and-adaptor.rst @@ -3,7 +3,7 @@ +++++++++++++++++++++++++++++ :Author: David Abrahams, Jeremy Siek, Thomas Witt -:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@acm.org :organization: `Boost Consulting`_, Indiana University `Open Systems Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 157bf28..ef9ecd9 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -3,7 +3,7 @@ ++++++++++++++++++++++ :Author: David Abrahams, Jeremy Siek, Thomas Witt -:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@acm.org :organization: `Boost Consulting`_, Indiana University `Open Systems Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ :Number: **This document is a revised version of the official** N1477=03-0060 From f6cbffeda0ae71e253d87ea1c77a2679ca4e4fb5 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 22 Sep 2003 13:58:20 +0000 Subject: [PATCH 218/265] updated to match the rst file [SVN r20150] --- doc/new-iter-concepts.html | 226 ++++++++++++++++--------------------- 1 file changed, 98 insertions(+), 128 deletions(-) diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index 0df8278..f7d1636 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -7,7 +7,7 @@ New Iterator Concepts - + @@ -25,7 +25,7 @@

- + @@ -57,22 +57,21 @@ is a revision of paper Readable Iterators [lib.readable.iterators]
  • Writable Iterators [lib.writable.iterators]
  • Swappable Iterators [lib.swappable.iterators]
  • -
  • Readable Lvalue Iterators [lib.readable.lvalue.iterators]
  • -
  • Writable Lvalue Iterators [lib.writable.lvalue.iterators]
  • +
  • Lvalue Iterators [lib.lvalue.iterators]
  • -
  • Iterator Traversal Concepts [lib.iterator.traversal]
  • -
  • Addition to [lib.iterator.synopsis]
  • -
  • Addition to [lib.iterator.traits]
  • +
  • Addition to [lib.iterator.synopsis]
  • +
  • Addition to [lib.iterator.traits]
  • @@ -236,12 +235,8 @@ set of concepts handles the syntax and semantics of value access:

  • Readable Iterator
  • Writable Iterator
  • Swappable Iterator
  • -
  • Readable Lvalue Iterator
  • -
  • Writable Lvalue Iterator
  • +
  • Lvalue Iterator
  • -

    The refinement relationships among these iterator concepts are given -in the following diagram.

    -

    access.png

    The access concepts describe requirements related to operator* and operator->, including the value_type, reference, and pointer associated types.

    @@ -269,17 +264,17 @@ given in the following diagram.

    dispatching. There are two hierarchies of tags, one for the access concepts and one for the traversal concepts. The tags are related via inheritance so that a tag is convertible to another tag if the concept -associated with the first tag is a refinement of the second tag. We -use virtual inheritance of the diamonds in the current hierarchy, and -because of possible diamonds that could be created when programmers -define new iterator concepts and the corresponding tags.

    +associated with the first tag is a refinement of the second tag. +There is not a tag for Lvalue Iterator because one can easily deduce +whether an iterator is an Lvalue Iterator by checking whether +iterator_traits<Iterator>::reference is a real reference.

    We provide an access mechanism for mapping iterator types to the new tags. Our design reuses iterator_traits<Iter>::iterator_category as the access mechanism. To enable this, a pair of access and traversal tags are combined into a single type using the following iterator_tag class.

    -template <class AccessTag, class TraversalTag>
    +template <class AccessTag, class Reference, class TraversalTag>
     struct iterator_tag : /* appropriate old category or categories */
     {
       typedef AccessTag access;
    @@ -357,9 +352,8 @@ member of type T.

    iterator_traits<X>::value_type
    - - + + @@ -399,9 +393,8 @@ output.

    - - + + @@ -435,6 +428,10 @@ semantics.

    + + + + @@ -447,9 +444,9 @@ semantics.

    is also a model of Swappable Iterator. --end note]
    -
    -

    Readable Lvalue Iterators [lib.readable.lvalue.iterators]

    -

    The Readable Lvalue Iterator concept adds the requirement that the +

    +

    Lvalue Iterators [lib.lvalue.iterators]

    +

    The Lvalue Iterator concept adds the requirement that the reference type be a reference to the value type of the iterator.

    Organization: Boost Consulting, Indiana University Open Systems Lab, University of Hanover Institute for Transport Railway Operation and Construction
    Date:2003-09-20
    2003-09-22
    Number:This document is a revised version of the official N1477=03-0060
    Copyright: 
    access_category<X>::typeConvertible to -readable_iterator_tag
    is_readable<X>::typetruetype  
    *a
    access_category<X>::typeConvertible to -writable_iterator_tag
    is_writable<X>::typetrue_type  
    *a = o
    is_swappable<X>::typetrue_type 
    iter_swap(a, b) void post: the pointed to values are exchanged
    @@ -459,7 +456,7 @@ semantics.

    - + @@ -474,53 +471,19 @@ semantics.

    where cv is an optional cv-qualification
    - - - - - -
    Readable Lvalue Iterator Requirements (in addition to Readable Iterator)
    Lvalue Iterator Requirements
    Expression Return Type
    access_category<X>::typeConvertible to -readable_lvalue_iterator_tag 
    - -
    -
    -

    Writable Lvalue Iterators [lib.writable.lvalue.iterators]

    -

    The Writable Lvalue Iterator concept adds the requirement that the -reference type be a non-const reference to the value type of the -iterator.

    -
    - ---- - - - - - - - - - - - - - -
    Writable Lvalue Iterator Requirements (in addition to Readable Lvalue Iterator)
    ExpressionReturn Type
    iterator_traits<X>::referenceiterator_traits<X>::value_type&
    access_category<X>::typeConvertible to writable_lvalue_iterator_tag
    -

    Iterator Traversal Concepts [lib.iterator.traversal]

    +

    Iterator Traversal Concepts [lib.iterator.traversal]

    In the tables below, X is an iterator type, a and b are constant objects of type X, r and s are mutable objects of type X, T is std::iterator_traits<X>::value_type, and v is a constant object of type T.

    -

    Incrementable Iterators [lib.incrementable.iterators]

    +

    Incrementable Iterators [lib.incrementable.iterators]

    A class or built-in type X models the Incrementable Iterator concept if the following expressions are valid and respect the stated semantics.

    @@ -557,7 +520,7 @@ semantics.

    -

    Single Pass Iterators [lib.single.pass.iterators]

    +

    Single Pass Iterators [lib.single.pass.iterators]

    A class or built-in type X models the Single Pass Iterator concept if the following expressions are valid and respect the stated semantics.

    @@ -602,7 +565,7 @@ its domain
    -

    Forward Traversal Iterators [lib.forward.traversal.iterators]

    +

    Forward Traversal Iterators [lib.forward.traversal.iterators]

    A class or built-in type X models the Forward Traversal Iterator concept if the following expressions are valid and respect the stated semantics.

    @@ -648,7 +611,7 @@ the distance between iterators
    -

    Bidirectional Traversal Iterators [lib.bidirectional.traversal.iterators]

    +

    Bidirectional Traversal Iterators [lib.bidirectional.traversal.iterators]

    A class or built-in type X models the Bidirectional Traversal Iterator concept if the following expressions are valid and respect the stated semantics.

    @@ -690,7 +653,7 @@ dereferenceable. --(++r)
    -

    Random Access Traversal Iterators [lib.random.access.traversal.iterators]

    +

    Random Access Traversal Iterators [lib.random.access.traversal.iterators]

    A class or built-in type X models the Random Access Traversal Iterator concept if the following expressions are valid and respect the stated semantics. In the table below, Distance is @@ -805,31 +768,23 @@ relation

    -

    Addition to [lib.iterator.synopsis]

    +

    Addition to [lib.iterator.synopsis]

     // lib.iterator.traits, traits and tags
    -template <class Iterator> struct access_category;
    +template <class Iterator> struct is_readable;
    +template <class Iterator> struct is_writable;
    +template <class Iterator> struct is_swappable;
     template <class Iterator> struct traversal_category;
     
    -template <class AccessTag, class TraversalTag>
    +enum iterator_access { readable_iterator = 1, writable_iterator = 2, 
    +    swappable_iterator = 4, lvalue_iterator = 8 };
    +
    +template <iterator_access x, class TraversalTag>
     struct iterator_tag : /* appropriate old category or categories */ {
    -  typedef AccessTag access;
    +  static const iterator_access access = x;
       typedef TraversalTag traversal;
     };
     
    -struct readable_iterator_tag { };
    -struct writable_iterator_tag { };
    -struct swappable_iterator_tag { };
    -struct readable_writable_iterator_tag
    -  : virtual readable_iterator_tag
    -  , virtual writable_iterator_tag
    -  , virtual swappable_iterator_tag { };
    -struct readable_lvalue_iterator_tag 
    -  : virtual readable_iterator_tag { };
    -struct writable_lvalue_iterator_tag
    -  : virtual public readable_writable_iterator_tag
    -  , virtual public readable_lvalue_iterator_tag { };
    -
     struct incrementable_iterator_tag { };
     struct single_pass_iterator_tag : incrementable_iterator_tag { };
     struct forward_traversal_tag : single_pass_iterator_tag { };
    @@ -841,15 +796,15 @@ struct input_output_iterator_tag : input_iterator_tag, output_iterator_tag {};
     
    -

    Addition to [lib.iterator.traits]

    +

    Addition to [lib.iterator.traits]

    The iterator_tag class template is an iterator category tag that -encodes the access and traversal tags in addition to being compatible +encodes the access enum and traversal tag in addition to being compatible with the original iterator tags. The iterator_tag class inherits from one of the original iterator tags according to the following pseudo-code.

    -inherit-category(access-tag, traversal-tag) =
    -     if (access-tag is convertible to readable_lvalue_iterator_tag) {
    +inherit-category(access, traversal-tag) =
    +     if (access & lvalue_iterator) {
              if (traversal-tag is convertible to random_access_traversal_tag)
                  return random_access_iterator_tag;
              else if (traversal-tag is convertible to bidirectional_traversal_tag)
    @@ -861,52 +816,64 @@ inherit-category(access-tag, traversal-tag) =
                      return input_output_iterator_tag;
                  else
                      return input_iterator_tag;
    -         else if (access-tag is convertible to writable_iterator_tag)
    +         else if (access & writable_iterator)
                  return output_iterator_tag;
              else
                  return null_category_tag;
    -     } else if (access-tag is convertible to readable_writable_iterator_tag
    +     } else if ((access & readable_iterator) and (access & writable_iterator)
                     and traversal-tag is convertible to single_pass_iterator_tag)
              return input_output_iterator_tag;
    -     else if (access-tag is convertible to readable_iterator_tag
    +     else if (access & readable_iterator
                   and traversal-tag is convertible to single_pass_iterator_tag)
              return input_iterator_tag;
    -     else if (access-tag is convertible to writable_iterator_tag
    +     else if (access & writable_iterator
                   and traversal-tag is convertible to incrementable_iterator_tag)
              return output_iterator_tag;
          else
              return null_category_tag;
     
    -

    If the argument for the template parameter AccessTag is not -convertible to one or more of: readable_iterator_tag, -writable_iterator_tag, swappable_iterator_tag, or if the -argument for TraversalTag is not convertible to +

    If the argument for TraversalTag is not convertible to incrementable_iterator_tag then the programm is ill-formed.

    -

    The access_category and traversal_category class templates are -traits classes. For iterators whose -iterator_traits<Iter>::iterator_category type is iterator_tag, -the access_category and traversal_category traits access the -access and traversal member types within iterator_tag. -For iterators whose iterator_traits<Iter>::iterator_category type -is not iterator_tag and instead is a tag convertible to one of the -original tags, the appropriate traversal and access tags is deduced. -The following pseudo-code describes the algorithm.

    +

    The is_readable, is_writable, is_swappable, and +traversal_category class templates are traits classes. For +iterators whose iterator_traits<Iter>::iterator_category type is +iterator_tag, these traits obtain the access enum and +traversal member type from within iterator_tag. For iterators +whose iterator_traits<Iter>::iterator_category type is not +iterator_tag and instead is a tag convertible to one of the +original tags, the appropriate traversal tag and access bits are +deduced. The following pseudo-code describes the algorithm.

    -access-category(Iterator) =
    +is-readable(Iterator) = 
         cat = iterator_traits<Iterator>::iterator_category;
         if (cat == iterator_tag<Access,Traversal>)
    -        return Access;
    +        return Access % readable_iterator;
    +    else if (cat is convertible to input_iterator_tag)
    +        return true;
    +    else
    +        return false;
    +
    +is-writable(Iterator) =
    +    cat = iterator_traits<Iterator>::iterator_category;
    +    if (cat == iterator_tag<Access,Traversal>)
    +        return Access % writable_iterator;
    +    else if (cat is convertible to forward_iterator_tag
    +             or output_iterator_tag)
    +        return true;
    +    else
    +        return false;
    +
    +is-swappable(Iterator) =
    +    cat = iterator_traits<Iterator>::iterator_category;
    +    if (cat == iterator_tag<Access,Traversal>)
    +        return Access % swappable_iterator;
         else if (cat is convertible to forward_iterator_tag) {
             if (iterator_traits<Iterator>::reference is a const reference)
    -            return readable_lvalue_iterator_tag;
    +            return false;
             else
    -            return writable_lvalue_iterator_tag;
    -    } else if (cat is convertible to input_iterator_tag)
    -        return readable_iterator_tag;
    -    else if (cat is convertible to output_iterator_tag)
    -        return writable_iterator_tag;
    -    else
    -        return null_category_tag;
    +            return true;
    +    } else 
    +        return false;
     
     traversal-category(Iterator) =
         cat = iterator_traits<Iterator>::iterator_category;
    @@ -929,15 +896,18 @@ traversal-category(Iterator) =
     category tags for pointer types.

     template <typename T>
    -struct access_category<const T*>
    -{
    -  typedef readable_lvalue_iterator_tag type;
    -};
    +struct is_readable<const T*> { typedef true_type type; };
     template <typename T>
    -struct access_category<T*>
    -{
    -  typedef writable_lvalue_iterator_tag type;
    -};
    +struct is_writable<const T*> { typedef false_type type; };
    +template <typename T>
    +struct is_swappable<const T*> { typedef false_type type; };
    +
    +template <typename T>
    +struct is_readable<T*> { typedef true_type type; };
    +template <typename T>
    +struct is_writable<T*> { typedef true_type type; };
    +template <typename T>
    +struct is_swappable<T*> { typedef true_type type; };
     
     template <typename T>
     struct traversal_category<T*>
    
    From 1710c484b3a51700ed4678f6034b6cd7a8140882 Mon Sep 17 00:00:00 2001
    From: Dave Abrahams 
    Date: Mon, 22 Sep 2003 15:10:34 +0000
    Subject: [PATCH 219/265] Table formatting tweaks for PDF/tex generation. Some
     minor editing for language improvements.
    
    [SVN r20151]
    ---
     doc/counting_iterator.html        |   6 +-
     doc/facade-and-adaptor.html       | 260 ++++++++++++++++---
     doc/filter_iterator.html          |   6 +-
     doc/function_output_iterator.html |   6 +-
     doc/index.html                    |   2 +-
     doc/indirect_iterator.html        |   6 +-
     doc/iterator_adaptor.html         |   6 +-
     doc/iterator_adaptor_ref.rst      |  22 +-
     doc/iterator_facade.html          |   6 +-
     doc/new-iter-concepts.html        | 403 +++++++++++++++++++++++-------
     doc/new-iter-concepts.rst         | 373 ++++++++++++++-------------
     doc/permutation_iterator.html     |   6 +-
     doc/reverse_iterator.html         |   6 +-
     13 files changed, 782 insertions(+), 326 deletions(-)
    
    diff --git a/doc/counting_iterator.html b/doc/counting_iterator.html
    index 6fd0e36..c5390c2 100644
    --- a/doc/counting_iterator.html
    +++ b/doc/counting_iterator.html
    @@ -7,7 +7,7 @@
     Counting Iterator
     
     
    -
    +
     
     
     
    @@ -27,7 +27,7 @@
     Lab, University of Hanover Institute for Transport
     Railway Operation and Construction
     Date:
    -2003-08-05
    +2003-09-14
     Copyright:
     Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
     
    @@ -143,7 +143,7 @@ object copy constructed from x
     
     
     
    diff --git a/doc/facade-and-adaptor.html b/doc/facade-and-adaptor.html
    index aa0cde4..747de28 100755
    --- a/doc/facade-and-adaptor.html
    +++ b/doc/facade-and-adaptor.html
    @@ -7,9 +7,200 @@
     Iterator Facade and Adaptor
     
     
    -
    +
     
    -
    +
     
     
     
    @@ -21,13 +212,13 @@ Author: David Abrahams, Jeremy Siek, Thomas Witt Contact: -dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +dave@boost-consulting.com, jsiek@osl.iu.edu, witt@acm.org Organization: Boost Consulting, Indiana University Open Systems Lab, University of Hanover Institute for Transport Railway Operation and Construction Date: -2003-08-05 +2003-09-22 Number:This document is a revised version of the official N1476=03-0059 Copyright: @@ -965,11 +1156,12 @@ class iterator_adaptor expressions involving m_iterator in the specifications of those private member functions of iterator_adaptor that are not redefined by the Derived class and that are needed to model the -concept corresponding to the iterator_adaptor's category -typedef according to the requirements of iterator_facade. The -rest of the template parameters specify the types for the member -typedefs in iterator_facade. The following pseudo-code -specifies the traits types for iterator_adaptor.

    +concept corresponding to +iterator_traits<Derived>::iterator_category according to the +requirements of iterator_facade. The rest of the template +parameters specify the types for the member typedefs in +iterator_facade. The following pseudo-code specifies the +traits types for iterator_adaptor.

     if (Value == use_default)
         value_type = iterator_traits<Base>::value_type;
    @@ -994,12 +1186,17 @@ if (Category == use_default)
             access_category< Base >,
             traversal_category< Base >
         >
    -else if (Category is an access tag)
    +else if (Category is convertible to a standard access tag)
         iterator_category = iterator_tag<
             Category
    -    ...
    +    else if (Category has a nested traversal type)
    +         if (reference is not a reference-to-const)
    +             Category::access
    +         else
    +             if (Category
    +        
     
    -else if (Category is a traversal tag)
    +else if (Category is convertable to a standard traversal tag)
         ...
     else
         iterator_category = Category;
    @@ -1369,7 +1566,7 @@ then returns the result.

    Class template transform_iterator

    -template <class AdaptableUnaryFunction,
    +template <class UnaryFunction,
               class Iterator, 
               class Reference = use_default, 
               class Value = use_default>
    @@ -1379,45 +1576,44 @@ class transform_iterator
       friend class iterator_core_access;
     public:
       transform_iterator();
    -  transform_iterator(Iterator const& x, AdaptableUnaryFunction f);
    +  transform_iterator(Iterator const& x, UnaryFunction f);
     
       template<class OtherIterator, class R2, class V2>
       transform_iterator(
    -        transform_iterator<AdaptableUnaryFunction, OtherIterator, R2, V2> const& t
    +        transform_iterator<UnaryFunction, OtherIterator, R2, V2> const& t
           , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
       );
     
    -  AdaptableUnaryFunction functor() const;
    +  UnaryFunction functor() const;
     private:
       typename transform_iterator::value_type dereference() const;
    -  AdaptableUnaryFunction m_f;
    +  UnaryFunction m_f;
     };
     

    transform_iterator requirements

    -

    The type AdaptableUnaryFunction must be Assignable, Copy -Constructible, and the expression f(x) must be valid where f -is an object of type AdaptableUnaryFunction, x is an object of -type AdaptableUnaryFunction::argument_type, and where the type of -f(x) must be AdaptableUnaryFunction::result_type.

    +

    The type UnaryFunction must be Assignable, Copy Constructible, and +the expression f(*i) must be valid where f is an object of +type UnaryFunction, i is an object of type Iterator, and +where the type of f(*i) must be +result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type.

    The type Iterator must at least model Readable Iterator. The resulting transform_iterator models the most refined of the following options that is also modeled by Iterator.

      -
    • Writable Lvalue Iterator if the result_type of the -AdaptableUnaryFunction is a non-const reference.
    • -
    • Readable Lvalue Iterator if the result_type is a const +
    • Writable Lvalue Iterator if result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type is a non-const reference.
    • +
    • Readable Lvalue Iterator if result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type is a const reference.
    • Readable Iterator otherwise.

    The transform_iterator models the most refined standard traversal concept that is modeled by Iterator.

    -

    The value_type of transform_iterator is -remove_reference<result_type>::type. The reference type is -result_type.

    +

    The reference type of transform_iterator is +result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type. +The value_type is remove_cv<remove_reference<reference> >::type.

    transform_iterator public operations

    @@ -1431,7 +1627,7 @@ and m_iterator default constru -

    transform_iterator(Iterator const& x, AdaptableUnaryFunction f);

    +

    transform_iterator(Iterator const& x, UnaryFunction f);

    @@ -1444,7 +1640,7 @@ initialized to f and template<class OtherIterator, class R2, class V2> transform_iterator( - transform_iterator<AdaptableUnaryFunction, OtherIterator, R2, V2> const& t + transform_iterator<UnaryFunction, OtherIterator, R2, V2> const& t , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition ); @@ -1458,7 +1654,7 @@ transform_iterator(
    -

    AdaptableUnaryFunction functor() const;

    +

    UnaryFunction functor() const;

    @@ -1847,7 +2043,7 @@ LocalWords: OtherIncrementable Coplien --> diff --git a/doc/filter_iterator.html b/doc/filter_iterator.html index 4133ae5..2afaf83 100644 --- a/doc/filter_iterator.html +++ b/doc/filter_iterator.html @@ -7,7 +7,7 @@ Filter Iterator - + @@ -27,7 +27,7 @@ Lab, University of Hanover Institute for Transport Railway Operation and Construction - + @@ -189,7 +189,7 @@ filter_iterator( diff --git a/doc/function_output_iterator.html b/doc/function_output_iterator.html index 30d4559..90e2d2f 100644 --- a/doc/function_output_iterator.html +++ b/doc/function_output_iterator.html @@ -7,7 +7,7 @@ Function Output Iterator - + @@ -27,7 +27,7 @@ Lab, University of Hanover Institute for Transport Railway Operation and Construction - + @@ -158,7 +158,7 @@ return *this; diff --git a/doc/index.html b/doc/index.html index 37421eb..3dfe4a0 100755 --- a/doc/index.html +++ b/doc/index.html @@ -181,7 +181,7 @@ LocalWords: TraversalTag typename lvalues DWA Hmm JGS --> diff --git a/doc/indirect_iterator.html b/doc/indirect_iterator.html index 9bbc80b..fafefb5 100644 --- a/doc/indirect_iterator.html +++ b/doc/indirect_iterator.html @@ -7,7 +7,7 @@ Indirect Iterator - + @@ -27,7 +27,7 @@ Lab, University of Hanover Institute for Transport Railway Operation and Construction - + @@ -162,7 +162,7 @@ indirect_iterator( diff --git a/doc/iterator_adaptor.html b/doc/iterator_adaptor.html index d34598e..ec328a9 100644 --- a/doc/iterator_adaptor.html +++ b/doc/iterator_adaptor.html @@ -7,7 +7,7 @@ Iterator Adaptor - + @@ -27,7 +27,7 @@ Lab, University of Hanover Institute for Transport Railway Operation and Construction - + @@ -328,7 +328,7 @@ typename iterator_adaptor::difference_type distance_to( diff --git a/doc/iterator_adaptor_ref.rst b/doc/iterator_adaptor_ref.rst index 69c6aa7..af910f5 100644 --- a/doc/iterator_adaptor_ref.rst +++ b/doc/iterator_adaptor_ref.rst @@ -51,11 +51,12 @@ The ``Derived`` template parameter must be a derived class of expressions involving ``m_iterator`` in the specifications of those private member functions of ``iterator_adaptor`` that are not redefined by the ``Derived`` class and that are needed to model the -concept corresponding to the ``iterator_adaptor``\ 's ``category`` -typedef according to the requirements of ``iterator_facade``. The -rest of the template parameters specify the types for the member -typedefs in ``iterator_facade``. The following pseudo-code -specifies the traits types for ``iterator_adaptor``. +concept corresponding to +``iterator_traits::iterator_category`` according to the +requirements of ``iterator_facade``. The rest of the template +parameters specify the types for the member typedefs in +``iterator_facade``. The following pseudo-code specifies the +traits types for ``iterator_adaptor``. :: @@ -82,12 +83,17 @@ specifies the traits types for ``iterator_adaptor``. access_category< Base >, traversal_category< Base > > - else if (Category is an access tag) + else if (Category is convertible to a standard access tag) iterator_category = iterator_tag< Category - ... + else if (Category has a nested traversal type) + if (reference is not a reference-to-const) + Category::access + else + if (Category + - else if (Category is a traversal tag) + else if (Category is convertable to a standard traversal tag) ... else iterator_category = Category; diff --git a/doc/iterator_facade.html b/doc/iterator_facade.html index 84f7e25..af5d672 100644 --- a/doc/iterator_facade.html +++ b/doc/iterator_facade.html @@ -7,7 +7,7 @@ Iterator Facade - + @@ -27,7 +27,7 @@ Lab, University of Hanover Institute for Transport Railway Operation and Construction - + @@ -573,7 +573,7 @@ return tmp -= n; diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index f7d1636..26c2651 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -3,13 +3,204 @@ - +New Iterator Concepts - +
    @@ -21,7 +212,7 @@
    - + @@ -96,6 +287,10 @@ requirements in the iterator categories.

    + + + + @@ -176,7 +371,9 @@ following lists the proposed changes to the type requirements of algorithms.

    Forward Iterator -> Forward Traversal Iterator and Readable Iterator

    -find_end, adjacent_find, search, search_n, rotate_copy, lower_bound, upper_bound, equal_range, binary_search, min_element, max_element
    +find_end, adjacent_find, search, search_n, rotate_copy, +lower_bound, upper_bound, equal_range, binary_search, +min_element, max_element

    Forward Iterator (1) -> Single Pass Iterator and Readable Iterator Forward Iterator (2) -> Forward Traversal Iterator and Readable Iterator

    @@ -229,7 +426,7 @@ Bidirectional Iterator (2) -> Bidirectional Traversal Iterator and Writable I

    Design

    -

    The iterator requirements are be separated into two hierarchies. One +

    The iterator requirements are to be separated into two hierarchies. One set of concepts handles the syntax and semantics of value access:

    • Readable Iterator
    • @@ -260,7 +457,7 @@ matches with the original input and output iterator requirements.

      The relationship between the new iterator concepts and the old are given in the following diagram.

      oldeqnew.png

      -

      Like the old iterator requirements, we provide tags for purposes of +

      As in the existing library, we provide tags for purposes of dispatching. There are two hierarchies of tags, one for the access concepts and one for the traversal concepts. The tags are related via inheritance so that a tag is convertible to another tag if the concept @@ -270,7 +467,7 @@ whether an iterator is an Lvalue Iterator by checking whether iterator_traits<Iterator>::reference is a real reference.

      We provide an access mechanism for mapping iterator types to the new tags. Our design reuses iterator_traits<Iter>::iterator_category -as the access mechanism. To enable this, a pair of access and +as the access mechanism. To that end, a pair of access and traversal tags are combined into a single type using the following iterator_tag class.

      @@ -327,25 +524,25 @@ object of type T.

      for the value type T if the following expressions are valid and respect the stated semantics. U is the type of any specified member of type T.

      -
    Date:2003-08-05
    2003-09-14
    Copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
    Date:2003-08-05
    2003-09-14
    Copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
    Date:2003-08-05
    2003-09-14
    Copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
    Date:2003-08-05
    2003-09-14
    Copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
    Date:2003-08-05
    2003-09-14
    Copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
    Author: David Abrahams, Jeremy Siek, Thomas Witt
    Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
    dave@boost-consulting.com, jsiek@osl.iu.edu, witt@acm.org
    Organization: Boost Consulting, Indiana University Open Systems Lab, University of Hanover Institute for Transport Railway Operation and Construction
    Date:
    Value Access Requirements in Existing Iterator Categories
    Output Iterator *i = a
    ---+++ - + - + - + - + - +
    Readable Iterator Requirements (in addition to CopyConstructible)
    Expression Return TypeAssertion/Note/Precondition/PostconditionNote/Precondition
    iterator_traits<X>::value_type TAny non-reference, non-cv-qualified typeAny non-reference, +non-cv-qualified type
    iterator_traits<X>::reference Convertible to @@ -353,22 +550,24 @@ member of type T.

     
    is_readable<X>::typetruetypetrue_type  
    *a iterator_traits<X>::referencepre: a is dereferenceable. If a == -b then *a is equivalent to *bpre: a is +dereferenceable. If a +== b then *a is +equivalent to *b
    a->m U&pre: (*a).m is well-defined. -Equivalent to (*a).mpre: (*a).m is +well-defined. Equivalent +to (*a).m
    -

    Writable Iterators [lib.writable.iterators]

    @@ -377,12 +576,11 @@ if the following expressions are valid and respect the stated semantics. In addition, a model of Writable Iterator must include in its documentation the set of value types that it allows for output.

    -
    ++-- @@ -405,19 +603,17 @@ value types of X
    Writable Iterator Requirements (in addition to CopyConstructible)
    -

    Swappable Iterators [lib.swappable.iterators]

    A class or built-in type X models the Swappable Iterator concept if the following expressions are valid and respect the stated semantics.

    -
    ---+++ @@ -434,11 +630,11 @@ semantics.

    - +
    Swappable Iterator Requirements (in addition to CopyConstructible)
    iter_swap(a, b) voidpost: the pointed to values are exchangedthe pointed to values are +exchanged
    -
    [Note: An iterator that is a model of the Readable and Writable Iterator concepts
    is also a model of Swappable Iterator. --end note]
    @@ -448,12 +644,11 @@ semantics.

    Lvalue Iterators [lib.lvalue.iterators]

    The Lvalue Iterator concept adds the requirement that the reference type be a reference to the value type of the iterator.

    -
    ---+++ @@ -473,7 +668,6 @@ cv-qualification
    Lvalue Iterator Requirements
    -
    @@ -487,12 +681,11 @@ type X, A class or built-in type X models the Incrementable Iterator concept if the following expressions are valid and respect the stated semantics.

    -
    ---+++ @@ -509,47 +702,56 @@ semantics.

    - + - +
    Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible)
    r++ X{ X tmp = r; ++r; return tmp; }
    +{
    +   X tmp = r;
    +   ++r;
    +   return tmp;
    +}
    +
    +
    traversal_category<X>::typeConvertible to incrementable_iterator_tagConvertible to +incrementable_iterator_tag  
    -

    Single Pass Iterators [lib.single.pass.iterators]

    A class or built-in type X models the Single Pass Iterator concept if the following expressions are valid and respect the stated semantics.

    -
    +--+ - + - + - + - + @@ -562,19 +764,17 @@ its domain
    Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality Comparable)
    Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality +Comparable)
    Expression Return TypeAssertion/Semantics/Pre-/Post-conditionAssertion/Semantics / +Pre-/Post-condition
    ++r X&pre: r is dereferenceable; post: -r is dereferenceable or r is -past-the-endpre: r is +dereferenceable; post: +r is dereferenceable or +r is past-the-end
    a == b convertible to bool== is an equivalence relation over -its domain== is an equivalence +relation over its domain
    a != b convertible to bool
    -

    Forward Traversal Iterators [lib.forward.traversal.iterators]

    A class or built-in type X models the Forward Traversal Iterator concept if the following expressions are valid and respect the stated semantics.

    -
    +--+ @@ -587,14 +787,17 @@ semantics.

    - + - +
    Forward Traversal Iterator Requirements (in addition to Single Pass Iterator)
    X u; X&note: u may have a -singular value.note: u may +have a singular +value.
    ++r X&r == s and r is -dereferenceable implies -++r == ++s.r == s and +r is +dereferenceable +implies ++r +== ++s.
    iterator_traits<X>::difference_type A signed integral type representing @@ -608,40 +811,50 @@ the distance between iterators
    -

    Bidirectional Traversal Iterators [lib.bidirectional.traversal.iterators]

    A class or built-in type X models the Bidirectional Traversal Iterator concept if the following expressions are valid and respect the stated semantics.

    -
    --++ - + - + - +
    Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal Iterator)
    Expression Return TypeAssertion/Semantics/Pre-/Post-conditionAssertion/Semantics / +Pre-/Post-condition
    --r X&pre: there exists s such that r -== ++s. post: s is -dereferenceable. --(++r) == r. ---r == --s implies r == s. &r -== &--r.pre: there exists +s such that r +== ++s. post: +s is +dereferenceable. +--(++r) == r. +--r == --s +implies r == +s. &r == &--r.
    r-- convertible to const X&{ X tmp = r; --r; return tmp; }
    +{
    +  X tmp = r;
    +  --r;
    +  return tmp;
    +}
    +
    +
    traversal_category<X>::type Convertible to @@ -650,7 +863,6 @@ dereferenceable. --(++r)
    -

    Random Access Traversal Iterators [lib.random.access.traversal.iterators]

    @@ -659,13 +871,12 @@ Iterator concept if the following expressions are valid and respect the stated semantics. In the table below, Distance is iterator_traits<X>::difference_type and n represents a constant object of type Distance.

    -
    --++-+ @@ -673,7 +884,8 @@ constant object of type Distance - + @@ -696,8 +908,8 @@ constant object of type Distance - + @@ -707,19 +919,19 @@ constant object of type Distance - + - - + + @@ -736,14 +948,14 @@ iterator - + - + @@ -763,7 +975,6 @@ relation
    Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal Iterator)Expression Return Type Operational SemanticsAssertion/PreconditionAssertion/ +Precondition
    a + n, n + a X{ X tmp = a; return -tmp += n; }{ X tmp = a; return tmp ++= n; }  
    r -= n
    a - n X{ X tmp = a; return -tmp -= n; }{ X tmp = a; return tmp +-= n; }  
    b - a Distancea < b ? -distance(a,b) : --distance(b,a)pre: there exists a value -n of Distance such -that a + n == b. b == -a + (b - a).a < b ?  distance(a,b) +: -distance(b,a)pre: there exists a +value n of +Distance such that +a + n == b. b +== a + (b - a).
    a[n] convertible to T
    a < b convertible to bool b - a > 0< is a total ordering -relation< is a total +ordering relation
    a > b convertible to bool b < a> is a total ordering -relation> is a total +ordering relation
    a >= b convertible to bool
    -
    @@ -925,5 +1136,11 @@ LocalWords: TraversalTag typename lvalues DWA Hmm JGS --> + + diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index ef9ecd9..fdde1cc 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -42,7 +42,9 @@ requirements that address value access sneak in at various places. The following table gives a summary of the current value access requirements in the iterator categories. -+------------------------+-----------------------------------------------------+ ++------------------------------------------------------------------------------+ +|Value Access Requirements in Existing Iterator Categories | ++========================+=====================================================+ |Output Iterator |``*i = a`` | +------------------------+-----------------------------------------------------+ |Input Iterator |``*i`` is convertible to ``T`` | @@ -138,7 +140,9 @@ algorithms. Forward Iterator -> Forward Traversal Iterator and Readable Iterator - ``find_end, adjacent_find, search, search_n, rotate_copy, lower_bound, upper_bound, equal_range, binary_search, min_element, max_element`` + ``find_end, adjacent_find, search, search_n, rotate_copy, + lower_bound, upper_bound, equal_range, binary_search, + min_element, max_element`` Forward Iterator (1) -> Single Pass Iterator and Readable Iterator Forward Iterator (2) -> Forward Traversal Iterator and Readable Iterator @@ -203,7 +207,7 @@ Input Iterator (2) -> Incrementable Iterator and Readable Iterator Design ======== -The iterator requirements are be separated into two hierarchies. One +The iterator requirements are to be separated into two hierarchies. One set of concepts handles the syntax and semantics of value access: - Readable Iterator @@ -240,7 +244,7 @@ given in the following diagram. .. image:: oldeqnew.png -Like the old iterator requirements, we provide tags for purposes of +As in the existing library, we provide tags for purposes of dispatching. There are two hierarchies of tags, one for the access concepts and one for the traversal concepts. The tags are related via inheritance so that a tag is convertible to another tag if the concept @@ -252,7 +256,7 @@ whether an iterator is an Lvalue Iterator by checking whether We provide an access mechanism for mapping iterator types to the new tags. Our design reuses ``iterator_traits::iterator_category`` -as the access mechanism. To enable this, a pair of access and +as the access mechanism. To that end, a pair of access and traversal tags are combined into a single type using the following `iterator_tag` class. @@ -325,24 +329,28 @@ for the value type ``T`` if the following expressions are valid and respect the stated semantics. ``U`` is the type of any specified member of type ``T``. - +-------------------------------------------------------------------------------------------------------------------+ - |Readable Iterator Requirements (in addition to CopyConstructible) | - +--------------------------------------+----------------------------------+-----------------------------------------+ - |Expression |Return Type |Assertion/Note/Precondition/Postcondition| - +======================================+==================================+=========================================+ - |``iterator_traits::value_type`` |``T`` |Any non-reference, non-cv-qualified type | - +--------------------------------------+----------------------------------+-----------------------------------------+ - |``iterator_traits::reference`` |Convertible to | | - | |``iterator_traits::value_type``| | - +--------------------------------------+----------------------------------+-----------------------------------------+ - |``is_readable::type`` |``truetype`` | | - +--------------------------------------+----------------------------------+-----------------------------------------+ - |``*a`` |``iterator_traits::reference`` |pre: ``a`` is dereferenceable. If ``a == | - | | |b`` then ``*a`` is equivalent to ``*b`` | - +--------------------------------------+----------------------------------+-----------------------------------------+ - |``a->m`` |``U&`` |pre: ``(*a).m`` is well-defined. | - | | |Equivalent to ``(*a).m`` | - +--------------------------------------+----------------------------------+-----------------------------------------+ ++-------------------------------------------------------------------------------------------------+ +|Readable Iterator Requirements (in addition to CopyConstructible) | ++-----------------------------------+-----------------------------------+-------------------------+ +|Expression |Return Type |Note/Precondition | ++===================================+===================================+=========================+ +|``iterator_traits::value_type`` |``T`` |Any non-reference, | +| | |non-cv-qualified type | ++-----------------------------------+-----------------------------------+-------------------------+ +|``iterator_traits::reference`` |Convertible to | | +| |``iterator_traits::value_type`` | | ++-----------------------------------+-----------------------------------+-------------------------+ +|``is_readable::type`` |``true_type`` | | ++-----------------------------------+-----------------------------------+-------------------------+ +|``*a`` |``iterator_traits::reference`` |pre: ``a`` is | +| | |dereferenceable. If ``a | +| | |== b`` then ``*a`` is | +| | |equivalent to ``*b`` | ++-----------------------------------+-----------------------------------+-------------------------+ +|``a->m`` |``U&`` |pre: ``(*a).m`` is | +| | |well-defined. Equivalent| +| | |to ``(*a).m`` | ++-----------------------------------+-----------------------------------+-------------------------+ .. _Writable Iterator: @@ -356,17 +364,17 @@ semantics. In addition, a model of *Writable Iterator* must include in its documentation the *set of value types* that it allows for output. - +---------------------------------------------------------------------------------------------+ - |Writable Iterator Requirements (in addition to CopyConstructible) | - +--------------------------------------+-------------------------+----------------------------+ - |Expression |Return Type |Precondition | - +======================================+=========================+============================+ - |``is_writable::type`` |``true_type`` | | - +--------------------------------------+-------------------------+----------------------------+ - |``*a = o`` | | pre: The type of ``o`` | - | | | is in the set of | - | | | value types of ``X`` | - +--------------------------------------+-------------------------+----------------------------+ ++---------------------------------------------------------------------+ +|Writable Iterator Requirements (in addition to CopyConstructible) | ++-------------------------+--------------+----------------------------+ +|Expression |Return Type |Precondition | ++=========================+==============+============================+ +|``is_writable::type`` |``true_type`` | | ++-------------------------+--------------+----------------------------+ +|``*a = o`` | | pre: The type of ``o`` | +| | | is in the set of | +| | | value types of ``X`` | ++-------------------------+--------------+----------------------------+ @@ -377,15 +385,16 @@ A class or built-in type ``X`` models the *Swappable Iterator* concept if the following expressions are valid and respect the stated semantics. - +------------------------------------------------------------------------------------------------+ - |Swappable Iterator Requirements (in addition to CopyConstructible) | - +------------------------------------+-------------+---------------------------------------------+ - |Expression |Return Type |Postcondition | - +====================================+=============+=============================================+ - |``is_swappable::type`` |``true_type``| | - +------------------------------------+-------------+---------------------------------------------+ - |``iter_swap(a, b)`` |``void`` |post: the pointed to values are exchanged | - +------------------------------------+-------------+---------------------------------------------+ ++---------------------------------------------------------------------+ +|Swappable Iterator Requirements (in addition to CopyConstructible) | ++-------------------------+-------------+-----------------------------+ +|Expression |Return Type |Postcondition | ++=========================+=============+=============================+ +|``is_swappable::type``|``true_type``| | ++-------------------------+-------------+-----------------------------+ +|``iter_swap(a, b)`` |``void`` |the pointed to values are | +| | |exchanged | ++-------------------------+-------------+-----------------------------+ [*Note:* An iterator that is a model of the *Readable* and *Writable Iterator* concepts is also a model of *Swappable Iterator*. *--end note*] @@ -397,16 +406,16 @@ Lvalue Iterators [lib.lvalue.iterators] The *Lvalue Iterator* concept adds the requirement that the ``reference`` type be a reference to the value type of the iterator. - +----------------------------------------------------------------------------------------------------------+ - | Lvalue Iterator Requirements | - +------------------------------------+---------------------------------+-----------------------------------+ - |Expression |Return Type |Assertion | - +====================================+=================================+===================================+ - |``iterator_traits::reference`` |``T&`` |``T`` is *cv* | - | | |``iterator_traits::value_type`` | - | | |where *cv* is an optional | - | | |cv-qualification | - +------------------------------------+---------------------------------+-----------------------------------+ ++---------------------------------------------------------------------------------+ +| Lvalue Iterator Requirements | ++---------------------------------+-----------+-----------------------------------+ +|Expression |Return Type|Assertion | ++=================================+===========+===================================+ +|``iterator_traits::reference``|``T&`` |``T`` is *cv* | +| | |``iterator_traits::value_type`` | +| | |where *cv* is an optional | +| | |cv-qualification | ++---------------------------------+-----------+-----------------------------------+ Iterator Traversal Concepts [lib.iterator.traversal] @@ -426,17 +435,25 @@ concept if the following expressions are valid and respect the stated semantics. - +-------------------------------------------------------------------------------------------------------------------------+ - |Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible) | - +--------------------------------+---------------------------------------------+------------------------------------------+ - |Expression |Return Type |Assertion/Semantics | - +================================+=============================================+==========================================+ - |``++r`` |``X&`` |``&r == &++r`` | - +--------------------------------+---------------------------------------------+------------------------------------------+ - |``r++`` |``X`` |``{ X tmp = r; ++r; return tmp; }`` | - +--------------------------------+---------------------------------------------+------------------------------------------+ - |``traversal_category::type`` |Convertible to ``incrementable_iterator_tag``| | - +--------------------------------+---------------------------------------------+------------------------------------------+ ++-------------------------------------------------------------------------------------+ +|Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible) | +| | ++--------------------------------+-------------------------------+--------------------+ +|Expression |Return Type |Assertion/Semantics | ++================================+===============================+====================+ +|``++r`` |``X&`` |``&r == &++r`` | ++--------------------------------+-------------------------------+--------------------+ +|``r++`` |``X`` |:: | +| | | | +| | | { | +| | | X tmp = r; | +| | | ++r; | +| | | return tmp; | +| | | } | ++--------------------------------+-------------------------------+--------------------+ +|``traversal_category::type`` |Convertible to | | +| |``incrementable_iterator_tag`` | | ++--------------------------------+-------------------------------+--------------------+ Single Pass Iterators [lib.single.pass.iterators] @@ -447,23 +464,26 @@ concept if the following expressions are valid and respect the stated semantics. - +--------------------------------------------------------------------------------------------------------+ - |Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality Comparable) | - +----------------------------------+----------------------------+----------------------------------------+ - |Expression |Return Type |Assertion/Semantics/Pre-/Post-condition | - +==================================+============================+========================================+ - |``++r`` |``X&`` |pre: ``r`` is dereferenceable; post: | - | | |``r`` is dereferenceable or ``r`` is | - | | |past-the-end | - +----------------------------------+----------------------------+----------------------------------------+ - |``a == b`` |convertible to ``bool`` |``==`` is an equivalence relation over | - | | |its domain | - +----------------------------------+----------------------------+----------------------------------------+ - |``a != b`` |convertible to ``bool`` |``!(a == b)`` | - +----------------------------------+----------------------------+----------------------------------------+ - |``traversal_category::type`` |Convertible to | | - | |``single_pass_iterator_tag``| | - +----------------------------------+----------------------------+----------------------------------------+ ++------------------------------------------------------------------------------------------+ +|Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality | +|Comparable) | ++--------------------------------+-----------------------------+---------------------------+ +|Expression |Return Type |Assertion/Semantics / | +| | |Pre-/Post-condition | ++================================+=============================+===========================+ +|``++r`` |``X&`` |pre: ``r`` is | +| | |dereferenceable; post: | +| | |``r`` is dereferenceable or| +| | |``r`` is past-the-end | ++--------------------------------+-----------------------------+---------------------------+ +|``a == b`` |convertible to ``bool`` |``==`` is an equivalence | +| | |relation over its domain | ++--------------------------------+-----------------------------+---------------------------+ +|``a != b`` |convertible to ``bool`` |``!(a == b)`` | ++--------------------------------+-----------------------------+---------------------------+ +|``traversal_category::type`` |Convertible to | | +| |``single_pass_iterator_tag`` | | ++--------------------------------+-----------------------------+---------------------------+ Forward Traversal Iterators [lib.forward.traversal.iterators] @@ -473,24 +493,28 @@ A class or built-in type ``X`` models the *Forward Traversal Iterator* concept if the following expressions are valid and respect the stated semantics. - +------------------------------------------------------------------------------------------------------+ - |Forward Traversal Iterator Requirements (in addition to Single Pass Iterator) | - +---------------------------------------+-------------------------------------+------------------------+ - |Expression |Return Type |Assertion/Note | - +=======================================+=====================================+========================+ - |``X u;`` |``X&`` |``note: u may have a | - | | |singular value.`` | - +---------------------------------------+-------------------------------------+------------------------+ - |``++r`` |``X&`` |``r == s`` and ``r`` is | - | | |dereferenceable implies | - | | |``++r == ++s.`` | - +---------------------------------------+-------------------------------------+------------------------+ - |``iterator_traits::difference_type``|A signed integral type representing | | - | |the distance between iterators | | - +---------------------------------------+-------------------------------------+------------------------+ - |``traversal_category::type`` |Convertible to | | - | |``forward_traversal_iterator_tag`` | | - +---------------------------------------+-------------------------------------+------------------------+ ++-------------------------------------------------------------------------------------------+ +|Forward Traversal Iterator Requirements (in addition to Single Pass Iterator) | ++---------------------------------------+-----------------------------------+---------------+ +|Expression |Return Type |Assertion/Note | ++=======================================+===================================+===============+ +|``X u;`` |``X&`` |note: ``u`` may| +| | |have a singular| +| | |value. | ++---------------------------------------+-----------------------------------+---------------+ +|``++r`` |``X&`` |``r == s`` and | +| | |``r`` is | +| | |dereferenceable| +| | |implies ``++r | +| | |== ++s.`` | ++---------------------------------------+-----------------------------------+---------------+ +|``iterator_traits::difference_type``|A signed integral type representing| | +| |the distance between iterators | | +| | | | ++---------------------------------------+-----------------------------------+---------------+ +|``traversal_category::type`` |Convertible to | | +| |``forward_traversal_iterator_tag`` | | ++---------------------------------------+-----------------------------------+---------------+ Bidirectional Traversal Iterators [lib.bidirectional.traversal.iterators] @@ -500,25 +524,34 @@ A class or built-in type ``X`` models the *Bidirectional Traversal Iterator* concept if the following expressions are valid and respect the stated semantics. - +----------------------------------------------------------------------------------------------------------------+ - |Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal Iterator) | - +-------------------------------+----------------------------------------+---------------------------------------+ - |Expression |Return Type |Assertion/Semantics/Pre-/Post-condition| - +===============================+========================================+=======================================+ - |``--r`` |``X&`` |pre: there exists ``s`` such that ``r | - | | |== ++s``. post: ``s`` is | - | | |dereferenceable. ``--(++r) == r``. | - | | |``--r == --s`` implies ``r == s``. ``&r| - | | |== &--r``. | - +-------------------------------+----------------------------------------+---------------------------------------+ - |``r--`` |convertible to ``const X&`` |``{ X tmp = r; --r; return tmp; }`` | - | | | | - | | | | - +-------------------------------+----------------------------------------+---------------------------------------+ - |``traversal_category::type``|Convertible to | | - | |``bidirectional_traversal_iterator_tag``| | - | | | | - +-------------------------------+----------------------------------------+---------------------------------------+ ++--------------------------------------------------------------------------------------------------------+ +|Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal Iterator) | ++------------------------------------+---------------------------------------------+---------------------+ +|Expression |Return Type |Assertion/Semantics /| +| | |Pre-/Post-condition | ++====================================+=============================================+=====================+ +|``--r`` |``X&`` |pre: there exists | +| | |``s`` such that ``r | +| | |== ++s``. post: | +| | |``s`` is | +| | |dereferenceable. | +| | |``--(++r) == r``. | +| | |``--r == --s`` | +| | |implies ``r == | +| | |s``. ``&r == &--r``. | ++------------------------------------+---------------------------------------------+---------------------+ +|``r--`` |convertible to ``const X&`` |:: | +| | | | +| | | { | +| | | X tmp = r; | +| | | --r; | +| | | return tmp; | +| | | } | ++------------------------------------+---------------------------------------------+---------------------+ +|``traversal_category::type`` |Convertible to | | +| |``bidirectional_traversal_iterator_tag`` | | +| | | | ++------------------------------------+---------------------------------------------+---------------------+ Random Access Traversal Iterators [lib.random.access.traversal.iterators] @@ -530,56 +563,60 @@ the stated semantics. In the table below, ``Distance`` is ``iterator_traits::difference_type`` and ``n`` represents a constant object of type ``Distance``. - +------------------------------------------------------------------------------------------------------------------------------+ - |Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal Iterator) | - +--------------------------------+----------------------------------------+----------------------+-----------------------------+ - | Expression |Return Type | Operational Semantics| Assertion/Precondition | - +================================+========================================+======================+=============================+ - |``r += n`` |``X&`` |:: | | - | | | | | - | | | { | | - | | | Distance m = n; | | - | | | if (m >= 0) | | - | | | while (m--) | | - | | | ++r; | | - | | | else | | - | | | while (m++) | | - | | | --r; | | - | | | return r; | | - | | | } | | - +--------------------------------+----------------------------------------+----------------------+-----------------------------+ - | ``a + n``, ``n + a`` |``X`` |``{ X tmp = a; return | | - | | |tmp += n; }`` | | - +--------------------------------+----------------------------------------+----------------------+-----------------------------+ - |``r -= n`` |``X&`` |``return r += -n`` | | - +--------------------------------+----------------------------------------+----------------------+-----------------------------+ - |``a - n`` |``X`` |``{ X tmp = a; return | | - | | |tmp -= n; }`` | | - +--------------------------------+----------------------------------------+----------------------+-----------------------------+ - |``b - a`` |``Distance`` |``a < b ? |pre: there exists a value | - | | |distance(a,b) : |``n`` of ``Distance`` such | - | | |-distance(b,a)`` |that ``a + n == b``. ``b == | - | | | |a + (b - a)``. | - +--------------------------------+----------------------------------------+----------------------+-----------------------------+ - |``a[n]`` |convertible to T |``*(a + n)`` |pre: a is a `readable | - | | | |iterator`_ | - +--------------------------------+----------------------------------------+----------------------+-----------------------------+ - |``a[n] = v`` |convertible to T |``*(a + n) = v`` |pre: a is a `writable | - | | | |iterator`_ | - +--------------------------------+----------------------------------------+----------------------+-----------------------------+ - |``a < b`` |convertible to ``bool`` |``b - a > 0`` |``<`` is a total ordering | - | | | |relation | - +--------------------------------+----------------------------------------+----------------------+-----------------------------+ - |``a > b`` |convertible to ``bool`` |``b < a`` |``>`` is a total ordering | - | | | |relation | - +--------------------------------+----------------------------------------+----------------------+-----------------------------+ - |``a >= b`` |convertible to ``bool`` |``!(a < b)`` | | - +--------------------------------+----------------------------------------+----------------------+-----------------------------+ - |``a <= b`` |convertible to ``bool`` |``!(a > b)`` | | - +--------------------------------+----------------------------------------+----------------------+-----------------------------+ - |``traversal_category::type`` |Convertible to | | | - | |``random_access_traversal_iterator_tag``| | | - +--------------------------------+----------------------------------------+----------------------+-----------------------------+ ++----------------------------------------------------------------------------------------------------------------------------------------------+ +|Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal Iterator) | ++-------------------------------------------+-------------------------------------------------+-------------------------+----------------------+ +|Expression |Return Type |Operational Semantics |Assertion/ | +| | | |Precondition | ++===========================================+=================================================+=========================+======================+ +|``r += n`` |``X&`` |:: | | +| | | | | +| | | { | | +| | | Distance m = n; | | +| | | if (m >= 0) | | +| | | while (m--) | | +| | | ++r; | | +| | | else | | +| | | while (m++) | | +| | | --r; | | +| | | return r; | | +| | | } | | ++-------------------------------------------+-------------------------------------------------+-------------------------+----------------------+ +|``a + n``, ``n + a`` |``X`` |``{ X tmp = a; return tmp| | +| | |+= n; }`` | | +| | | | | ++-------------------------------------------+-------------------------------------------------+-------------------------+----------------------+ +|``r -= n`` |``X&`` |``return r += -n`` | | ++-------------------------------------------+-------------------------------------------------+-------------------------+----------------------+ +|``a - n`` |``X`` |``{ X tmp = a; return tmp| | +| | |-= n; }`` | | +| | | | | ++-------------------------------------------+-------------------------------------------------+-------------------------+----------------------+ +|``b - a`` |``Distance`` |``a < b ? distance(a,b) |pre: there exists a | +| | |: -distance(b,a)`` |value ``n`` of | +| | | |``Distance`` such that| +| | | |``a + n == b``. ``b | +| | | |== a + (b - a)``. | ++-------------------------------------------+-------------------------------------------------+-------------------------+----------------------+ +|``a[n]`` |convertible to T |``*(a + n)`` |pre: a is a `readable | +| | | |iterator`_ | ++-------------------------------------------+-------------------------------------------------+-------------------------+----------------------+ +|``a[n] = v`` |convertible to T |``*(a + n) = v`` |pre: a is a `writable | +| | | |iterator`_ | ++-------------------------------------------+-------------------------------------------------+-------------------------+----------------------+ +|``a < b`` |convertible to ``bool`` |``b - a > 0`` |``<`` is a total | +| | | |ordering relation | ++-------------------------------------------+-------------------------------------------------+-------------------------+----------------------+ +|``a > b`` |convertible to ``bool`` |``b < a`` |``>`` is a total | +| | | |ordering relation | ++-------------------------------------------+-------------------------------------------------+-------------------------+----------------------+ +|``a >= b`` |convertible to ``bool`` |``!(a < b)`` | | ++-------------------------------------------+-------------------------------------------------+-------------------------+----------------------+ +|``a <= b`` |convertible to ``bool`` |``!(a > b)`` | | ++-------------------------------------------+-------------------------------------------------+-------------------------+----------------------+ +|``traversal_category::type`` |Convertible to | | | +| |``random_access_traversal_iterator_tag`` | | | ++-------------------------------------------+-------------------------------------------------+-------------------------+----------------------+ diff --git a/doc/permutation_iterator.html b/doc/permutation_iterator.html index 4549786..bfa30dd 100644 --- a/doc/permutation_iterator.html +++ b/doc/permutation_iterator.html @@ -7,7 +7,7 @@ Permutation Iterator - + @@ -26,7 +26,7 @@ Boost Consulting, Indiana University Open Systems Lab Date: -2003-08-05 +2003-09-14 Copyright: Copyright Toon Knapen, David Abrahams, Roland Richter, and Jeremy Siek 2003. All rights reserved @@ -121,7 +121,7 @@ ForwardIterator instead of amortized constant time.

    diff --git a/doc/reverse_iterator.html b/doc/reverse_iterator.html index 3aba842..ac3ceaf 100644 --- a/doc/reverse_iterator.html +++ b/doc/reverse_iterator.html @@ -7,7 +7,7 @@ Reverse Iterator - + @@ -27,7 +27,7 @@ Lab, University of Hanover Institute for Transport Railway Operation and Construction Date: -2003-08-05 +2003-09-14 Copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved @@ -136,7 +136,7 @@ reverse_iterator( From 9ac583096c540110c0fa488981e00ab5fe1f9e96 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 22 Sep 2003 15:45:58 +0000 Subject: [PATCH 220/265] added the paper number and resolved some conflicts [SVN r20152] --- doc/new-iter-concepts.html | 261 +++++-------------------------------- doc/new-iter-concepts.rst | 57 ++++---- 2 files changed, 68 insertions(+), 250 deletions(-) diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index 26c2651..8a1e639 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -3,204 +3,13 @@ - + New Iterator Concepts - +
    @@ -217,7 +26,7 @@ ul.auto-toc { Boost Consulting, Indiana University Open Systems Lab, University of Hanover Institute for Transport Railway Operation and Construction Date: 2003-09-22 -Number:This document is a revised version of the official N1477=03-0060 +Number:N1531=03-0114 Copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved @@ -232,7 +41,7 @@ access and positioning independently. This allows the concepts to more closely match the requirements of algorithms and provides better categorizations of iterators that are used in practice. This proposal -is a revision of paper n1297. +is a revision of paper n1297 and n1477. @@ -374,7 +183,7 @@ algorithms.

    find_end, adjacent_find, search, search_n, rotate_copy, lower_bound, upper_bound, equal_range, binary_search, min_element, max_element -

    Forward Iterator (1) -> Single Pass Iterator and Readable Iterator +

    Forward Iterator (1) -> Single Pass Iterator and Readable Iterator, Forward Iterator (2) -> Forward Traversal Iterator and Readable Iterator

    find_first_of
    @@ -387,7 +196,7 @@ Forward Iterator (2) -> Forward Traversal Iterator and Readable Iterator

    Forward Iterator -> Forward Traversal Iterator and Swappable Iterator

    rotate
    -

    Forward Iterator (1) -> Swappable Iterator and Single Pass Iterator +

    Forward Iterator (1) -> Swappable Iterator and Single Pass Iterator, Forward Iterator (2) -> Swappable Iterator and Incrementable Iterator

    swap_ranges
    @@ -457,30 +266,31 @@ matches with the original input and output iterator requirements.

    The relationship between the new iterator concepts and the old are given in the following diagram.

    oldeqnew.png

    -

    As in the existing library, we provide tags for purposes of -dispatching. There are two hierarchies of tags, one for the access -concepts and one for the traversal concepts. The tags are related via +

    Like the old iterator requirements, we provide tags for purposes of +dispatching based on the traversal concepts. The tags are related via inheritance so that a tag is convertible to another tag if the concept associated with the first tag is a refinement of the second tag. -There is not a tag for Lvalue Iterator because one can easily deduce -whether an iterator is an Lvalue Iterator by checking whether -iterator_traits<Iterator>::reference is a real reference.

    +Since the access concepts are not related via refinment, but instead +cover orthogonal issues, we do not use tags for the access concepts, +but instead use the equivalent of a bitfield.

    We provide an access mechanism for mapping iterator types to the new -tags. Our design reuses iterator_traits<Iter>::iterator_category -as the access mechanism. To that end, a pair of access and -traversal tags are combined into a single type using the following -iterator_tag class.

    +traversal tags and access bitfield. Our design reuses +iterator_traits<Iter>::iterator_category as the access +mechanism. To that end, a pair of access and traversal tags are +combined into a single type using the following iterator_tag class.

    -template <class AccessTag, class Reference, class TraversalTag>
    -struct iterator_tag : /* appropriate old category or categories */
    -{
    -  typedef AccessTag access;
    +enum iterator_access { readable_iterator = 1, writable_iterator = 2, 
    +    swappable_iterator = 4, lvalue_iterator = 8 };
    +
    +template <iterator_access x, class TraversalTag>
    +struct iterator_tag : /* appropriate old category or categories */ {
    +  static const iterator_access access = x;
       typedef TraversalTag traversal;
     };
     

    The iterator_tag class template is derived from the appropriate iterator tag or tags from the old requirements based on the new-style -tags passed as template parameters. The algorithm for determining the +tags passed as template parameters. The algorithm for determining the old tag or tags from the new tags picks the least-refined old concepts that include all of the requirements of the access and traversal concepts (that is, the closest fit), if any such category exists. For @@ -488,15 +298,22 @@ example, a the category tag for a Readable Single Pass Iterator will always be derived from input_iterator_tag, while the category tag for a Single Pass Iterator that is both Readable and Writable will be derived from both input_iterator_tag and output_iterator_tag.

    -

    We also provide two helper classes that make it convenient to obtain -the access and traversal tags of an iterator. These helper classes -work both for iterators whose iterator_category is +

    We also provide several helper classes that make it convenient to +obtain the access and traversal characteristics of an iterator. These +helper classes work both for iterators whose iterator_category is iterator_tag and also for iterators using the original iterator categories.

    -
    -template <class Iterator> struct access_category { typedef ... type; };
    -template <class Iterator> struct traversal_category { typedef ... type; };
    -
    +
    +
    ::
    +

    template <class Iterator> struct is_readable { typedef ... type; }; +template <class Iterator> struct is_writable { typedef ... type; }; +template <class Iterator> struct is_swappable { typedef ... type; }; +template <class Iterator> struct traversal_category { typedef ... type; };

    +
    +
    +

    We do not include a helper class is_lvalue_iterator because that +can easily be deduced by checking whether +iterator_traits<Iterator>::reference is a real reference.

    The most difficult design decision concerned the operator[]. The direct approach for specifying operator[] would have a return type of reference; the same as operator*. However, going in this @@ -1136,11 +953,5 @@ LocalWords: TraversalTag typename lvalues DWA Hmm JGS -->

    - - diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index fdde1cc..90ea9b8 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -6,7 +6,7 @@ :Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@acm.org :organization: `Boost Consulting`_, Indiana University `Open Systems Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:Number: **This document is a revised version of the official** N1477=03-0060 +:Number: N1531=03-0114 :copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com @@ -18,11 +18,12 @@ concepts to more closely match the requirements of algorithms and provides better categorizations of iterators that are used in practice. This proposal - is a revision of paper n1297_. + is a revision of paper n1297_ and n1477_. .. contents:: Table of Contents .. _n1297: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2001/n1297.html +.. _n1477: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1477.html ============ Motivation @@ -144,7 +145,7 @@ Forward Iterator -> Forward Traversal Iterator and Readable Iterator lower_bound, upper_bound, equal_range, binary_search, min_element, max_element`` -Forward Iterator (1) -> Single Pass Iterator and Readable Iterator +Forward Iterator (1) -> Single Pass Iterator and Readable Iterator, Forward Iterator (2) -> Forward Traversal Iterator and Readable Iterator ``find_first_of`` @@ -161,7 +162,7 @@ Forward Iterator -> Forward Traversal Iterator and Swappable Iterator ``rotate`` -Forward Iterator (1) -> Swappable Iterator and Single Pass Iterator +Forward Iterator (1) -> Swappable Iterator and Single Pass Iterator, Forward Iterator (2) -> Swappable Iterator and Incrementable Iterator ``swap_ranges`` @@ -244,34 +245,34 @@ given in the following diagram. .. image:: oldeqnew.png -As in the existing library, we provide tags for purposes of -dispatching. There are two hierarchies of tags, one for the access -concepts and one for the traversal concepts. The tags are related via +Like the old iterator requirements, we provide tags for purposes of +dispatching based on the traversal concepts. The tags are related via inheritance so that a tag is convertible to another tag if the concept associated with the first tag is a refinement of the second tag. -There is not a tag for Lvalue Iterator because one can easily deduce -whether an iterator is an Lvalue Iterator by checking whether -``iterator_traits::reference`` is a real reference. - +Since the access concepts are not related via refinment, but instead +cover orthogonal issues, we do not use tags for the access concepts, +but instead use the equivalent of a bitfield. We provide an access mechanism for mapping iterator types to the new -tags. Our design reuses ``iterator_traits::iterator_category`` -as the access mechanism. To that end, a pair of access and -traversal tags are combined into a single type using the following -`iterator_tag` class. +traversal tags and access bitfield. Our design reuses +``iterator_traits::iterator_category`` as the access +mechanism. To that end, a pair of access and traversal tags are +combined into a single type using the following `iterator_tag` class. :: - template - struct iterator_tag : /* appropriate old category or categories */ - { - typedef AccessTag access; + enum iterator_access { readable_iterator = 1, writable_iterator = 2, + swappable_iterator = 4, lvalue_iterator = 8 }; + + template + struct iterator_tag : /* appropriate old category or categories */ { + static const iterator_access access = x; typedef TraversalTag traversal; }; The ``iterator_tag`` class template is derived from the appropriate iterator tag or tags from the old requirements based on the new-style -tags passed as template parameters. The algorithm for determining the +tags passed as template parameters. The algorithm for determining the old tag or tags from the new tags picks the least-refined old concepts that include all of the requirements of the access and traversal concepts (that is, the closest fit), if any such category exists. For @@ -280,18 +281,24 @@ always be derived from ``input_iterator_tag``, while the category tag for a Single Pass Iterator that is both Readable and Writable will be derived from both ``input_iterator_tag`` and ``output_iterator_tag``. -We also provide two helper classes that make it convenient to obtain -the access and traversal tags of an iterator. These helper classes -work both for iterators whose ``iterator_category`` is +We also provide several helper classes that make it convenient to +obtain the access and traversal characteristics of an iterator. These +helper classes work both for iterators whose ``iterator_category`` is ``iterator_tag`` and also for iterators using the original iterator categories. :: - - template struct access_category { typedef ... type; }; + template struct is_readable { typedef ... type; }; + template struct is_writable { typedef ... type; }; + template struct is_swappable { typedef ... type; }; template struct traversal_category { typedef ... type; }; +We do not include a helper class ``is_lvalue_iterator`` because that +can easily be deduced by checking whether +``iterator_traits::reference`` is a real reference. + + The most difficult design decision concerned the ``operator[]``. The direct approach for specifying ``operator[]`` would have a return type of ``reference``; the same as ``operator*``. However, going in this From 5efcabf3bda0dc7a2aee8f071132feb2f64a3f37 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 22 Sep 2003 15:55:22 +0000 Subject: [PATCH 221/265] small change to iterator_tag body [SVN r20154] --- doc/new-iter-concepts.html | 12 ++++++++---- doc/new-iter-concepts.rst | 14 +++++++++----- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index 8a1e639..380256b 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -807,9 +807,9 @@ template <class Iterator> struct traversal_category; enum iterator_access { readable_iterator = 1, writable_iterator = 2, swappable_iterator = 4, lvalue_iterator = 8 }; -template <iterator_access x, class TraversalTag> +template <unsigned int access_bits, class TraversalTag> struct iterator_tag : /* appropriate old category or categories */ { - static const iterator_access access = x; + static const iterator_access access = (iterator_access)access_bits; typedef TraversalTag traversal; }; @@ -860,8 +860,12 @@ inherit-category(access, traversal-tag) = else return null_category_tag; -

    If the argument for TraversalTag is not convertible to -incrementable_iterator_tag then the programm is ill-formed.

    +

    The access argument is declared to be unsigned int instead of the +enum iterator_access for convenience of use. For example, the +expression (readable_iterator | writable_iterator) produces an +unsigned int, not iterator_access. If the argument for +TraversalTag is not convertible to incrementable_iterator_tag +then the programm is ill-formed.

    The is_readable, is_writable, is_swappable, and traversal_category class templates are traits classes. For iterators whose iterator_traits<Iter>::iterator_category type is diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 90ea9b8..dca1700 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -642,9 +642,9 @@ Addition to [lib.iterator.synopsis] enum iterator_access { readable_iterator = 1, writable_iterator = 2, swappable_iterator = 4, lvalue_iterator = 8 }; - template + template struct iterator_tag : /* appropriate old category or categories */ { - static const iterator_access access = x; + static const iterator_access access = (iterator_access)access_bits; typedef TraversalTag traversal; }; @@ -696,9 +696,13 @@ pseudo-code. return output_iterator_tag; else return null_category_tag; - -If the argument for ``TraversalTag`` is not convertible to -``incrementable_iterator_tag`` then the programm is ill-formed. + +The access argument is declared to be ``unsigned int`` instead of the +enum ``iterator_access`` for convenience of use. For example, the +expression ``(readable_iterator | writable_iterator)`` produces an +unsigned int, not ``iterator_access``. If the argument for +``TraversalTag`` is not convertible to ``incrementable_iterator_tag`` +then the programm is ill-formed. The ``is_readable``, ``is_writable``, ``is_swappable``, and ``traversal_category`` class templates are traits classes. For From d68ac3db4c99ea058a9dca503abaf12efc94e21f Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 22 Sep 2003 16:04:44 +0000 Subject: [PATCH 222/265] hierarchy->group [SVN r20155] --- doc/new-iter-concepts.html | 8 ++++---- doc/new-iter-concepts.rst | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index 380256b..848c882 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -235,8 +235,8 @@ Bidirectional Iterator (2) -> Bidirectional Traversal Iterator and Writable I

    Design

    -

    The iterator requirements are to be separated into two hierarchies. One -set of concepts handles the syntax and semantics of value access:

    +

    The iterator requirements are to be separated into two groups. One set +of concepts handles the syntax and semantics of value access:

    • Readable Iterator
    • Writable Iterator
    • @@ -276,8 +276,8 @@ but instead use the equivalent of a bitfield.

      We provide an access mechanism for mapping iterator types to the new traversal tags and access bitfield. Our design reuses iterator_traits<Iter>::iterator_category as the access -mechanism. To that end, a pair of access and traversal tags are -combined into a single type using the following iterator_tag class.

      +mechanism. To that end, the access and traversal information is +bundled into a single type using the following iterator_tag class.

       enum iterator_access { readable_iterator = 1, writable_iterator = 2, 
           swappable_iterator = 4, lvalue_iterator = 8 };
      diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst
      index dca1700..381449d 100644
      --- a/doc/new-iter-concepts.rst
      +++ b/doc/new-iter-concepts.rst
      @@ -208,8 +208,8 @@ Input Iterator (2) -> Incrementable Iterator and Readable Iterator
        Design
       ========
       
      -The iterator requirements are to be separated into two hierarchies. One
      -set of concepts handles the syntax and semantics of value access:
      +The iterator requirements are to be separated into two groups. One set
      +of concepts handles the syntax and semantics of value access:
       
       - Readable Iterator
       - Writable Iterator
      @@ -256,8 +256,8 @@ but instead use the equivalent of a bitfield.
       We provide an access mechanism for mapping iterator types to the new
       traversal tags and access bitfield. Our design reuses
       ``iterator_traits::iterator_category`` as the access
      -mechanism. To that end, a pair of access and traversal tags are
      -combined into a single type using the following `iterator_tag` class.
      +mechanism. To that end, the access and traversal information is
      +bundled into a single type using the following `iterator_tag` class.
       
       ::
       
      
      From 20e28188449b6a9bc0dc71a429b875297b752f30 Mon Sep 17 00:00:00 2001
      From: Jeremy Siek 
      Date: Mon, 22 Sep 2003 16:07:24 +0000
      Subject: [PATCH 223/265] fixed iterator_tag in first part to match
       iterator_tag in the second part
      
      [SVN r20156]
      ---
       doc/new-iter-concepts.html | 4 ++--
       doc/new-iter-concepts.rst  | 4 ++--
       2 files changed, 4 insertions(+), 4 deletions(-)
      
      diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html
      index 848c882..284cef1 100755
      --- a/doc/new-iter-concepts.html
      +++ b/doc/new-iter-concepts.html
      @@ -282,9 +282,9 @@ bundled into a single type using the following iterator_tag class.<
       enum iterator_access { readable_iterator = 1, writable_iterator = 2, 
           swappable_iterator = 4, lvalue_iterator = 8 };
       
      -template <iterator_access x, class TraversalTag>
      +template <unsigned int access_bits, class TraversalTag>
       struct iterator_tag : /* appropriate old category or categories */ {
      -  static const iterator_access access = x;
      +  static const iterator_access access = (iterator_access)access_bits;
         typedef TraversalTag traversal;
       };
       
      diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 381449d..577bf99 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -264,9 +264,9 @@ bundled into a single type using the following `iterator_tag` class. enum iterator_access { readable_iterator = 1, writable_iterator = 2, swappable_iterator = 4, lvalue_iterator = 8 }; - template + template struct iterator_tag : /* appropriate old category or categories */ { - static const iterator_access access = x; + static const iterator_access access = (iterator_access)access_bits; typedef TraversalTag traversal; }; From a3856b5c60dadeeb160450300b0d81dcaa2a1e5c Mon Sep 17 00:00:00 2001 From: Thomas Witt Date: Mon, 22 Sep 2003 16:24:44 +0000 Subject: [PATCH 224/265] Typos [SVN r20157] --- doc/new-iter-concepts.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 577bf99..7d77512 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -249,7 +249,7 @@ Like the old iterator requirements, we provide tags for purposes of dispatching based on the traversal concepts. The tags are related via inheritance so that a tag is convertible to another tag if the concept associated with the first tag is a refinement of the second tag. -Since the access concepts are not related via refinment, but instead +Since the access concepts are not related via refinement, but instead cover orthogonal issues, we do not use tags for the access concepts, but instead use the equivalent of a bitfield. @@ -276,7 +276,7 @@ tags passed as template parameters. The algorithm for determining the old tag or tags from the new tags picks the least-refined old concepts that include all of the requirements of the access and traversal concepts (that is, the closest fit), if any such category exists. For -example, a the category tag for a Readable Single Pass Iterator will +example, the category tag for a Readable Single Pass Iterator will always be derived from ``input_iterator_tag``, while the category tag for a Single Pass Iterator that is both Readable and Writable will be derived from both ``input_iterator_tag`` and ``output_iterator_tag``. @@ -288,6 +288,7 @@ helper classes work both for iterators whose ``iterator_category`` is categories. :: + template struct is_readable { typedef ... type; }; template struct is_writable { typedef ... type; }; template struct is_swappable { typedef ... type; }; From d85b8db0aa3b8ccacac98d52e1e26200effe284b Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 22 Sep 2003 16:28:27 +0000 Subject: [PATCH 225/265] added more design rationale, and moved some text [SVN r20158] --- doc/new-iter-concepts.html | 41 +++++++++++++++++++++----------------- doc/new-iter-concepts.rst | 29 +++++++++++++++++---------- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index 284cef1..2167f3e 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -270,11 +270,11 @@ given in the following diagram.

      dispatching based on the traversal concepts. The tags are related via inheritance so that a tag is convertible to another tag if the concept associated with the first tag is a refinement of the second tag. -Since the access concepts are not related via refinment, but instead +Since the access concepts are not related via refinement, but instead cover orthogonal issues, we do not use tags for the access concepts, -but instead use the equivalent of a bitfield.

      +but instead use the equivalent of a bit field.

      We provide an access mechanism for mapping iterator types to the new -traversal tags and access bitfield. Our design reuses +traversal tags and access bit field. Our design reuses iterator_traits<Iter>::iterator_category as the access mechanism. To that end, the access and traversal information is bundled into a single type using the following iterator_tag class.

      @@ -284,17 +284,28 @@ enum iterator_access { readable_iterator = 1, writable_iterator = 2, template <unsigned int access_bits, class TraversalTag> struct iterator_tag : /* appropriate old category or categories */ { - static const iterator_access access = (iterator_access)access_bits; + static const iterator_access access = + (iterator_access)access_bits & + (readable_iterator | writable_iterator | swappable_iterator); typedef TraversalTag traversal; }; +

      The access_bits argument is declared to be unsigned int +instead of the enum iterator_access for convenience of use. For +example, the expression (readable_iterator | writable_iterator) +produces an unsigned int, not an iterator_access. The purpose of +the lvalue_iterator part of the iterator_access enum is to +communicate to iterator_tag whether the reference type is an +lvalue so that the appropriate old category can be chosen for the base +class. The lvalue_iterator bit is not recorded in the +iterator_tag::access data member.

      The iterator_tag class template is derived from the appropriate iterator tag or tags from the old requirements based on the new-style tags passed as template parameters. The algorithm for determining the old tag or tags from the new tags picks the least-refined old concepts that include all of the requirements of the access and traversal concepts (that is, the closest fit), if any such category exists. For -example, a the category tag for a Readable Single Pass Iterator will +example, the category tag for a Readable Single Pass Iterator will always be derived from input_iterator_tag, while the category tag for a Single Pass Iterator that is both Readable and Writable will be derived from both input_iterator_tag and output_iterator_tag.

      @@ -303,14 +314,12 @@ obtain the access and traversal characteristics of an iterator. These helper classes work both for iterators whose iterator_category is iterator_tag and also for iterators using the original iterator categories.

      -
      -
      ::
      -

      template <class Iterator> struct is_readable { typedef ... type; }; +

      +template <class Iterator> struct is_readable  { typedef ... type; };
       template <class Iterator> struct is_writable { typedef ... type; };
       template <class Iterator> struct is_swappable { typedef ... type; };
      -template <class Iterator> struct traversal_category { typedef ... type; };

      -
      -
      +template <class Iterator> struct traversal_category { typedef ... type; }; +

      We do not include a helper class is_lvalue_iterator because that can easily be deduced by checking whether iterator_traits<Iterator>::reference is a real reference.

      @@ -860,12 +869,8 @@ inherit-category(access, traversal-tag) = else return null_category_tag; -

      The access argument is declared to be unsigned int instead of the -enum iterator_access for convenience of use. For example, the -expression (readable_iterator | writable_iterator) produces an -unsigned int, not iterator_access. If the argument for -TraversalTag is not convertible to incrementable_iterator_tag -then the programm is ill-formed.

      +

      If the argument for TraversalTag is not convertible to +incrementable_iterator_tag then the program is ill-formed.

      The is_readable, is_writable, is_swappable, and traversal_category class templates are traits classes. For iterators whose iterator_traits<Iter>::iterator_category type is @@ -953,7 +958,7 @@ LocalWords: ConstantLvalueIterator MutableLvalueIterator CopyConstructible TR LocalWords: ForwardTraversalIterator BidirectionalTraversalIterator lvalue LocalWords: RandomAccessTraversalIterator dereferenceable Incrementable tmp LocalWords: incrementable xxx min prev inplace png oldeqnew AccessTag struct -LocalWords: TraversalTag typename lvalues DWA Hmm JGS --> +LocalWords: TraversalTag typename lvalues DWA Hmm JGS mis enum -->

    diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 7d77512..44642f7 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -251,10 +251,10 @@ inheritance so that a tag is convertible to another tag if the concept associated with the first tag is a refinement of the second tag. Since the access concepts are not related via refinement, but instead cover orthogonal issues, we do not use tags for the access concepts, -but instead use the equivalent of a bitfield. +but instead use the equivalent of a bit field. We provide an access mechanism for mapping iterator types to the new -traversal tags and access bitfield. Our design reuses +traversal tags and access bit field. Our design reuses ``iterator_traits::iterator_category`` as the access mechanism. To that end, the access and traversal information is bundled into a single type using the following `iterator_tag` class. @@ -266,10 +266,22 @@ bundled into a single type using the following `iterator_tag` class. template struct iterator_tag : /* appropriate old category or categories */ { - static const iterator_access access = (iterator_access)access_bits; + static const iterator_access access = + (iterator_access)access_bits & + (readable_iterator | writable_iterator | swappable_iterator); typedef TraversalTag traversal; }; +The ``access_bits`` argument is declared to be ``unsigned int`` +instead of the enum ``iterator_access`` for convenience of use. For +example, the expression ``(readable_iterator | writable_iterator)`` +produces an unsigned int, not an ``iterator_access``. The purpose of +the ``lvalue_iterator`` part of the ``iterator_access`` enum is to +communicate to ``iterator_tag`` whether the reference type is an +lvalue so that the appropriate old category can be chosen for the base +class. The ``lvalue_iterator`` bit is not recorded in the +``iterator_tag::access`` data member. + The ``iterator_tag`` class template is derived from the appropriate iterator tag or tags from the old requirements based on the new-style tags passed as template parameters. The algorithm for determining the @@ -281,6 +293,7 @@ always be derived from ``input_iterator_tag``, while the category tag for a Single Pass Iterator that is both Readable and Writable will be derived from both ``input_iterator_tag`` and ``output_iterator_tag``. + We also provide several helper classes that make it convenient to obtain the access and traversal characteristics of an iterator. These helper classes work both for iterators whose ``iterator_category`` is @@ -698,12 +711,8 @@ pseudo-code. else return null_category_tag; -The access argument is declared to be ``unsigned int`` instead of the -enum ``iterator_access`` for convenience of use. For example, the -expression ``(readable_iterator | writable_iterator)`` produces an -unsigned int, not ``iterator_access``. If the argument for -``TraversalTag`` is not convertible to ``incrementable_iterator_tag`` -then the programm is ill-formed. +If the argument for ``TraversalTag`` is not convertible to +``incrementable_iterator_tag`` then the program is ill-formed. The ``is_readable``, ``is_writable``, ``is_swappable``, and ``traversal_category`` class templates are traits classes. For @@ -800,4 +809,4 @@ category tags for pointer types. LocalWords: ForwardTraversalIterator BidirectionalTraversalIterator lvalue LocalWords: RandomAccessTraversalIterator dereferenceable Incrementable tmp LocalWords: incrementable xxx min prev inplace png oldeqnew AccessTag struct - LocalWords: TraversalTag typename lvalues DWA Hmm JGS + LocalWords: TraversalTag typename lvalues DWA Hmm JGS mis enum From ac0c6461fb831a9185d07ac849acd7cbc66e6016 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 22 Sep 2003 16:32:56 +0000 Subject: [PATCH 226/265] small edits [SVN r20159] --- doc/new-iter-concepts.html | 19 ++++++++++--------- doc/new-iter-concepts.rst | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index 2167f3e..42c958c 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -300,15 +300,16 @@ lvalue so that the appropriate old category can be chosen for the base class. The lvalue_iterator bit is not recorded in the iterator_tag::access data member.

    The iterator_tag class template is derived from the appropriate -iterator tag or tags from the old requirements based on the new-style -tags passed as template parameters. The algorithm for determining the -old tag or tags from the new tags picks the least-refined old concepts -that include all of the requirements of the access and traversal -concepts (that is, the closest fit), if any such category exists. For -example, the category tag for a Readable Single Pass Iterator will -always be derived from input_iterator_tag, while the category tag -for a Single Pass Iterator that is both Readable and Writable will be -derived from both input_iterator_tag and output_iterator_tag.

    +iterator tag or tags from the old requirements based on the access +bits and traversal tag passed as template parameters. The algorithm +for determining the old tag or tags picks the least-refined old +concepts that include all of the requirements of the access and +traversal concepts (that is, the closest fit), if any such category +exists. For example, the category tag for a Readable Single Pass +Iterator will always be derived from input_iterator_tag, while the +category tag for a Single Pass Iterator that is both Readable and +Writable will be derived from both input_iterator_tag and +output_iterator_tag.

    We also provide several helper classes that make it convenient to obtain the access and traversal characteristics of an iterator. These helper classes work both for iterators whose iterator_category is diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 44642f7..a92d11a 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -283,16 +283,16 @@ class. The ``lvalue_iterator`` bit is not recorded in the ``iterator_tag::access`` data member. The ``iterator_tag`` class template is derived from the appropriate -iterator tag or tags from the old requirements based on the new-style -tags passed as template parameters. The algorithm for determining the -old tag or tags from the new tags picks the least-refined old concepts -that include all of the requirements of the access and traversal -concepts (that is, the closest fit), if any such category exists. For -example, the category tag for a Readable Single Pass Iterator will -always be derived from ``input_iterator_tag``, while the category tag -for a Single Pass Iterator that is both Readable and Writable will be -derived from both ``input_iterator_tag`` and ``output_iterator_tag``. - +iterator tag or tags from the old requirements based on the access +bits and traversal tag passed as template parameters. The algorithm +for determining the old tag or tags picks the least-refined old +concepts that include all of the requirements of the access and +traversal concepts (that is, the closest fit), if any such category +exists. For example, the category tag for a Readable Single Pass +Iterator will always be derived from ``input_iterator_tag``, while the +category tag for a Single Pass Iterator that is both Readable and +Writable will be derived from both ``input_iterator_tag`` and +``output_iterator_tag``. We also provide several helper classes that make it convenient to obtain the access and traversal characteristics of an iterator. These From 30ca43dd0813f42530801b16b0081aee54c34b7d Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 22 Sep 2003 16:48:40 +0000 Subject: [PATCH 227/265] fixed bug in inherit-category that Thomas found [SVN r20160] --- doc/new-iter-concepts.html | 12 +++++++----- doc/new-iter-concepts.rst | 12 +++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index 42c958c..db1fe97 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -819,7 +819,9 @@ enum iterator_access { readable_iterator = 1, writable_iterator = 2, template <unsigned int access_bits, class TraversalTag> struct iterator_tag : /* appropriate old category or categories */ { - static const iterator_access access = (iterator_access)access_bits; + static const iterator_access access = + (iterator_access)access_bits & + (readable_iterator | writable_iterator | swappable_iterator); typedef TraversalTag traversal; }; @@ -842,7 +844,7 @@ from one of the original iterator tags according to the following pseudo-code.

     inherit-category(access, traversal-tag) =
    -     if (access & lvalue_iterator) {
    +     if ((access & readable_iterator) && (access & lvalue_iterator)) {
              if (traversal-tag is convertible to random_access_traversal_tag)
                  return random_access_iterator_tag;
              else if (traversal-tag is convertible to bidirectional_traversal_tag)
    @@ -885,7 +887,7 @@ deduced.  The following pseudo-code describes the algorithm.

    is-readable(Iterator) = cat = iterator_traits<Iterator>::iterator_category; if (cat == iterator_tag<Access,Traversal>) - return Access % readable_iterator; + return Access & readable_iterator; else if (cat is convertible to input_iterator_tag) return true; else @@ -894,7 +896,7 @@ is-readable(Iterator) = is-writable(Iterator) = cat = iterator_traits<Iterator>::iterator_category; if (cat == iterator_tag<Access,Traversal>) - return Access % writable_iterator; + return Access & writable_iterator; else if (cat is convertible to forward_iterator_tag or output_iterator_tag) return true; @@ -904,7 +906,7 @@ is-writable(Iterator) = is-swappable(Iterator) = cat = iterator_traits<Iterator>::iterator_category; if (cat == iterator_tag<Access,Traversal>) - return Access % swappable_iterator; + return Access & swappable_iterator; else if (cat is convertible to forward_iterator_tag) { if (iterator_traits<Iterator>::reference is a const reference) return false; diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index a92d11a..46172f9 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -658,7 +658,9 @@ Addition to [lib.iterator.synopsis] template struct iterator_tag : /* appropriate old category or categories */ { - static const iterator_access access = (iterator_access)access_bits; + static const iterator_access access = + (iterator_access)access_bits & + (readable_iterator | writable_iterator | swappable_iterator); typedef TraversalTag traversal; }; @@ -683,7 +685,7 @@ pseudo-code. :: inherit-category(access, traversal-tag) = - if (access & lvalue_iterator) { + if ((access & readable_iterator) && (access & lvalue_iterator)) { if (traversal-tag is convertible to random_access_traversal_tag) return random_access_iterator_tag; else if (traversal-tag is convertible to bidirectional_traversal_tag) @@ -729,7 +731,7 @@ deduced. The following pseudo-code describes the algorithm. is-readable(Iterator) = cat = iterator_traits::iterator_category; if (cat == iterator_tag) - return Access % readable_iterator; + return Access & readable_iterator; else if (cat is convertible to input_iterator_tag) return true; else @@ -738,7 +740,7 @@ deduced. The following pseudo-code describes the algorithm. is-writable(Iterator) = cat = iterator_traits::iterator_category; if (cat == iterator_tag) - return Access % writable_iterator; + return Access & writable_iterator; else if (cat is convertible to forward_iterator_tag or output_iterator_tag) return true; @@ -748,7 +750,7 @@ deduced. The following pseudo-code describes the algorithm. is-swappable(Iterator) = cat = iterator_traits::iterator_category; if (cat == iterator_tag) - return Access % swappable_iterator; + return Access & swappable_iterator; else if (cat is convertible to forward_iterator_tag) { if (iterator_traits::reference is a const reference) return false; From 50fe1b062ba59e2a27a76fd3922df74e21a2babc Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 22 Sep 2003 16:51:02 +0000 Subject: [PATCH 228/265] fixed another small bug in inherit-category [SVN r20161] --- doc/new-iter-concepts.html | 2 -- doc/new-iter-concepts.rst | 2 -- 2 files changed, 4 deletions(-) diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index db1fe97..6e7e79e 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -856,8 +856,6 @@ inherit-category(access, traversal-tag) = return input_output_iterator_tag; else return input_iterator_tag; - else if (access & writable_iterator) - return output_iterator_tag; else return null_category_tag; } else if ((access & readable_iterator) and (access & writable_iterator) diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 46172f9..72a17b2 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -697,8 +697,6 @@ pseudo-code. return input_output_iterator_tag; else return input_iterator_tag; - else if (access & writable_iterator) - return output_iterator_tag; else return null_category_tag; } else if ((access & readable_iterator) and (access & writable_iterator) From ebb09db44eee6aeb75bdd2207c43b4b92b7fef6f Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 22 Sep 2003 19:55:01 +0000 Subject: [PATCH 229/265] Separate access and traversal for iterator_adaptor [SVN r20162] --- doc/counting_iterator_ref.rst | 12 +- doc/facade-and-adaptor.html | 185 +++++++++++++----------- doc/facade-and-adaptor.rst | 14 +- doc/filter_iterator_ref.rst | 13 +- doc/function_output_iterator_ref.rst | 2 +- doc/indirect_iterator_ref.rst | 18 +-- doc/iterator_adaptor_body.rst | 19 +-- doc/iterator_adaptor_ref.rst | 85 ++++++----- doc/iterator_facade_ref.rst | 25 +++- doc/new-iter-concepts.html | 201 ++++++++++++++++++++++++++- doc/permutation_iterator_ref.rst | 3 +- doc/style.tex | 78 +++++++++++ 12 files changed, 485 insertions(+), 170 deletions(-) create mode 100755 doc/style.tex diff --git a/doc/counting_iterator_ref.rst b/doc/counting_iterator_ref.rst index fc01011..f443682 100644 --- a/doc/counting_iterator_ref.rst +++ b/doc/counting_iterator_ref.rst @@ -1,12 +1,18 @@ :: - template + template < + class Incrementable + , unsigned Access = use_default_access + , class Traversal = use_default + , class Difference = use_default + > class counting_iterator : public iterator_adaptor< - counting_iterator + counting_iterator , Incrementable , Incrementable - , /* see details for category */ + , Access + , /* see details for traversal category */ , Incrementable const& , Incrementable const* , /* distance = Difference or a signed integral type */> diff --git a/doc/facade-and-adaptor.html b/doc/facade-and-adaptor.html index 747de28..49efb2e 100755 --- a/doc/facade-and-adaptor.html +++ b/doc/facade-and-adaptor.html @@ -219,7 +219,7 @@ Lab, University of Hanover Date: 2003-09-22 -Number:This document is a revised version of the official N1476=03-0059 +Number:N1530=03-0113 Copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved @@ -642,17 +642,18 @@ above. The Base type need not iterator. It need only support the operations used by the core interface functions of iterator_adaptor that have not been redefined in the user's derived class.

    -

    Several of the template parameters of iterator_adaptor default to -use_default. This allows the user to make use of a default -parameter even when the user wants to specify a parameter later in the -parameter list. Also, the defaults for the corresponding associated -types are fairly complicated, so metaprogramming is required to -compute them, and use_default can help to simplify the -implementation. Finally, use_default is not left unspecified +

    Several of the template parameters of iterator_adaptor default +to use_default (or use_default_access). This allows the +user to make use of a default parameter even when she wants to +specify a parameter later in the parameter list. Also, the +defaults for the corresponding associated types are somewhat +complicated, so metaprogramming is required to compute them, and +use_default can help to simplify the implementation. Finally, +the identity of the use_default type is not left unspecified because specification helps to highlight that the Reference template parameter may not always be identical to the iterator's -reference type, and will keep users making mistakes based on that -assumption.

    +reference type, and will keep users making mistakes based on +that assumption.

    Specialized Adaptors

    @@ -697,13 +698,14 @@ Standard compliant iterators).

    Header <iterator_helper> synopsis [lib.iterator.helper.synopsis]

     struct use_default;
    +const unsigned use_default_access = -1;
     
     struct iterator_core_access { /* implementation detail */ };
     
     template <
         class Derived
       , class Value
    -  , class AccessCategory
    +  , unsigned AccessCategory
       , class TraversalCategory
       , class Reference  = Value&
       , class Difference = ptrdiff_t
    @@ -714,7 +716,8 @@ template <
         class Derived
       , class Base
       , class Value      = use_default
    -  , class Category   = use_default
    +  , unsigned Access  = use_default_access
    +  , class Traversal  = use_default
       , class Reference  = use_default
       , class Difference = use_default
     >
    @@ -723,7 +726,8 @@ class iterator_adaptor;
     template <
         class Iterator
       , class Value = use_default
    -  , class Category = use_default
    +  , unsigned Access  = use_default_access
    +  , class Traversal  = use_default
       , class Reference = use_default
       , class Difference = use_default
     >
    @@ -745,7 +749,8 @@ class filter_iterator;
     
     template <
         class Incrementable
    -  , class Category = use_default
    +  , unsigned Access  = use_default_access
    +  , class Traversal  = use_default
       , class Difference = use_default
     >
     class counting_iterator
    @@ -765,7 +770,7 @@ and associated types, to be supplied by a derived iterator class.

    template < class Derived , class Value - , class AccessCategory + , unsigned AccessCategory , class TraversalCategory , class Reference = /* see below */ , class Difference = ptrdiff_t @@ -855,11 +860,21 @@ out of the overload set when the types are not interoperable.]

    title prevents an automatic link from being generated -->

    iterator_facade requirements

    +

    Some of the constraints on template parameters to +iterator_facade are expressed in terms of resulting nested +types and should be viewed in the context of their impact on +iterator_traits<Derived>.

    The Derived template parameter must be a class derived from iterator_facade.

    -

    The default for the Reference parameter is Value& if the -access category for iterator_facade is implicitly convertible to -writable_iterator_tag, and const Value& otherwise.

    +

    The nested ::value_type type will be the same as +remove_cv<Value>::type, so the Value parameter must be +an (optionally const-qualified) non-reference type.

    +

    AccessCategory must be an unsigned value which uses no more +bits than the greatest value of iterator_access.

    +

    The nested ::reference will be the same as the Reference +parameter; it must be a suitable reference type for the resulting +iterator. The default for the Reference parameter is +Value&.

    The following table describes the other requirements on the Derived parameter. Depending on the resulting iterator's iterator_category, a subset of the expressions listed in the table @@ -973,8 +988,8 @@ of type X::pointer equal to:Otherwise returns an object of unspecified type such that, given an object a of type X, a->m is equivalent to (w = *a, w.m) for some temporary object w of type X::value_type.

    -

    The type X::pointer is Value* if the access category for -X is implicitly convertible to writable_iterator_tag, and +

    The type X::pointer is Value* if +is_writable_iterator<X>::value is true, and Value const* otherwise.

    @@ -1107,11 +1122,13 @@ core interface functions of iterator_facad

    Class template iterator_adaptor

    +bool
     template <
         class Derived
       , class Base
       , class Value      = use_default
    -  , class Category   = use_default
    +  , unsigned Access  = use_default_access
    +  , class Traversal  = use_default
       , class Reference  = use_default
       , class Difference = use_default
     >
    @@ -1163,54 +1180,47 @@ parameters specify the types for the member typedefs in
     iterator_facade.  The following pseudo-code specifies the
     traits types for iterator_adaptor.

    -if (Value == use_default)
    -    value_type = iterator_traits<Base>::value_type;
    -else 
    -    value_type = remove_cv<Value>::type;
    -
    -if (Reference == use_default) {
    -    if (Value == use_default)
    -        reference = iterator_traits<Base>::reference;
    -    else 
    -        reference = Value&;
    -} else
    -    reference = Reference;
    -
    -if (Distance == use_default)
    -    difference_type = iterator_traits<Base>::difference_type;
    +if (Value != use_default)
    +     value_type = remove_cv<Value>::type;
     else
    -    difference_type = Distance;
    +     value_type = iterator_traits<Base>::value_type;
     
    -if (Category == use_default)
    -    iterator_category = iterator_tag< 
    -        access_category< Base >,
    -        traversal_category< Base >
    -    >
    -else if (Category is convertible to a standard access tag)
    -    iterator_category = iterator_tag<
    -        Category
    -    else if (Category has a nested traversal type)
    -         if (reference is not a reference-to-const)
    -             Category::access
    -         else
    -             if (Category
    -        
     
    -else if (Category is convertable to a standard traversal tag)
    -    ...
    +if (Traversal != use_default)
    +    traversal_category = Traversal
     else
    -    iterator_category = Category;
    -    // Actually the above is wrong.  See the use of
    -    // access_category_tag and
    -    // new_category_to_access/iter_category_to_access.
    +    traversal_category = traversal_category< Base >::type
    +
    +iterator_category = iterator_tag<
    +                         access_category
    +                       , traversal_category
    +                     >
    +
    +if (Access != use_default)
    +{
    +   access_category = Access
    +}
    +else
    +{
    +   access_category
    +     = access_category< Base >::value
    +
    +   if (is_const<Value>)
    +       access_category &= ~writable_iterator;
    +}
    +
    +iterator_category = iterator_tag<
    +                         access_category
    +                       , traversal_category
    +                     >
    +
    +if (Reference != use_default)
    +    reference = Reference
    +else if (Value != use_default)
    +    reference = Value&
    +else
    +    reference = iterator_traits<Base>::reference
     
    -

    iterator_adaptor public operations

    @@ -1362,7 +1372,8 @@ iterators over smart pointers, which the impl handles. -JGS --> template < class Iterator , class Value = use_default - , class Category = use_default + , unsigned Access = use_default_access + , class Traversal = use_default , class Reference = use_default , class Difference = use_default > @@ -1374,12 +1385,12 @@ class indirect_iterator indirect_iterator(); indirect_iterator(Iterator x); template < - class Iterator2, class Value2, class Category2 + class Iterator2, class Value2, unsigned Access2, class Traversal2 , class Reference2, class Difference2 > indirect_iterator( indirect_iterator< - Iterator2, Value2, Category2, Reference2, Difference2 + Iterator2, Value2, Access2, Traversal2, Reference2, Difference2 > const& y , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition ); @@ -1408,9 +1419,10 @@ specialization of iterator_traits

    The Reference parameter will be the reference type of the indirect_iterator. The default is Value&.

    -

    The Category parameter is the iterator_category type for the -indirect_iterator. The default is -iterator_traits<Iterator>::iterator_category.

    +

    The Access and Traversal parameters are passed unchanged to +the corresponding parameters of the iterator_adaptor base +class, and the Iterator parameter is passed unchanged as the +Base parameter to the iterator_adaptor base class.

    The indirect iterator will model the most refined standard traversal concept that is modeled by the Iterator type. The indirect iterator will model the most refined standard access concept that is @@ -1442,12 +1454,12 @@ the iterator_adaptor subobject

     template <
    -    class Iterator2, class Value2, class Category2
    +    class Iterator2, class Value2, unsigned Access, class Traversal
       , class Reference2, class Difference2
     >
     indirect_iterator(
         indirect_iterator<
    -         Iterator2, Value2, Category2, Reference2, Difference2
    +         Iterator2, Value2, Access, Traversal, Reference2, Difference2
         > const& y
       , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition
     );
    @@ -1733,12 +1745,13 @@ class filter_iterator
     

    filter_iterator requirements

    -

    The base Iterator parameter must be a model of Readable Iterator -and Single Pass Iterator. The resulting filter_iterator will be a -model of Forward Traversal Iterator if Iterator is, otherwise the -filter_iterator will be a model of Single Pass Iterator. The -access category of the filter_iterator will be the most refined -standard access category that is modeled by Iterator.

    +

    The base Iterator parameter must be a model of Readable +Iterator and Single Pass Iterator. The resulting +filter_iterator will be a model of Forward Traversal Iterator +if Iterator is, otherwise the filter_iterator will be a +model of Single Pass Iterator. The access category of the +filter_iterator will be the same as the access category of +Iterator.

    The Predicate must be Assignable, Copy Constructible, and the @@ -1830,13 +1843,19 @@ the base m_iterator, as per th

    Class template counting_iterator

    -template <class Incrementable, class Category = use_default, class Difference = use_default>
    +template <
    +    class Incrementable
    +  , unsigned Access = use_default_access
    +  , class Traversal = use_default
    +  , class Difference = use_default
    +>
     class counting_iterator
       : public iterator_adaptor<
    -        counting_iterator<Incrementable, Category, Difference>
    +        counting_iterator<Incrementable, Access, Traversal, Difference>
           , Incrementable
           , Incrementable
    -      , /* see details for category */
    +      , Access
    +      , /* see details for traversal category */
           , Incrementable const&
           , Incrementable const*
           , /* distance = Difference or a signed integral type */>
    @@ -1935,7 +1954,7 @@ template <class UnaryFunction>
     class function_output_iterator {
     public:
       typedef iterator_tag<
    -        writable_iterator_tag
    +        writable_iterator
           , incrementable_traversal_tag
       > iterator_category;
       typedef void                value_type;
    @@ -2043,7 +2062,7 @@ LocalWords:  OtherIncrementable Coplien -->
     
     
     
    diff --git a/doc/facade-and-adaptor.rst b/doc/facade-and-adaptor.rst
    index 9ed64a1..0dca788 100644
    --- a/doc/facade-and-adaptor.rst
    +++ b/doc/facade-and-adaptor.rst
    @@ -8,7 +8,7 @@
                    Lab`_, University of Hanover `Institute for Transport
                    Railway Operation and Construction`_
     :date: $Date$
    -:Number: **This document is a revised version of the official** N1476=03-0059
    +:Number: N1530=03-0113
     :copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
     
     .. _`Boost Consulting`: http://www.boost-consulting.com
    @@ -226,13 +226,14 @@ Header ```` synopsis    [lib.iterator.helper.synopsis]
     ::
     
       struct use_default;
    +  const unsigned use_default_access = -1;
     
       struct iterator_core_access { /* implementation detail */ };
       
       template <
           class Derived
         , class Value
    -    , class AccessCategory
    +    , unsigned AccessCategory
         , class TraversalCategory
         , class Reference  = Value&
         , class Difference = ptrdiff_t
    @@ -243,7 +244,8 @@ Header ```` synopsis    [lib.iterator.helper.synopsis]
           class Derived
         , class Base
         , class Value      = use_default
    -    , class Category   = use_default
    +    , unsigned Access  = use_default_access
    +    , class Traversal  = use_default
         , class Reference  = use_default
         , class Difference = use_default
       >
    @@ -252,7 +254,8 @@ Header ```` synopsis    [lib.iterator.helper.synopsis]
       template <
           class Iterator
         , class Value = use_default
    -    , class Category = use_default
    +    , unsigned Access  = use_default_access
    +    , class Traversal  = use_default
         , class Reference = use_default
         , class Difference = use_default
       >
    @@ -274,7 +277,8 @@ Header ```` synopsis    [lib.iterator.helper.synopsis]
     
       template <
           class Incrementable
    -    , class Category = use_default
    +    , unsigned Access  = use_default_access
    +    , class Traversal  = use_default
         , class Difference = use_default
       >
       class counting_iterator
    diff --git a/doc/filter_iterator_ref.rst b/doc/filter_iterator_ref.rst
    index 29bc166..239d2f8 100644
    --- a/doc/filter_iterator_ref.rst
    +++ b/doc/filter_iterator_ref.rst
    @@ -41,12 +41,13 @@
     ``filter_iterator`` requirements
     --------------------------------
     
    -The base ``Iterator`` parameter must be a model of Readable Iterator
    -and Single Pass Iterator. The resulting ``filter_iterator`` will be a
    -model of Forward Traversal Iterator if ``Iterator`` is, otherwise the
    -``filter_iterator`` will be a model of Single Pass Iterator. The
    -access category of the ``filter_iterator`` will be the most refined
    -standard access category that is modeled by ``Iterator``.
    +The base ``Iterator`` parameter must be a model of Readable
    +Iterator and Single Pass Iterator. The resulting
    +``filter_iterator`` will be a model of Forward Traversal Iterator
    +if ``Iterator`` is, otherwise the ``filter_iterator`` will be a
    +model of Single Pass Iterator. The access category of the
    +``filter_iterator`` will be the same as the access category of
    +``Iterator``.
     
     .. Thomas is going to try implementing filter_iterator so that
        it will be bidirectional if the underlying iterator is. -JGS
    diff --git a/doc/function_output_iterator_ref.rst b/doc/function_output_iterator_ref.rst
    index 4bb5cf1..bee8a60 100644
    --- a/doc/function_output_iterator_ref.rst
    +++ b/doc/function_output_iterator_ref.rst
    @@ -4,7 +4,7 @@
       class function_output_iterator {
       public:
         typedef iterator_tag<
    -          writable_iterator_tag
    +          writable_iterator
             , incrementable_traversal_tag
         > iterator_category;
         typedef void                value_type;
    diff --git a/doc/indirect_iterator_ref.rst b/doc/indirect_iterator_ref.rst
    index ebbe2ff..5525c2e 100644
    --- a/doc/indirect_iterator_ref.rst
    +++ b/doc/indirect_iterator_ref.rst
    @@ -3,7 +3,8 @@
       template <
           class Iterator
         , class Value = use_default
    -    , class Category = use_default
    +    , unsigned Access  = use_default_access
    +    , class Traversal  = use_default
         , class Reference = use_default
         , class Difference = use_default
       >
    @@ -15,12 +16,12 @@
           indirect_iterator();
           indirect_iterator(Iterator x);
           template <
    -          class Iterator2, class Value2, class Category2
    +          class Iterator2, class Value2, unsigned Access2, class Traversal2
             , class Reference2, class Difference2
           >
           indirect_iterator(
               indirect_iterator<
    -               Iterator2, Value2, Category2, Reference2, Difference2
    +               Iterator2, Value2, Access2, Traversal2, Reference2, Difference2
               > const& y
             , typename enable_if_convertible::type* = 0 // exposition
           );
    @@ -53,9 +54,10 @@ iterator.
     The ``Reference`` parameter will be the ``reference`` type of the
     ``indirect_iterator``. The default is ``Value&``.
     
    -The ``Category`` parameter is the ``iterator_category`` type for the
    -``indirect_iterator``. The default is 
    -``iterator_traits::iterator_category``.
    +The ``Access`` and ``Traversal`` parameters are passed unchanged to
    +the corresponding parameters of the ``iterator_adaptor`` base
    +class, and  the ``Iterator`` parameter is passed unchanged as the
    +``Base`` parameter to the ``iterator_adaptor`` base class.
     
     The indirect iterator will model the most refined standard traversal
     concept that is modeled by the ``Iterator`` type.  The indirect
    @@ -81,12 +83,12 @@ modeled by the value type of ``Iterator``.
     ::
     
       template <
    -      class Iterator2, class Value2, class Category2
    +      class Iterator2, class Value2, unsigned Access, class Traversal
         , class Reference2, class Difference2
       >
       indirect_iterator(
           indirect_iterator<
    -           Iterator2, Value2, Category2, Reference2, Difference2
    +           Iterator2, Value2, Access, Traversal, Reference2, Difference2
           > const& y
         , typename enable_if_convertible::type* = 0 // exposition
       );
    diff --git a/doc/iterator_adaptor_body.rst b/doc/iterator_adaptor_body.rst
    index 0136ad1..942c2f6 100644
    --- a/doc/iterator_adaptor_body.rst
    +++ b/doc/iterator_adaptor_body.rst
    @@ -18,15 +18,16 @@ iterator. It need only support the operations used by the core
     interface functions of ``iterator_adaptor`` that have not been
     redefined in the user's derived class.
     
    -Several of the template parameters of ``iterator_adaptor`` default to
    -``use_default``. This allows the user to make use of a default
    -parameter even when the user wants to specify a parameter later in the
    -parameter list.  Also, the defaults for the corresponding associated
    -types are fairly complicated, so metaprogramming is required to
    -compute them, and ``use_default`` can help to simplify the
    -implementation.  Finally, ``use_default`` is not left unspecified
    +Several of the template parameters of ``iterator_adaptor`` default
    +to ``use_default`` (or ``use_default_access``). This allows the
    +user to make use of a default parameter even when she wants to
    +specify a parameter later in the parameter list.  Also, the
    +defaults for the corresponding associated types are somewhat
    +complicated, so metaprogramming is required to compute them, and
    +``use_default`` can help to simplify the implementation.  Finally,
    +the identity of the ``use_default`` type is not left unspecified
     because specification helps to highlight that the ``Reference``
     template parameter may not always be identical to the iterator's
    -``reference`` type, and will keep users making mistakes based on that
    -assumption.
    +``reference`` type, and will keep users making mistakes based on
    +that assumption.
     
    diff --git a/doc/iterator_adaptor_ref.rst b/doc/iterator_adaptor_ref.rst
    index af910f5..7226341 100644
    --- a/doc/iterator_adaptor_ref.rst
    +++ b/doc/iterator_adaptor_ref.rst
    @@ -1,10 +1,12 @@
     .. parsed-literal::
       
    +  bool
       template <
           class Derived
         , class Base
         , class Value      = use_default
    -    , class Category   = use_default
    +    , unsigned Access  = use_default_access
    +    , class Traversal  = use_default
         , class Reference  = use_default
         , class Difference = use_default
       >
    @@ -60,55 +62,46 @@ traits types for ``iterator_adaptor``.
     
     ::
     
    -    if (Value == use_default)
    -        value_type = iterator_traits::value_type;
    -    else 
    +   if (Value != use_default)
             value_type = remove_cv::type;
    -
    -    if (Reference == use_default) {
    -        if (Value == use_default)
    -            reference = iterator_traits::reference;
    -        else 
    -            reference = Value&;
    -    } else
    -        reference = Reference;
    -
    -    if (Distance == use_default)
    -        difference_type = iterator_traits::difference_type;
    -    else
    -        difference_type = Distance;
    -
    -    if (Category == use_default)
    -        iterator_category = iterator_tag< 
    -            access_category< Base >,
    -            traversal_category< Base >
    -        >
    -    else if (Category is convertible to a standard access tag)
    -        iterator_category = iterator_tag<
    -            Category
    -        else if (Category has a nested traversal type)
    -             if (reference is not a reference-to-const)
    -                 Category::access
    -             else
    -                 if (Category
    -            
    -    
    -    else if (Category is convertable to a standard traversal tag)
    -        ...
    -    else
    -        iterator_category = Category;
    -        // Actually the above is wrong.  See the use of
    -        // access_category_tag and
    -        // new_category_to_access/iter_category_to_access.
    +   else
    +        value_type = iterator_traits::value_type;
     
     
    -..  Replaced with new semantics --thw
    -    if (Category == use_default)
    -        iterator_category = iterator_traits::iterator_category;
    -    else
    -        iterator_category = Category;
    +   if (Traversal != use_default)
    +       traversal_category = Traversal
    +   else
    +       traversal_category = traversal_category< Base >::type
     
    -    Fix this up!!
    +   iterator_category = iterator_tag<
    +                            access_category
    +                          , traversal_category
    +                        >
    +
    +   if (Access != use_default)
    +   {
    +      access_category = Access
    +   }
    +   else
    +   {
    +      access_category
    +        = access_category< Base >::value
    +
    +      if (is_const)
    +          access_category &= ~writable_iterator;
    +   }
    +
    +   iterator_category = iterator_tag<
    +                            access_category
    +                          , traversal_category
    +                        >
    +
    +   if (Reference != use_default)
    +       reference = Reference
    +   else if (Value != use_default)
    +       reference = Value&
    +   else
    +       reference = iterator_traits::reference
     
     
     ``iterator_adaptor`` public operations
    diff --git a/doc/iterator_facade_ref.rst b/doc/iterator_facade_ref.rst
    index 04d5150..bba0dd2 100644
    --- a/doc/iterator_facade_ref.rst
    +++ b/doc/iterator_facade_ref.rst
    @@ -3,7 +3,7 @@
       template <
           class Derived
         , class Value
    -    , class AccessCategory
    +    , unsigned AccessCategory
         , class TraversalCategory
         , class Reference  = /* see below__ \*/
         , class Difference = ptrdiff_t
    @@ -108,12 +108,25 @@ out of the overload set when the types are not interoperable.]
     ``iterator_facade`` requirements
     ................................
     
    +Some of the constraints on template parameters to
    +``iterator_facade`` are expressed in terms of resulting nested
    +types and should be viewed in the context of their impact on
    +``iterator_traits``.
    +
     The ``Derived`` template parameter must be a class derived from
     ``iterator_facade``.
     
    -The default for the ``Reference`` parameter is ``Value&`` if the
    -access category for ``iterator_facade`` is implicitly convertible to
    -``writable_iterator_tag``, and ``const Value&`` otherwise.
    +The nested ``::value_type`` type will be the same as
    +``remove_cv::type``, so the ``Value`` parameter must be
    +an (optionally ``const``\ -qualified) non-reference type.
    +
    +``AccessCategory`` must be an unsigned value which uses no more
    +bits than the greatest value of ``iterator_access``.
    +
    +The nested ``::reference`` will be the same as the ``Reference``
    +parameter; it must be a suitable reference type for the resulting
    +iterator.  The default for the ``Reference`` parameter is
    +``Value&``.
     
     The following table describes the other requirements on the
     ``Derived`` parameter.  Depending on the resulting iterator's
    @@ -188,8 +201,8 @@ __ `operator arrow`_
       object ``a`` of type ``X``, ``a->m`` is equivalent to ``(w = *a,
       w.m)`` for some temporary object ``w`` of type ``X::value_type``.
     
    -  The type ``X::pointer`` is ``Value*`` if the access category for
    -  ``X`` is implicitly convertible to ``writable_iterator_tag``, and
    +  The type ``X::pointer`` is ``Value*`` if
    +  ``is_writable_iterator::value`` is ``true``, and
       ``Value const*`` otherwise.
     
     
    diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html
    index 6e7e79e..e2a5c85 100755
    --- a/doc/new-iter-concepts.html
    +++ b/doc/new-iter-concepts.html
    @@ -3,13 +3,204 @@
     
     
     
    -
    +
     New Iterator Concepts
     
     
     
     
    -
    +
     
     
     
    @@ -963,5 +1154,11 @@ LocalWords: TraversalTag typename lvalues DWA Hmm JGS mis enum -->
    + + diff --git a/doc/permutation_iterator_ref.rst b/doc/permutation_iterator_ref.rst index ef84045..ab82271 100644 --- a/doc/permutation_iterator_ref.rst +++ b/doc/permutation_iterator_ref.rst @@ -3,7 +3,8 @@ template< class ElementIterator , class IndexIterator , class ValueT = use_default - , class CategoryT = use_default + , unsigned access = use_default_access + , class Traversal = use_default , class ReferenceT = use_default , class DifferenceT = use_default > class permutation_iterator diff --git a/doc/style.tex b/doc/style.tex new file mode 100755 index 0000000..4b2407e --- /dev/null +++ b/doc/style.tex @@ -0,0 +1,78 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%% docutils.sty: A style for docutils latex output %%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% o author: Alexander Schmolck (a.schmolck@gmx.net) +%% o created: 2002-07-07 10:50:31+00:40 +%% o last modified: $Date: 2003/09/22 19:55:01 $ +%% o keywords: +%% o license: +%XXX titlesec +%% XXX geometry +\usepackage{graphicx} +\usepackage{latexsym} % extra symbols +\usepackage{url} % !!!: pay attention when using in other commands!!! +\usepackage{verbatim} % normal verbatim has lenght-limit +\usepackage{enumerate} % easy style choice with e.g: ``\begin{enumerate}[Ex i.]`` +\usepackage{hyperref} %href, htarget and hlink XXX: pdfauthor, pdfcreator etc. +\usepackage{xr} %XXX do we need this? +% need this to have ``fboxes`` in ``enviroments``, as well as ``verbatim``s +\usepackage{fancybox} +\usepackage{mdwtab} % better tables and arrays (fixes spacing and adds + % vertical align and multirows (m)) +\usepackage{ltxtable} % long and autoscaling tables (use X for autoscaled + % columns) +\newcommand{\transition}{\vspace{2em}\par\hrule{}\par\vspace{2em}} +\newcommand{\classifier}[1]{(\textit{#1})} +\newenvironment{topic}[1]% +{\begin{Sbox}% + \begin{minipage}{.8\textwidth}% + \protect{\large{\textbf{#1}}}\par\vspace{.5em}}% +{\end{minipage}\end{Sbox}\fbox{\TheSbox}\par\vspace{.5em}} +%XXX shadow box for warnings? +\newenvironment{admonition}[1]% +{\begin{center}% + \begin{Sbox}% + \begin{minipage}{.9\textwidth}% + \protect{\textsc{#1}}\par\vspace{.2em}}% +{\end{minipage}\end{Sbox}\fbox{\TheSbox}\par\vspace{.5em}\end{center}} + +\newenvironment{doctest}% +{\VerbatimEnvironment + \begin{Verbatim}}% +{\end{Verbatim}} +% {% +% \begin{Sbox}% +% \begin{minipage}{.8\textwidth}% +% \protect{\large{\textsc{#1}}\par\vspace{.5em}}}% +% {\end{minipage}\end{Sbox}\fbox{\TheSbox}\par\vspace{.5em}} +%{\end{minipage}\end{Sbox}\fbox{\TheSbox}} + + +%% just a piece of example code +% \newcommand{\vitem}% +% {\SaveVerb[{\item[\UseVerb{\MyTemp}]}]{\MyTemp}} + +%%%%%%%%%%%%%%%%%%% Added by DWA %%%%%%%%%%%%%%%%%%%%%%%%% + +% donot indent first line. +\setlength{\parindent}{0pt} +\setlength{\parskip}{5pt plus 2pt minus 1pt} + +% sloppy +% ------ +% Less strict (opposite to default fussy) space size between words. Therefore +% less hyphenation. +\sloppy + +% fonts +% ----- +% times for pdf generation, gives smaller pdf files. +% +% But in standard postscript fonts: courier and times/helvetica do not fit. +% Maybe use pslatex. +\usepackage{times} +\usepackage{pslatex} + +% pagestyle +\pagestyle{headings} From 361f62d02206c332f57c3c431c0f63088abc3724 Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Mon, 29 Sep 2003 16:27:55 +0000 Subject: [PATCH 230/265] Add V2 Jamfile [SVN r20211] --- test/Jamfile.v2 | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 test/Jamfile.v2 diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 new file mode 100644 index 0000000..4cdb206 --- /dev/null +++ b/test/Jamfile.v2 @@ -0,0 +1,44 @@ +# Copyright David Abrahams 2003. 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. + +import testing ; + +test-suite iterator + : + # These first two tests will run last, and are expected to fail + # for many less-capable compilers. + + [ compile-fail interoperable_fail.cpp ] + # test uses expected success, so that we catch unrelated + # compilation problems. + [ run is_convertible_fail.cpp ] + + # These tests should work for just about everything. + [ run unit_tests.cpp ] + [ run concept_tests.cpp ] + [ run iterator_adaptor_cc.cpp ] + [ run iterator_adaptor_test.cpp ] + [ compile iterator_archetype_cc.cpp ] + [ run transform_iterator_test.cpp ] + [ run indirect_iterator_test.cpp ] + [ run filter_iterator_test.cpp ] + [ run reverse_iterator_test.cpp ] + [ run counting_iterator_test.cpp ] + [ run permutation_iterator_test.cpp : : : # on + ] + [ run zip_iterator_test.cpp ] + + [ run ../../utility/iterator_adaptor_examples.cpp ] + [ run ../../utility/counting_iterator_example.cpp ] + [ run ../../utility/filter_iterator_example.cpp ] + [ run ../../utility/fun_out_iter_example.cpp ] + [ run ../../utility/indirect_iterator_example.cpp ] + [ run ../../utility/projection_iterator_example.cpp ] + [ run ../../utility/reverse_iterator_example.cpp ] + [ run ../../utility/transform_iterator_example.cpp ] + [ run ../../utility/iterator_traits_test.cpp ] + +; From 1c39976ccd5909dbb38b21baa7e1f21f4b9c2906 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 30 Sep 2003 12:22:56 +0000 Subject: [PATCH 231/265] Correct broken #include [SVN r20231] --- include/boost/iterator/zip_iterator.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/iterator/zip_iterator.hpp b/include/boost/iterator/zip_iterator.hpp index cc12591..943a347 100755 --- a/include/boost/iterator/zip_iterator.hpp +++ b/include/boost/iterator/zip_iterator.hpp @@ -26,7 +26,7 @@ #include #include // for enable_if_convertible #include -#include +#include #include From 17026cc30d8c2d6bdea31ac05ee3b52bb10ae80a Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 16 Oct 2003 13:57:35 +0000 Subject: [PATCH 232/265] Fixed is-writable computation. Traits protocol still needs fixing. [SVN r20398] --- doc/new-iter-concepts.rst | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 72a17b2..601ba49 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -6,9 +6,10 @@ :Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@acm.org :organization: `Boost Consulting`_, Indiana University `Open Systems Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:Number: N1531=03-0114 +:Number: revised from `N1531=03-0114`__ :copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved +.. __: n1531_ .. _`Boost Consulting`: http://www.boost-consulting.com .. _`Open Systems Lab`: http://www.osl.iu.edu .. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de @@ -18,12 +19,13 @@ concepts to more closely match the requirements of algorithms and provides better categorizations of iterators that are used in practice. This proposal - is a revision of paper n1297_ and n1477_. + is a revision of paper n1297_, n1477_, and n1531_. .. contents:: Table of Contents .. _n1297: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2001/n1297.html .. _n1477: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1477.html +.. _n1531: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1531.html ============ Motivation @@ -739,8 +741,12 @@ deduced. The following pseudo-code describes the algorithm. cat = iterator_traits::iterator_category; if (cat == iterator_tag) return Access & writable_iterator; - else if (cat is convertible to forward_iterator_tag - or output_iterator_tag) + else if (cat is convertible to output_iterator_tag) + return true; + else if ( + cat is convertible to forward_iterator_tag + and iterator_traits::reference is a + mutable reference) return true; else return false; From 15abd4c56ee85a550a63e2a5cda60e091913da25 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 30 Oct 2003 19:10:02 +0000 Subject: [PATCH 233/265] removed algorithm changes [SVN r20567] --- doc/new-iter-concepts.rst | 77 +++------------------------------------ 1 file changed, 6 insertions(+), 71 deletions(-) diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 601ba49..7b88ce7 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -134,77 +134,12 @@ appropriate old requirements. a tag that is not input_iterator_tag but that is convertible to input_iterator_tag? -JGS -The algorithms in the standard library benefit from the new iterator -concepts because the new concepts provide a more accurate way to -express their type requirements. The result is algorithms that are -usable in more situations and have fewer type requirements. The -following lists the proposed changes to the type requirements of -algorithms. - -Forward Iterator -> Forward Traversal Iterator and Readable Iterator - - ``find_end, adjacent_find, search, search_n, rotate_copy, - lower_bound, upper_bound, equal_range, binary_search, - min_element, max_element`` - -Forward Iterator (1) -> Single Pass Iterator and Readable Iterator, -Forward Iterator (2) -> Forward Traversal Iterator and Readable Iterator - - ``find_first_of`` - -Forward Iterator -> Readable Iterator and Writable Iterator - - ``iter_swap`` - -Forward Iterator -> Single Pass Iterator and Writable Iterator - - ``fill, generate`` - -Forward Iterator -> Forward Traversal Iterator and Swappable Iterator - - ``rotate`` - -Forward Iterator (1) -> Swappable Iterator and Single Pass Iterator, -Forward Iterator (2) -> Swappable Iterator and Incrementable Iterator - - ``swap_ranges`` - -Forward Iterator -> Forward Traversal Iterator and Readable Iterator and Writable Iterator - ``remove, remove_if, unique`` - -Forward Iterator -> Single Pass Iterator and Readable Iterator and Writable Iterator - - ``replace, replace_if`` - -Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator - ``reverse`` - -Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable and Swappable Iterator - ``partition`` - -Bidirectional Iterator (1) -> Bidirectional Traversal Iterator and Readable Iterator, -Bidirectional Iterator (2) -> Bidirectional Traversal Iterator and Writable Iterator - - ``copy_backwards`` - -Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator and Readable Iterator - ``next_permutation, prev_permutation`` - -Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator and Writable Iterator - ``stable_partition, inplace_merge`` - -Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator - ``reverse_copy`` - -Random Access Iterator -> Random Access Traversal Iterator and Readable and Writable Iterator - ``random_shuffle, sort, stable_sort, partial_sort, nth_element, push_heap, pop_heap - make_heap, sort_heap`` - -Input Iterator (2) -> Incrementable Iterator and Readable Iterator - ``equal, mismatch`` - -Input Iterator (2) -> Incrementable Iterator and Readable Iterator - ``transform`` +The algorithms in the standard library could benefit from the new +iterator concepts because the new concepts provide a more accurate way +to express their type requirements. The result is algorithms that are +usable in more situations, have fewer type requirements, and that are +backward compatible. However, this proposal does not include making +these changes. ======== Design From e888f18b5a351220b32b52b27f25788f7d682dab Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 30 Oct 2003 21:11:10 +0000 Subject: [PATCH 234/265] Edits for committee meeting, moving algorithm changes to suggestions for WP. [SVN r20568] --- doc/new-iter-concepts.html | 176 +++++++++++++++++++++++-------------- doc/new-iter-concepts.rst | 121 ++++++++++++++++++++++--- 2 files changed, 223 insertions(+), 74 deletions(-) diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index e2a5c85..cc69a33 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -7,7 +7,7 @@ New Iterator Concepts - + + + +
    +

    Issues With N1550 and N1530

    + +++ + + + + + + + + + + + +
    Author:David Abrahams
    Contact:dave@boost-consulting.com
    Organization:Boost Consulting
    date:$Date$
    Copyright:Copyright David Abrahams 2003. Use, modification and +distribution is subject to the Boost Software License, +Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +at http://www.boost.org/LICENSE_1_0.txt)
    + +
    +

    Introduction

    +

    Several issues with N1550 (New Iterator Concepts) were raised in +the run-up before the fall 2003 C++ Committee meeting, in a thread +beginning with John Maddock's posting c++std-lib-12187. In +looking at those issues, several other problems came up. This +document addresses those issues and discusses some potential +solutions and their impact on N1530 (Iterator Facade and Adaptor).

    +
    +
    +

    The Issues

    +
    +

    Non-Uniformity of the "lvalue_iterator Bit"

    +

    The proposed iterator_tag class template accepts an "access +bits" parameter which includes a bit to indicate the iterator's +lvalueness (whether its dereference operator returns a reference +to its value_type. The relevant part of N1550 says:

    +
    +The purpose of the lvalue_iterator part of the +iterator_access enum is to communicate to iterator_tag +whether the reference type is an lvalue so that the appropriate +old category can be chosen for the base class. The +lvalue_iterator bit is not recorded in the +iterator_tag::access data member.
    +

    The lvalue_iterator bit is not recorded because N1550 aims to +improve orthogonality of the iterator concepts, and a new-style +iterator's lvalueness is detectable by examining its reference +type. This inside/outside difference is awkward and confusing.

    +
    +
    +

    Redundancy of Some Explicit Access Category Flags

    +

    Shortly after N1550 was accepted, we discovered that an iterator's +lvalueness can be determined knowing only its value_type. This +predicate can be calculated even for old-style iterators (on whose +reference type the standard places few requirements). A trait +in the Boost iterator library does it by relying on the compiler's +unwillingness to bind an rvalue to a T& function template +parameter. Similarly, it is possible to detect an iterator's +readability knowing only its value_type. Thus, any interface +which asks the user to explicitly describe an iterator's +lvalue-ness or readability seems to introduce needless complexity.

    +
    +
    +

    New Access Traits Templates Wrong For Some Iterators

    +
    +

    is_writable_iterator

    +

    The part of the is_writable_iterator trait definition which +applies to old-style iterators is:

    +
    +if (cat is convertible to output_iterator_tag)
    +         return true;
    +    else if (
    +         cat is convertible to forward_iterator_tag
    +         and iterator_traits<Iterator>::reference is a 
    +             mutable reference)
    +        return true;
    +    else
    +        return false;
    +
    +

    The current forward iterator requirements place no constraints on +the iterator's reference type, so the logic above will give +false negatives for some otherwise-writable forward iterators whose +reference type is not a mutable reference. Also, it will +report false positives for any forward, bidirectional, or random +access iterator whose reference is a mutable reference but +whose value_type is not assignable.

    +
    +
    +

    is_swappable_iterator

    +

    Similarly, the part of is_swappable_iterator which applies to +old-style iterators is:

    +
    +else if (cat is convertible to forward_iterator_tag) {
    +    if (iterator_traits<Iterator>::reference is a const reference)
    +        return false;
    +    else
    +        return true;
    +} else 
    +    return false;
    +
    +

    In this case false positives are possible for non-writable forward +iterators whose reference type is not a reference, or as above, +any forward, bidirectional, or random access iterator whose +reference is not a constant reference but whose value_type +is not assignable (e.g., because it has a private assignment +operator).

    +

    False negatives can be "reasoned away": since it is part of a +writable iterator's concept definition that +is_writable<I>::value is true, any iterator for which +it is false is by definition not writable. This seems like a +perverse use of logic, though.

    +

    It might be reasonable to conclude that it is a defect that the +standard allows forward iterators with a reference type other +than value_type cv&, but that still leaves the problem +of old-style iterators whose value_type is not assignable. It +is not possible to correctly compute writability and swappability +for those old-style iterators without intervention +(specializations of is_writable_iterator and +is_swappable_iterator) from a user.

    +
    +
    +
    +

    No Use Cases for Some Access Traits

    +
    +

    is_swappable_iterator

    +

    is_swappable_iterator<I> is supposed to yield true if +iter_swap(x,y) is valid for instances x and y of type +I. The only argument we have heard for +is_swappable_iterator goes something like this:

    +
    +"If is_swappable_iterator yields false, you +could fall back to using copy construction and assignment on +the value_type instead."
    +

    This line of reasoning, however, falls down when closely examined. +To achieve the same effect using copy construction and assignment +on the iterator's value_type, the iterator must be readable and +writable, and its value_type must be copy-constructible. But +then, iter_swap must work in that case, because its default +implementation just calls swap on the dereferenced iterators. +The only purpose for the swappable concept is to represent +iterators which do not fulfill the properties listed above, but +which are nonetheless swappable because the user has provided an +overload or specialization of iter_swap. In other words, +generic code which wants to swap the referents of two iterators +should always call iter_swap instead of doing the +assignments.

    +
    +
    +

    is_writable_iterator

    +

    Try to imagine a case where is_writable_iterator can be used to +choose behavior. Since the only requirement on a writable iterator +is that we can assign into its referent, the only use for +is_writable_iterator in selecting behavior is to modify a +sequence when the sequence is mutable, and to not modify it +otherwise.

    +

    There is no precedent for generic functions which modify their +arguments only if the arguments are non-const reference, and with +good reason: the simple fact that data is mutable does not mean +that a user intends it to be mutated. We provide const and +non-const overloads for functions like operator[], but +these do not modify data; they merely return a reference to data +which preserves the object's mutability properties. We can do the +same with iterators using their reference types; the +accessibility of an assignment operator on the value_type, +which determines writability, does not change that.

    +

    The one plausible argument we can imagine for +is_writable_iterator and is_swappable_iterator is to remove +algorithms from an overload set using a SFINAE technique like +enable_if, but that seems to be too small a gain for the +requirements imposed on iterator implementors by the need to report +writability and swappability, especially since it can't be done +correctly for all existing iterators.

    +
    +
    +
    +
    +

    Proposed Solution

    +

    (incomplete)

    +

    Change iterator_traits as follows:

    +
    +iterator_traits<I>::iterator_category
    +  = if (I::iterator_category is a type) // use mpl::has_xxx (SFINAE)
    +       return I::iterator_category
    +
    +    if (iterator_value_type<I>::type is void
    +        || iterator_difference_type<I>::type is void
    +    )
    +       return std::output_iterator_tag
    +
    +    t = iterator_traversal<I>::type
    +    
    +    if (is_lvalue_iterator<I>::value)
    +    {
    +       if (t is convertible to random_access_traversal_tag)
    +          return std::random_access_iterator_tag
    +       if (t is convertible to bidirectional_traversal_tag)
    +          return std::bidirectional_iterator_tag
    +       else if (t is convertible to forward_traversal_tag)
    +          return std::forward_iterator_tag
    +    }
    +
    +    if (t is convertible to single_pass_traversal_tag
    +        && is_readable_iterator<I>::value
    +    )
    +       return input_output_iterator_tag // (**)
    +    else
    +       return std::output_iterator_tag
    +
    +
    +
    + + + + diff --git a/doc/issues.rst b/doc/issues.rst new file mode 100755 index 0000000..2a35e2a --- /dev/null +++ b/doc/issues.rst @@ -0,0 +1,229 @@ ++++++++++++++++++++++++++++++++ + Issues With N1550_ and N1530_ ++++++++++++++++++++++++++++++++ + +.. _N1550: http://www.boost-consulting.com/writing/n1550.html +.. _N1530: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1530.html + +:Author: David Abrahams +:Contact: dave@boost-consulting.com +:Organization: `Boost Consulting`_ +:date: $Date$ +:Copyright: Copyright David Abrahams 2003. Use, modification and + distribution is subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy + at http://www.boost.org/LICENSE_1_0.txt) + +.. _`Boost Consulting`: http://www.boost-consulting.com + +.. contents:: Table of Contents + +============== + Introduction +============== + +Several issues with N1550_ (New Iterator Concepts) were raised in +the run-up before the fall 2003 C++ Committee meeting, in a thread +beginning with John Maddock's posting ``c++std-lib-12187``. In +looking at those issues, several other problems came up. This +document addresses those issues and discusses some potential +solutions and their impact on N1530_ (Iterator Facade and Adaptor). + +============ + The Issues +============ + +Non-Uniformity of the "``lvalue_iterator`` Bit" +=============================================== + +The proposed ``iterator_tag`` class template accepts an "access +bits" parameter which includes a bit to indicate the iterator's +*lvalueness* (whether its dereference operator returns a reference +to its ``value_type``. The relevant part of N1550_ says: + + The purpose of the ``lvalue_iterator`` part of the + ``iterator_access`` enum is to communicate to ``iterator_tag`` + whether the reference type is an lvalue so that the appropriate + old category can be chosen for the base class. The + ``lvalue_iterator`` bit is not recorded in the + ``iterator_tag::access`` data member. + +The ``lvalue_iterator`` bit is not recorded because N1550_ aims to +improve orthogonality of the iterator concepts, and a new-style +iterator's lvalueness is detectable by examining its ``reference`` +type. This inside/outside difference is awkward and confusing. + +Redundancy of Some Explicit Access Category Flags +================================================= + +Shortly after N1550_ was accepted, we discovered that an iterator's +lvalueness can be determined knowing only its ``value_type``. This +predicate can be calculated even for old-style iterators (on whose +``reference`` type the standard places few requirements). A trait +in the Boost iterator library does it by relying on the compiler's +unwillingness to bind an rvalue to a ``T&`` function template +parameter. Similarly, it is possible to detect an iterator's +readability knowing only its ``value_type``. Thus, any interface +which asks the *user* to explicitly describe an iterator's +lvalue-ness or readability seems to introduce needless complexity. + +New Access Traits Templates Wrong For Some Iterators +==================================================== + +``is_writable_iterator`` +------------------------ + +The part of the ``is_writable_iterator`` trait definition which +applies to old-style iterators is:: + + if (cat is convertible to output_iterator_tag) + return true; + else if ( + cat is convertible to forward_iterator_tag + and iterator_traits::reference is a + mutable reference) + return true; + else + return false; + +The current forward iterator requirements place no constraints on +the iterator's ``reference`` type, so the logic above will give +false negatives for some otherwise-writable forward iterators whose +``reference`` type is not a mutable reference. Also, it will +report false positives for any forward, bidirectional, or random +access iterator whose ``reference`` is a mutable reference but +whose ``value_type`` is not assignable. + +``is_swappable_iterator`` +------------------------- + +Similarly, the part of ``is_swappable_iterator`` which applies to +old-style iterators is:: + + else if (cat is convertible to forward_iterator_tag) { + if (iterator_traits::reference is a const reference) + return false; + else + return true; + } else + return false; + +In this case false positives are possible for non-writable forward +iterators whose ``reference`` type is not a reference, or as above, +any forward, bidirectional, or random access iterator whose +``reference`` is not a constant reference but whose ``value_type`` +is not assignable (e.g., because it has a private assignment +operator). + +False negatives can be "reasoned away": since it is part of a +writable iterator's concept definition that +``is_writable::value`` is ``true``, any iterator for which +it is ``false`` is by definition not writable. This seems like a +perverse use of logic, though. + +It might be reasonable to conclude that it is a defect that the +standard allows forward iterators with a ``reference`` type other +than ``value_type`` *cv*\ ``&``, but that still leaves the problem +of old-style iterators whose ``value_type`` is not assignable. It +is not possible to correctly compute writability and swappability +for those old-style iterators without intervention +(specializations of ``is_writable_iterator`` and +``is_swappable_iterator``) from a user. + +No Use Cases for Some Access Traits +=================================== + +``is_swappable_iterator`` +------------------------- + +``is_swappable_iterator`` is supposed to yield true if +``iter_swap(x,y)`` is valid for instances ``x`` and ``y`` of type +``I``. The only argument we have heard for +``is_swappable_iterator`` goes something like this: + + *"If* ``is_swappable_iterator`` *yields* ``false``\ *, you + could fall back to using copy construction and assignment on + the* ``value_type`` *instead."* + +This line of reasoning, however, falls down when closely examined. +To achieve the same effect using copy construction and assignment +on the iterator's ``value_type``, the iterator must be readable and +writable, and its ``value_type`` must be copy-constructible. But +then, ``iter_swap`` must work in that case, because its default +implementation just calls ``swap`` on the dereferenced iterators. +The only purpose for the swappable iterator concept is to represent +iterators which do not fulfill the properties listed above, but +which are nonetheless swappable because the user has provided an +overload or specialization of ``iter_swap``. In other words, +generic code which wants to swap the referents of two iterators +should *always* call ``iter_swap`` instead of doing the +assignments. + +``is_writable_iterator`` +------------------------ + +Try to imagine a case where ``is_writable_iterator`` can be used to +choose behavior. Since the only requirement on a writable iterator +is that we can assign into its referent, the only use for +``is_writable_iterator`` in selecting behavior is to modify a +sequence when the sequence is mutable, and to not modify it +otherwise. + +There is no precedent for generic functions which modify their +arguments only if the arguments are non-const reference, and with +good reason: the simple fact that data is mutable does not mean +that a user *intends* it to be mutated. We provide ``const`` and +non-\ ``const`` overloads for functions like ``operator[]``, but +these do not modify data; they merely return a reference to data +which preserves the object's mutability properties. We can do the +same with iterators using their ``reference`` types; the +accessibility of an assignment operator on the ``value_type``, +which determines writability, does not change that. + +The one plausible argument we can imagine for +``is_writable_iterator`` and ``is_swappable_iterator`` is to remove +algorithms from an overload set using a SFINAE technique like +enable_if_, but that seems to be too small a gain for the +requirements imposed on iterator implementors by the need to report +writability and swappability, especially since it can't be done +correctly for all existing iterators. + +.. _enable_if: http://tinyurl.com/tsr7 + +=================== + Proposed Solution +=================== + +(incomplete) + +Change ``iterator_traits`` as follows:: + + iterator_traits::iterator_category + = if (I::iterator_category is a type) // use mpl::has_xxx (SFINAE) + return I::iterator_category + + if (iterator_value_type::type is void + || iterator_difference_type::type is void + ) + return std::output_iterator_tag + + t = iterator_traversal::type + + if (is_lvalue_iterator::value) + { + if (t is convertible to random_access_traversal_tag) + return std::random_access_iterator_tag + if (t is convertible to bidirectional_traversal_tag) + return std::bidirectional_iterator_tag + else if (t is convertible to forward_traversal_tag) + return std::forward_iterator_tag + } + + if (t is convertible to single_pass_traversal_tag + && is_readable_iterator::value + ) + return input_output_iterator_tag // (**) + else + return std::output_iterator_tag + + diff --git a/test/Jamfile b/test/Jamfile index 40d869c..639541c 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -20,6 +20,8 @@ test-suite iterator # These tests should work for just about everything. [ compile is_lvalue_iterator.cpp ] + [ compile is_readable_iterator.cpp ] + [ run unit_tests.cpp ] [ run concept_tests.cpp ] [ run iterator_adaptor_cc.cpp ] diff --git a/test/is_lvalue_iterator.cpp b/test/is_lvalue_iterator.cpp index cf043b7..df2449b 100755 --- a/test/is_lvalue_iterator.cpp +++ b/test/is_lvalue_iterator.cpp @@ -9,6 +9,7 @@ #include #include #include +#include // Last, for BOOST_NO_LVALUE_RETURN_DETECTION #include From 81870ac8b6235885aadb15e9355b71a57f02ff93 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 6 Nov 2003 03:07:31 +0000 Subject: [PATCH 239/265] progress [SVN r20691] --- doc/issues.html | 110 +++++++++++++++++++++++++++++++++++++++++------- doc/issues.rst | 100 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 180 insertions(+), 30 deletions(-) diff --git a/doc/issues.html b/doc/issues.html index eb95f5d..a356a8c 100755 --- a/doc/issues.html +++ b/doc/issues.html @@ -237,9 +237,19 @@ at http://www.b
  • is_writable_iterator
  • +
  • Naming Issues +
  • + + +
  • Proposed Solution (in progress)
  • -
  • Proposed Solution
  • @@ -307,7 +317,8 @@ false negatives for some otherwise-writable forward iterators whose reference type is not a mutable reference. Also, it will report false positives for any forward, bidirectional, or random access iterator whose reference is a mutable reference but -whose value_type is not assignable.

    +whose value_type is not assignable (e.g. has a private +assignment operator).

    is_swappable_iterator

    @@ -361,7 +372,7 @@ on the iterator's value_type, writable, and its value_type must be copy-constructible. But then, iter_swap must work in that case, because its default implementation just calls swap on the dereferenced iterators. -The only purpose for the swappable concept is to represent +The only purpose for the swappable iterator concept is to represent iterators which do not fulfill the properties listed above, but which are nonetheless swappable because the user has provided an overload or specialization of iter_swap. In other words, @@ -388,19 +399,81 @@ same with iterators using their reference< accessibility of an assignment operator on the value_type, which determines writability, does not change that.

    The one plausible argument we can imagine for -is_writable_iterator and is_swappable_iterator is to remove -algorithms from an overload set using a SFINAE technique like -enable_if, but that seems to be too small a gain for the -requirements imposed on iterator implementors by the need to report -writability and swappability, especially since it can't be done -correctly for all existing iterators.

    +is_writable_iterator and is_swappable_iterator is that they +can be used to remove algorithms from an overload set using a +SFINAE technique like enable_if, thus minimizing unintentional +matches due to Koenig Lookup. If it means requiring explicit +indications of writability and swappability from new-style iterator +implementors, however, it seems to be too small a gain to be worth +the cost. That's especially true since we can't get many existing +old-style iterators to meet the same requirements.

    +
    +
    +
    +

    Naming Issues

    +
    +

    Traversal Concepts and Tags

    +

    Howard Hinnant pointed out some inconsistencies with the naming of +these tag types:

    +
    +incrementable_iterator_tag            // ++r, r++
    +single_pass_iterator_tag              // adds a == b, a != b
    +forward_traversal_iterator_tag        // adds multi-pass capability
    +bidirectional_traversal_iterator_tag  // adds --r, r--
    +random_access_traversal_iterator_tag  // adds r+n,n+r,r-n,r[n],etc.
    +
    +

    Howard thought that it might be better if all tag names contained +the word "traversal".

    +

    It's not clear that would result in the best possible names, +though. For example, incrementable iterators can only make a +single pass over their input. What really distinguishes single +pass iterators from incrementable iterators is not that they can +make a single pass, but that they are equality comparable. Forward +traversal iterators really distinguish themselves by introducing +multi-pass capability. Without entering a "Parkinson's Bicycle +Shed" type of discussion, it might be worth giving the names of +these tags (and the associated concepts) some extra attention.

    +
    +
    +

    Access Traits

    +

    The names is_readable, is_writable, and is_swappable +are probably too general for their semantics. In particular, a +swappable iterator is only swappable in the same sense that a +mutable iterator is mutable: the trait refers to the iterator's +referent. It would probably be better to add the _iterator +suffix to each of these names.

    -
    -

    Proposed Solution

    -

    (incomplete)

    -

    Change iterator_traits as follows:

    +
    +

    Proposed Solution (in progress)

    +

    We believe that is_readable_iterator is a fine name for the +proposed is_readable trait and will use that from here on. In +order to avoid confusion, however, and because we aren't terribly +convinced of any answer yet, we are going to phrase this solution +in terms of the existing traversal concept and tag names. We'll +propose a few possible traversal naming schemes at the end of this +section.

    +
    +

    Overview

    +

    Following the dictum that what we can't do well probably shouldn't +be done at all, we'd like to solve many of the problems above by +eliminating details and simplifying the library as proposed. In +particular, we'd eliminate is_writable and is_swappable, +and remove the requirements which say that writable, and swappable +iterators must support these traits. is_readable_iterator has +proven to be useful and will be retained, but since it can be +implemented with no special hints from the iterator, it will not be +mentioned in the readable iterator requirements. Since we don't +want to require the user to explicitly specify access category +information, we'll change iterator_tag so that it computes the +old-style category in terms of the iterator's traversal category, +reference, and value_type.

    +
    +
    +

    Details

    +

    A cleaner solution would change iterator_traits as follows, +though this does not constitute a "pure bolt-on":

     iterator_traits<I>::iterator_category
       = if (I::iterator_category is a type) // use mpl::has_xxx (SFINAE)
    @@ -413,7 +486,7 @@ iterator_traits<I>::iterator_category
     
         t = iterator_traversal<I>::type
         
    -    if (is_lvalue_iterator<I>::value)
    +    if (I is an lvalue iterator)
         {
            if (t is convertible to random_access_traversal_tag)
               return std::random_access_iterator_tag
    @@ -424,18 +497,23 @@ iterator_traits<I>::iterator_category
         }
     
         if (t is convertible to single_pass_traversal_tag
    -        && is_readable_iterator<I>::value
    +        && I is a readable iterator
         )
            return input_output_iterator_tag // (**)
         else
            return std::output_iterator_tag
     
    +
    +

    Impact on N1530 (Iterator Facade and Adaptor)

    +

    XXX

    +
    +
    diff --git a/doc/issues.rst b/doc/issues.rst index 2a35e2a..30226d4 100755 --- a/doc/issues.rst +++ b/doc/issues.rst @@ -92,7 +92,8 @@ false negatives for some otherwise-writable forward iterators whose ``reference`` type is not a mutable reference. Also, it will report false positives for any forward, bidirectional, or random access iterator whose ``reference`` is a mutable reference but -whose ``value_type`` is not assignable. +whose ``value_type`` is not assignable (e.g. has a private +assignment operator). ``is_swappable_iterator`` ------------------------- @@ -181,22 +182,89 @@ accessibility of an assignment operator on the ``value_type``, which determines writability, does not change that. The one plausible argument we can imagine for -``is_writable_iterator`` and ``is_swappable_iterator`` is to remove -algorithms from an overload set using a SFINAE technique like -enable_if_, but that seems to be too small a gain for the -requirements imposed on iterator implementors by the need to report -writability and swappability, especially since it can't be done -correctly for all existing iterators. +``is_writable_iterator`` and ``is_swappable_iterator`` is that they +can be used to remove algorithms from an overload set using a +SFINAE technique like enable_if_, thus minimizing unintentional +matches due to Koenig Lookup. If it means requiring explicit +indications of writability and swappability from new-style iterator +implementors, however, it seems to be too small a gain to be worth +the cost. That's especially true since we can't get many existing +old-style iterators to meet the same requirements. .. _enable_if: http://tinyurl.com/tsr7 -=================== - Proposed Solution -=================== +Naming Issues +============= -(incomplete) +Traversal Concepts and Tags +--------------------------- -Change ``iterator_traits`` as follows:: +Howard Hinnant pointed out some inconsistencies with the naming of +these tag types:: + + incrementable_iterator_tag // ++r, r++ + single_pass_iterator_tag // adds a == b, a != b + forward_traversal_iterator_tag // adds multi-pass capability + bidirectional_traversal_iterator_tag // adds --r, r-- + random_access_traversal_iterator_tag // adds r+n,n+r,r-n,r[n],etc. + +Howard thought that it might be better if all tag names contained +the word "traversal". + +It's not clear that would result in the best possible names, +though. For example, incrementable iterators can only make a +single pass over their input. What really distinguishes single +pass iterators from incrementable iterators is not that they can +make a single pass, but that they are equality comparable. Forward +traversal iterators really distinguish themselves by introducing +multi-pass capability. Without entering a "Parkinson's Bicycle +Shed" type of discussion, it might be worth giving the names of +these tags (and the associated concepts) some extra attention. + +Access Traits +------------- + +The names ``is_readable``, ``is_writable``, and ``is_swappable`` +are probably too general for their semantics. In particular, a +swappable iterator is only swappable in the same sense that a +mutable iterator is mutable: the trait refers to the iterator's +referent. It would probably be better to add the ``_iterator`` +suffix to each of these names. + +================================ + Proposed Solution (in progress) +================================ + +We believe that ``is_readable_iterator`` is a fine name for the +proposed ``is_readable`` trait and will use that from here on. In +order to avoid confusion, however, and because we aren't terribly +convinced of any answer yet, we are going to phrase this solution +in terms of the existing traversal concept and tag names. We'll +propose a few possible traversal naming schemes at the end of this +section. + +Overview +======== + +Following the dictum that what we can't do well probably shouldn't +be done at all, we'd like to solve many of the problems above by +eliminating details and simplifying the library as proposed. In +particular, we'd eliminate ``is_writable`` and ``is_swappable``, +and remove the requirements which say that writable, and swappable +iterators must support these traits. ``is_readable_iterator`` has +proven to be useful and will be retained, but since it can be +implemented with no special hints from the iterator, it will not be +mentioned in the readable iterator requirements. Since we don't +want to require the user to explicitly specify access category +information, we'll change ``iterator_tag`` so that it computes the +old-style category in terms of the iterator's traversal category, +``reference``, and ``value_type``. + +Details +======= + +A cleaner solution would change ``iterator_traits`` as follows, +though this does not constitute a "pure bolt-on":: iterator_traits::iterator_category = if (I::iterator_category is a type) // use mpl::has_xxx (SFINAE) @@ -209,7 +277,7 @@ Change ``iterator_traits`` as follows:: t = iterator_traversal::type - if (is_lvalue_iterator::value) + if (I is an lvalue iterator) { if (t is convertible to random_access_traversal_tag) return std::random_access_iterator_tag @@ -220,10 +288,14 @@ Change ``iterator_traits`` as follows:: } if (t is convertible to single_pass_traversal_tag - && is_readable_iterator::value + && I is a readable iterator ) return input_output_iterator_tag // (**) else return std::output_iterator_tag +Impact on N1530_ (Iterator Facade and Adaptor) +============================================== + +XXX \ No newline at end of file From fed5967d9d7c4988f0da158fa7157297ff9e8b02 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 7 Nov 2003 19:03:58 +0000 Subject: [PATCH 240/265] checkpoint [SVN r20728] --- doc/issues.html | 17 +++++++++++------ doc/issues.rst | 13 +++++++++---- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/doc/issues.html b/doc/issues.html index a356a8c..713f1ba 100755 --- a/doc/issues.html +++ b/doc/issues.html @@ -246,7 +246,7 @@ at http://www.b
  • Proposed Solution (in progress)
  • @@ -470,15 +470,20 @@ information, we'll change iterator_tagreference, and value_type.

    -
    -

    Details

    -

    A cleaner solution would change iterator_traits as follows, -though this does not constitute a "pure bolt-on":

    +
    +

    Future Enhancements

    +

    For C++0x, we could consider a change to iterator_traits which +allows the user to avoid the use of iterator_tag (or similar +devices) altogether and write a new-style iterator by specifying +only a traversal tag. This change is not being proposed as it does +not constitute a "pure bolt-on":

     iterator_traits<I>::iterator_category
       = if (I::iterator_category is a type) // use mpl::has_xxx (SFINAE)
            return I::iterator_category
     
    +    // Only old-style output iterators may have a void value_type 
    +    // or difference_type
         if (iterator_value_type<I>::type is void
             || iterator_difference_type<I>::type is void
         )
    @@ -513,7 +518,7 @@ iterator_traits<I>::iterator_category
     
     
     
    diff --git a/doc/issues.rst b/doc/issues.rst
    index 30226d4..8236634 100755
    --- a/doc/issues.rst
    +++ b/doc/issues.rst
    @@ -260,16 +260,21 @@ information, we'll change ``iterator_tag`` so that it computes the
     old-style category in terms of the iterator's traversal category,
     ``reference``, and ``value_type``.
     
    -Details
    -=======
    +Future Enhancements
    +===================
     
    -A cleaner solution would change ``iterator_traits`` as follows,
    -though this does not constitute a "pure bolt-on"::
    +For C++0x, we could consider a change to ``iterator_traits`` which
    +allows the user to avoid the use of iterator_tag (or similar
    +devices) altogether and write a new-style iterator by specifying
    +only a traversal tag.  This change is not being proposed as it does
    +not constitute a "pure bolt-on"::
     
       iterator_traits::iterator_category
         = if (I::iterator_category is a type) // use mpl::has_xxx (SFINAE)
              return I::iterator_category
     
    +      // Only old-style output iterators may have a void value_type 
    +      // or difference_type
           if (iterator_value_type::type is void
               || iterator_difference_type::type is void
           )
    
    From f8cd96cb2e882059fec6943dc39406f664723605 Mon Sep 17 00:00:00 2001
    From: Dave Abrahams 
    Date: Mon, 10 Nov 2003 04:07:26 +0000
    Subject: [PATCH 241/265] Added
    
    [SVN r20771]
    ---
     test/is_readable_iterator.cpp | 93 +++++++++++++++++++++++++++++++++++
     1 file changed, 93 insertions(+)
     create mode 100755 test/is_readable_iterator.cpp
    
    diff --git a/test/is_readable_iterator.cpp b/test/is_readable_iterator.cpp
    new file mode 100755
    index 0000000..15ed099
    --- /dev/null
    +++ b/test/is_readable_iterator.cpp
    @@ -0,0 +1,93 @@
    +// Copyright David Abrahams 2003. Use, modification and distribution is
    +// subject to the Boost Software License, Version 1.0. (See accompanying
    +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +// Last, for BOOST_NO_LVALUE_RETURN_DETECTION
    +#include 
    +
    +struct v
    +{
    +    v();
    +    ~v();
    +};
    +
    +BOOST_TT_BROKEN_COMPILER_SPEC(v)
    +
    +struct value_iterator : boost::iterator
    +{
    +    v operator*() const;
    +};
    +
    +struct noncopyable_iterator : boost::iterator
    +{
    +    boost::noncopyable const& operator*() const;
    +};
    +
    +struct proxy_iterator : boost::iterator
    +{
    +#if BOOST_WORKAROUND(__GNUC__, == 2)
    +    typedef boost::iterator base;
    +    typedef base::iterator_category iterator_category;
    +    typedef base::value_type value_type;
    +    typedef base::difference_type difference_type;
    +    typedef base::pointer pointer;
    +    typedef base::reference reference;
    +#endif 
    +    
    +    struct proxy
    +    {
    +        operator v&();
    +        proxy& operator=(v) const;
    +    };
    +        
    +    proxy operator*() const;
    +};
    +
    +struct proxy_iterator2 : boost::iterator
    +{
    +#if BOOST_WORKAROUND(__GNUC__, == 2)
    +    typedef boost::iterator base;
    +    typedef base::iterator_category iterator_category;
    +    typedef base::value_type value_type;
    +    typedef base::difference_type difference_type;
    +    typedef base::pointer pointer;
    +    typedef base::reference reference;
    +#endif 
    +    
    +    struct proxy
    +    {
    +        proxy& operator=(v) const;
    +    };
    +        
    +    proxy operator*() const;
    +};
    +
    +BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator::proxy)
    +
    +int main()
    +{
    +    BOOST_STATIC_ASSERT(boost::is_readable_iterator::value);
    +    BOOST_STATIC_ASSERT(boost::is_readable_iterator::value);
    +    BOOST_STATIC_ASSERT(boost::is_readable_iterator::iterator>::value);
    +    BOOST_STATIC_ASSERT(boost::is_readable_iterator::const_iterator>::value);
    +    BOOST_STATIC_ASSERT(!boost::is_readable_iterator > >::value);
    +    BOOST_STATIC_ASSERT(!boost::is_readable_iterator >::value);
    +    BOOST_STATIC_ASSERT(boost::is_readable_iterator::value);
    +    BOOST_STATIC_ASSERT(!boost::is_readable_iterator::value);
    +    BOOST_STATIC_ASSERT(boost::is_readable_iterator::value);
    +    
    +    // Make sure inaccessible copy constructor doesn't prevent
    +    // readability
    +    BOOST_STATIC_ASSERT(boost::is_readable_iterator::value);
    +    
    +    return 0;
    +}
    
    From cb34b65f3fde0260efc8aa39b078c1ab7f8853db Mon Sep 17 00:00:00 2001
    From: Dave Abrahams 
    Date: Mon, 10 Nov 2003 04:13:16 +0000
    Subject: [PATCH 242/265] Fix missing is_readable_iterator test Fix naming for
     is_lvalue_iterator and is_mutable_lvalue_iterator
    
    [SVN r20772]
    ---
     include/boost/iterator/is_lvalue_iterator.hpp |   6 +-
     .../boost/iterator/is_readable_iterator.hpp   | 108 ++++++++++++++++++
     test/is_lvalue_iterator.cpp                   |  36 +++---
     3 files changed, 129 insertions(+), 21 deletions(-)
     create mode 100755 include/boost/iterator/is_readable_iterator.hpp
    
    diff --git a/include/boost/iterator/is_lvalue_iterator.hpp b/include/boost/iterator/is_lvalue_iterator.hpp
    index a89b373..9a31322 100755
    --- a/include/boost/iterator/is_lvalue_iterator.hpp
    +++ b/include/boost/iterator/is_lvalue_iterator.hpp
    @@ -126,7 +126,7 @@ namespace detail
       {};
     
       template 
    -  struct is_writable_lvalue_iterator_impl
    +  struct is_mutable_lvalue_iterator_impl
         : is_lvalue_iterator_impl<
               BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits::value_type
           >::template rebind
    @@ -136,10 +136,10 @@ namespace detail
     // Define the trait with full mpl lambda capability and various broken
     // compiler workarounds
     BOOST_TT_AUX_BOOL_TRAIT_DEF1(
    -    is_readable_lvalue_iterator,T,::boost::detail::is_readable_lvalue_iterator_impl::value)
    +    is_lvalue_iterator,T,::boost::detail::is_readable_lvalue_iterator_impl::value)
         
     BOOST_TT_AUX_BOOL_TRAIT_DEF1(
    -    is_writable_lvalue_iterator,T,::boost::detail::is_writable_lvalue_iterator_impl::value)
    +    is_mutable_lvalue_iterator,T,::boost::detail::is_mutable_lvalue_iterator_impl::value)
         
     } // namespace boost
     
    diff --git a/include/boost/iterator/is_readable_iterator.hpp b/include/boost/iterator/is_readable_iterator.hpp
    new file mode 100755
    index 0000000..40ab89f
    --- /dev/null
    +++ b/include/boost/iterator/is_readable_iterator.hpp
    @@ -0,0 +1,108 @@
    +// Copyright David Abrahams 2003. Use, modification and distribution is
    +// subject to the Boost Software License, Version 1.0. (See accompanying
    +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
    +#ifndef IS_READABLE_ITERATOR_DWA2003112_HPP
    +# define IS_READABLE_ITERATOR_DWA2003112_HPP
    +
    +#include 
    +#include 
    +
    +// should be the last #include
    +#include 
    +#include 
    +
    +namespace boost {
    + 
    +namespace detail
    +{
    +  struct any_conversion_eater
    +  {
    +      template 
    +      any_conversion_eater(T const&);
    +  };
    +  
    +  // Guts of is_readable_iterator.  Value is the iterator's value_type
    +  // and the result is computed in the nested rebind template.
    +  template 
    +  struct is_readable_iterator_impl
    +  {
    +      static char tester(Value&, int);
    +      static char (& tester(any_conversion_eater, ...) )[2];
    +    
    +      template 
    +      struct rebind
    +      {
    +          static It& x;
    +          
    +          BOOST_STATIC_CONSTANT(
    +              bool
    +            , value = (
    +                sizeof(
    +                    is_readable_iterator_impl::tester(*x, 1)
    +                ) == 1
    +            )
    +          );
    +      };
    +  };
    +
    +#undef BOOST_READABLE_PRESERVER
    +  
    +  //
    +  // void specializations to handle std input and output iterators
    +  //
    +  template <>
    +  struct is_readable_iterator_impl
    +  {
    +      template 
    +      struct rebind : boost::mpl::false_
    +      {};
    +  };
    +
    +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
    +  template <>
    +  struct is_readable_iterator_impl
    +  {
    +      template 
    +      struct rebind : boost::mpl::false_
    +      {};
    +  };
    +
    +  template <>
    +  struct is_readable_iterator_impl
    +  {
    +      template 
    +      struct rebind : boost::mpl::false_
    +      {};
    +  };
    +
    +  template <>
    +  struct is_readable_iterator_impl
    +  {
    +      template 
    +      struct rebind : boost::mpl::false_
    +      {};
    +  };
    +#endif
    +
    +  //
    +  // This level of dispatching is required for Borland.  We might save
    +  // an instantiation by removing it for others.
    +  //
    +  template 
    +  struct is_readable_iterator_impl2
    +    : is_readable_iterator_impl<
    +          BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits::value_type const
    +      >::template rebind
    +  {};
    +} // namespace detail
    +
    +// Define the trait with full mpl lambda capability and various broken
    +// compiler workarounds
    +BOOST_TT_AUX_BOOL_TRAIT_DEF1(
    +    is_readable_iterator,T,::boost::detail::is_readable_iterator_impl2::value)
    +    
    +} // namespace boost
    +
    +#include 
    +
    +#endif // IS_READABLE_ITERATOR_DWA2003112_HPP
    diff --git a/test/is_lvalue_iterator.cpp b/test/is_lvalue_iterator.cpp
    index df2449b..9c23c9c 100755
    --- a/test/is_lvalue_iterator.cpp
    +++ b/test/is_lvalue_iterator.cpp
    @@ -56,32 +56,32 @@ BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator::proxy)
     
     int main()
     {
    -    BOOST_STATIC_ASSERT(boost::is_readable_lvalue_iterator::value);
    -    BOOST_STATIC_ASSERT(boost::is_readable_lvalue_iterator::value);
    -    BOOST_STATIC_ASSERT(boost::is_readable_lvalue_iterator::iterator>::value);
    -    BOOST_STATIC_ASSERT(boost::is_readable_lvalue_iterator::const_iterator>::value);
    -    BOOST_STATIC_ASSERT(!boost::is_readable_lvalue_iterator > >::value);
    -    BOOST_STATIC_ASSERT(!boost::is_readable_lvalue_iterator >::value);
    -    BOOST_STATIC_ASSERT(!boost::is_readable_lvalue_iterator::value);
    +    BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::value);
    +    BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::value);
    +    BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::iterator>::value);
    +    BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::const_iterator>::value);
    +    BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator > >::value);
    +    BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator >::value);
    +    BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator::value);
     #ifndef BOOST_NO_LVALUE_RETURN_DETECTION
    -    BOOST_STATIC_ASSERT(!boost::is_readable_lvalue_iterator::value);
    +    BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator::value);
     #endif
         // Make sure inaccessible copy constructor doesn't prevent
         // reference binding
    -    BOOST_STATIC_ASSERT(boost::is_readable_lvalue_iterator::value);
    +    BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::value);
     
         
    -    BOOST_STATIC_ASSERT(boost::is_writable_lvalue_iterator::value);
    -    BOOST_STATIC_ASSERT(!boost::is_writable_lvalue_iterator::value);
    -    BOOST_STATIC_ASSERT(boost::is_writable_lvalue_iterator::iterator>::value);
    -    BOOST_STATIC_ASSERT(!boost::is_writable_lvalue_iterator::const_iterator>::value);
    -    BOOST_STATIC_ASSERT(!boost::is_writable_lvalue_iterator > >::value);
    -    BOOST_STATIC_ASSERT(!boost::is_writable_lvalue_iterator >::value);
    -    BOOST_STATIC_ASSERT(!boost::is_writable_lvalue_iterator::value);
    +    BOOST_STATIC_ASSERT(boost::is_mutable_lvalue_iterator::value);
    +    BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::value);
    +    BOOST_STATIC_ASSERT(boost::is_mutable_lvalue_iterator::iterator>::value);
    +    BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::const_iterator>::value);
    +    BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator > >::value);
    +    BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator >::value);
    +    BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::value);
     #ifndef BOOST_NO_LVALUE_RETURN_DETECTION
    -    BOOST_STATIC_ASSERT(!boost::is_writable_lvalue_iterator::value);
    +    BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::value);
     #endif
    -    BOOST_STATIC_ASSERT(!boost::is_writable_lvalue_iterator::value);
    +    BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::value);
         
         return 0;
     }
    
    From c055f1afaeb29a2f30370ecebb6029b5a68cf063 Mon Sep 17 00:00:00 2001
    From: Jeremy Siek 
    Date: Thu, 13 Nov 2003 18:18:23 +0000
    Subject: [PATCH 243/265] fixed typo
    
    [SVN r20805]
    ---
     doc/new-iter-concepts.rst | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst
    index 6023b35..07b8595 100644
    --- a/doc/new-iter-concepts.rst
    +++ b/doc/new-iter-concepts.rst
    @@ -157,7 +157,7 @@ Changes to Algorithm Requirements
     
     For the next working paper (but not for TR1), the committee should
     consider the following changes to the type requirements of
    -algorithms.  These changes are phrased as phrased as textual
    +algorithms.  These changes are phrased as textual
     substitutions, listing the algorithms to which each textual
     substitution applies.
     
    
    From 69d8856572aa3966be7d6d41ccf916cc7482b3d5 Mon Sep 17 00:00:00 2001
    From: Jeremy Siek 
    Date: Mon, 17 Nov 2003 16:24:29 +0000
    Subject: [PATCH 244/265] major revision, narrowed the focus of the paper
    
    [SVN r20826]
    ---
     doc/issues.rst | 429 ++++++++++++++++++-------------------------------
     1 file changed, 156 insertions(+), 273 deletions(-)
    
    diff --git a/doc/issues.rst b/doc/issues.rst
    index 8236634..4ac2f07 100755
    --- a/doc/issues.rst
    +++ b/doc/issues.rst
    @@ -1,6 +1,6 @@
    -+++++++++++++++++++++++++++++++
    - Issues With N1550_ and N1530_
    -+++++++++++++++++++++++++++++++
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    + Problem with ``is_writable`` and ``is_swappable`` in N1550_
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     
     .. _N1550: http://www.boost-consulting.com/writing/n1550.html
     .. _N1530: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1530.html
    @@ -22,285 +22,168 @@
      Introduction
     ==============
     
    -Several issues with N1550_ (New Iterator Concepts) were raised in
    -the run-up before the fall 2003 C++ Committee meeting, in a thread
    -beginning with John Maddock's posting ``c++std-lib-12187``.  In
    -looking at those issues, several other problems came up.  This
    -document addresses those issues and discusses some potential
    -solutions and their impact on N1530_ (Iterator Facade and Adaptor).
    +The ``is_writable`` and ``is_swappable`` traits classes in N1550_
    +provide a mechanism for determining at compile time if a type is a
    +model of the new Writable Iterator and Swappable Iterator concepts,
    +analogous to ``iterator_traits::iterator_category`` for the old
    +iterator concepts. For backward compatibility, ``is_writable`` and
    +``is_swappable`` not only work with new iterators, but they also are
    +intended to work for old iterators (iterators that meet the
    +requirements for one of the iterator concepts in the current
    +standard). In the case of old iterators, the writability and
    +swapability is deduced based on the ``iterator_category`` and also the
    +``reference`` type. The specification for this deduction gives false
    +positives for forward iterators that have non-assignable value types.
     
    -============
    - The Issues
    -============
    -
    -Non-Uniformity of the "``lvalue_iterator`` Bit"
    -===============================================
    -
    -The proposed ``iterator_tag`` class template accepts an "access
    -bits" parameter which includes a bit to indicate the iterator's
    -*lvalueness* (whether its dereference operator returns a reference
    -to its ``value_type``.  The relevant part of N1550_ says:
    -
    -  The purpose of the ``lvalue_iterator`` part of the
    -  ``iterator_access`` enum is to communicate to ``iterator_tag``
    -  whether the reference type is an lvalue so that the appropriate
    -  old category can be chosen for the base class. The
    -  ``lvalue_iterator`` bit is not recorded in the
    -  ``iterator_tag::access`` data member.
    -
    -The ``lvalue_iterator`` bit is not recorded because N1550_ aims to
    -improve orthogonality of the iterator concepts, and a new-style
    -iterator's lvalueness is detectable by examining its ``reference``
    -type.  This inside/outside difference is awkward and confusing.
    -
    -Redundancy of Some Explicit Access Category Flags
    -=================================================
    -
    -Shortly after N1550_ was accepted, we discovered that an iterator's
    -lvalueness can be determined knowing only its ``value_type``.  This
    -predicate can be calculated even for old-style iterators (on whose
    -``reference`` type the standard places few requirements).  A trait
    -in the Boost iterator library does it by relying on the compiler's
    -unwillingness to bind an rvalue to a ``T&`` function template
    -parameter.  Similarly, it is possible to detect an iterator's
    -readability knowing only its ``value_type``. Thus, any interface
    -which asks the *user* to explicitly describe an iterator's
    -lvalue-ness or readability seems to introduce needless complexity.
    -
    -New Access Traits Templates Wrong For Some Iterators
    -====================================================
    -
    -``is_writable_iterator``
    -------------------------
    -
    -The part of the ``is_writable_iterator`` trait definition which
    -applies to old-style iterators is::
    +To review, the part of the ``is_writable`` trait definition which
    +applies to old iterators is::
     
       if (cat is convertible to output_iterator_tag)
    -           return true;
    -      else if (
    -           cat is convertible to forward_iterator_tag
    +      return true;
    +  else if (cat is convertible to forward_iterator_tag
                and iterator_traits::reference is a 
                    mutable reference)
    -          return true;
    -      else
    -          return false;
    +      return true;
    +  else
    +      return false;
     
    -The current forward iterator requirements place no constraints on
    -the iterator's ``reference`` type, so the logic above will give
    -false negatives for some otherwise-writable forward iterators whose
    -``reference`` type is not a mutable reference.  Also, it will
    -report false positives for any forward, bidirectional, or random
    -access iterator whose ``reference`` is a mutable reference but
    -whose ``value_type`` is not assignable (e.g. has a private
    -assignment operator).
    +Suppose the ``value_type`` of the iterator has a private assignment
    +operator::
     
    -``is_swappable_iterator``
    --------------------------
    +  class B {
    +  public:
    +    ...
    +  private:
    +    B& operator=(const B&);
    +  };
     
    -Similarly, the part of ``is_swappable_iterator`` which applies to
    -old-style iterators is::
    +and suppose the ``reference`` type of the iterator is ``B&``.  Then
    +``is_writable`` will deduce true when in fact attempting to write into
    +``B`` will cause an error.
     
    -    else if (cat is convertible to forward_iterator_tag) {
    -        if (iterator_traits::reference is a const reference)
    -            return false;
    -        else
    -            return true;
    -    } else 
    -        return false;
    -
    -In this case false positives are possible for non-writable forward
    -iterators whose ``reference`` type is not a reference, or as above,
    -any forward, bidirectional, or random access iterator whose
    -``reference`` is not a constant reference but whose ``value_type``
    -is not assignable (e.g., because it has a private assignment
    -operator).
    -
    -False negatives can be "reasoned away": since it is part of a
    -writable iterator's concept definition that
    -``is_writable::value`` is ``true``, any iterator for which
    -it is ``false`` is by definition not writable.  This seems like a
    -perverse use of logic, though.
    -
    -It might be reasonable to conclude that it is a defect that the
    -standard allows forward iterators with a ``reference`` type other
    -than ``value_type`` *cv*\ ``&``, but that still leaves the problem
    -of old-style iterators whose ``value_type`` is not assignable.  It
    -is not possible to correctly compute writability and swappability
    -for those old-style iterators without intervention
    -(specializations of ``is_writable_iterator`` and
    -``is_swappable_iterator``) from a user.
    -
    -No Use Cases for Some Access Traits 
    -===================================
    -
    -``is_swappable_iterator``
    --------------------------
    -
    -``is_swappable_iterator`` is supposed to yield true if
    -``iter_swap(x,y)`` is valid for instances ``x`` and ``y`` of type
    -``I``.  The only argument we have heard for
    -``is_swappable_iterator`` goes something like this:
    -
    -     *"If* ``is_swappable_iterator`` *yields* ``false``\ *, you
    -     could fall back to using copy construction and assignment on
    -     the* ``value_type`` *instead."*
    -
    -This line of reasoning, however, falls down when closely examined.
    -To achieve the same effect using copy construction and assignment
    -on the iterator's ``value_type``, the iterator must be readable and
    -writable, and its ``value_type`` must be copy-constructible.  But
    -then, ``iter_swap`` must work in that case, because its default
    -implementation just calls ``swap`` on the dereferenced iterators.
    -The only purpose for the swappable iterator concept is to represent
    -iterators which do not fulfill the properties listed above, but
    -which are nonetheless swappable because the user has provided an
    -overload or specialization of ``iter_swap``.  In other words,
    -generic code which wants to swap the referents of two iterators
    -should *always* call ``iter_swap`` instead of doing the
    -assignments.
    -
    -``is_writable_iterator``
    -------------------------
    -
    -Try to imagine a case where ``is_writable_iterator`` can be used to
    -choose behavior.  Since the only requirement on a writable iterator
    -is that we can assign into its referent, the only use for
    -``is_writable_iterator`` in selecting behavior is to modify a
    -sequence when the sequence is mutable, and to not modify it
    -otherwise.
    -
    -There is no precedent for generic functions which modify their
    -arguments only if the arguments are non-const reference, and with
    -good reason: the simple fact that data is mutable does not mean
    -that a user *intends* it to be mutated.  We provide ``const`` and
    -non-\ ``const`` overloads for functions like ``operator[]``, but
    -these do not modify data; they merely return a reference to data
    -which preserves the object's mutability properties.  We can do the
    -same with iterators using their ``reference`` types; the
    -accessibility of an assignment operator on the ``value_type``,
    -which determines writability, does not change that.
    -
    -The one plausible argument we can imagine for
    -``is_writable_iterator`` and ``is_swappable_iterator`` is that they
    -can be used to remove algorithms from an overload set using a
    -SFINAE technique like enable_if_, thus minimizing unintentional
    -matches due to Koenig Lookup.  If it means requiring explicit
    -indications of writability and swappability from new-style iterator
    -implementors, however, it seems to be too small a gain to be worth
    -the cost.  That's especially true since we can't get many existing
    -old-style iterators to meet the same requirements.
    -
    -.. _enable_if: http://tinyurl.com/tsr7
    -
    -Naming Issues
    -=============
    -
    -Traversal Concepts and Tags
    ----------------------------
    -
    -Howard Hinnant pointed out some inconsistencies with the naming of
    -these tag types::
    -
    -  incrementable_iterator_tag            // ++r, r++
    -  single_pass_iterator_tag              // adds a == b, a != b
    -  forward_traversal_iterator_tag        // adds multi-pass capability
    -  bidirectional_traversal_iterator_tag  // adds --r, r--
    -  random_access_traversal_iterator_tag  // adds r+n,n+r,r-n,r[n],etc.
    -
    -Howard thought that it might be better if all tag names contained
    -the word "traversal".
    -
    -It's not clear that would result in the best possible names,
    -though.  For example, incrementable iterators can only make a
    -single pass over their input.  What really distinguishes single
    -pass iterators from incrementable iterators is not that they can
    -make a single pass, but that they are equality comparable.  Forward
    -traversal iterators really distinguish themselves by introducing
    -multi-pass capability.  Without entering a "Parkinson's Bicycle
    -Shed" type of discussion, it might be worth giving the names of
    -these tags (and the associated concepts) some extra attention.
    -
    -Access Traits
    --------------
    -
    -The names ``is_readable``, ``is_writable``, and ``is_swappable``
    -are probably too general for their semantics.  In particular, a
    -swappable iterator is only swappable in the same sense that a
    -mutable iterator is mutable: the trait refers to the iterator's
    -referent.  It would probably be better to add the ``_iterator``
    -suffix to each of these names.
    -
    -================================
    - Proposed Solution (in progress)
    -================================
    -
    -We believe that ``is_readable_iterator`` is a fine name for the
    -proposed ``is_readable`` trait and will use that from here on.  In
    -order to avoid confusion, however, and because we aren't terribly
    -convinced of any answer yet, we are going to phrase this solution
    -in terms of the existing traversal concept and tag names.  We'll
    -propose a few possible traversal naming schemes at the end of this
    -section.
    -
    -Overview
    -========
    -
    -Following the dictum that what we can't do well probably shouldn't
    -be done at all, we'd like to solve many of the problems above by
    -eliminating details and simplifying the library as proposed.  In
    -particular, we'd eliminate ``is_writable`` and ``is_swappable``,
    -and remove the requirements which say that writable, and swappable
    -iterators must support these traits.  ``is_readable_iterator`` has
    -proven to be useful and will be retained, but since it can be
    -implemented with no special hints from the iterator, it will not be
    -mentioned in the readable iterator requirements.  Since we don't
    -want to require the user to explicitly specify access category
    -information, we'll change ``iterator_tag`` so that it computes the
    -old-style category in terms of the iterator's traversal category,
    -``reference``, and ``value_type``.
    -
    -Future Enhancements
    -===================
    -
    -For C++0x, we could consider a change to ``iterator_traits`` which
    -allows the user to avoid the use of iterator_tag (or similar
    -devices) altogether and write a new-style iterator by specifying
    -only a traversal tag.  This change is not being proposed as it does
    -not constitute a "pure bolt-on"::
    -
    -  iterator_traits::iterator_category
    -    = if (I::iterator_category is a type) // use mpl::has_xxx (SFINAE)
    -         return I::iterator_category
    -
    -      // Only old-style output iterators may have a void value_type 
    -      // or difference_type
    -      if (iterator_value_type::type is void
    -          || iterator_difference_type::type is void
    -      )
    -         return std::output_iterator_tag
    -
    -      t = iterator_traversal::type
    -      
    -      if (I is an lvalue iterator)
    -      {
    -         if (t is convertible to random_access_traversal_tag)
    -            return std::random_access_iterator_tag
    -         if (t is convertible to bidirectional_traversal_tag)
    -            return std::bidirectional_iterator_tag
    -         else if (t is convertible to forward_traversal_tag)
    -            return std::forward_iterator_tag
    -      }
    -
    -      if (t is convertible to single_pass_traversal_tag
    -          && I is a readable iterator
    -      )
    -         return input_output_iterator_tag // (**)
    -      else
    -         return std::output_iterator_tag
    +The same problem applies to ``is_swappable``.
     
     
    -Impact on N1530_ (Iterator Facade and Adaptor)
    -==============================================
    +====================
    + Proposed Resolution
    +====================
    +
    +1. Remove the ``is_writable`` and ``is_swappable`` traits, and remove the
    +   requirements in the Writable Iterator and Swappable Iterator concepts
    +   that require their models to support these traits.
    +
    +2. Change the ``is_readable`` specification to be:
    +   ``is_readable::type`` is ``true_type`` if the
    +   result type of ``X::operator*`` is convertible to
    +   ``iterator_traits::value_type`` and is ``false_type``
    +   otherwise.
    +
    +   Remove the requirement for support of the ``is_readable`` trait from
    +   the Readable Iterator concept.
    +
    +3. Change ``iterator_tag`` to::
    +
    +     template 
    +     struct iterator_tag;
    +
    +   The argument for ``Value`` must be the value type of the
    +   iterator, ``Reference`` must be the return type of
    +   ``operator*`` [*]_, and ``Traversal`` the traversal tag for the
    +   iterator.
    +
    +   ``iterator_tag`` is required to be convertible to both the
    +   ``Traversal`` tag and also to the appropriate old iterator category
    +   tag, as specified by the following pseudo-code::
    +
    +     inherit-category(Value, Reference, Traversal) =
    +         if (Reference is a reference
    +             and Traversal is convertible to forward_traversal_tag) {
    +             if (Traversal is convertible to random_access_traversal_tag)
    +                 return random_access_iterator_tag;
    +             else if (Traversal is convertible to bidirectional_traversal_tag)
    +                 return bidirectional_iterator_tag;
    +             else
    +                 return forward_iterator_tag;
    +         } else if (Traversal is convertible to single_pass_traversal_tag
    +                    and Reference is convertible to Value) {
    +             if (Value is const)
    +                 return input_iterator_tag;
    +             else
    +                 return input_output_iterator_tag;
    +         } else
    +             return output_iterator_tag;
    +             
    +
    +.. [*] Instead of saying "return type of operator*", we could have
    +   said ``iterator_traits::reference``. However, the standard
    +   specifies nothing about ``iterator_traits::reference``,
    +   which we believe is a defect. Once the defect is fixed,
    +   the above could be rephrased.
    +
    +
    +4. Change the specification of ``traversal_category`` to::
    +
    +    traversal-category(Iterator) =
    +	let cat = iterator_traits::iterator_category
    +	if (cat convertible to incrementable_iterator_tag)
    +	  return cat; // Iterator is a new iterator
    +	else if (cat is convertible to random_access_iterator_tag)
    +	    return random_access_traversal_tag;
    +	else if (cat is convertible to bidirectional_iterator_tag)
    +	    return bidirectional_traversal_tag;
    +	else if (cat is convertible to forward_iterator_tag)
    +	    return forward_traversal_tag;
    +	else if (cat is convertible to input_iterator_tag)
    +	    return single_pass_iterator_tag;
    +	else if (cat is convertible to output_iterator_tag)
    +	    return incrementable_iterator_tag;
    +	else
    +	    return null_category_tag;
    +
    +
    +==========
    + Rationale
    +==========
    +
    +1. There are two reasons for removing ``is_writable``
    +   and ``is_swappable``. The first is that we do not know of
    +   a way to fix the specification so that it gives the correct
    +   answer for all iterators. Second, there was only a weak
    +   motivation for having ``is_writable`` and ``is_swappable``
    +   there in the first place. The main motivation was simply
    +   uniformity: we have tags for the old iterator categories
    +   so we should have tags for the new iterator categories.
    +   While having tags and the capability to dispatch based
    +   on the traversal categories is often used, we see
    +   less of a need for dispatching based on writability
    +   and swappability, since typically algorithms
    +   that need these capabilities have no alternative if
    +   they are not provided.
    +
    +2. We discovered that the ``is_readable`` trait can be
    +   implemented without special hints from the iterator.
    +   Therefore we remove the requirement for ``is_readable``
    +   from the Readable Iterator concept, and change
    +   the definition of ``is_readable`` so that it works
    +   for any iterator type.
    +
    +3. With ``is_writable`` and ``is_swappable`` gone, and
    +   ``is_readable`` no longer in need of special hints,
    +   there is no reason for the ``iterator_tag`` class to provide
    +   information about the access capabilities of an iterator.
    +   This new version provides only information about the traversal
    +   capabilities and the old iterator category tag. Instead of accessing
    +   the traversal category as a nested typedef ``::traversal``,
    +   the ``iterator_tag`` itself will be convertible to the traversal
    +   tag. The ``access_bits`` parameter is no longer needed for
    +   specifying the access member (which is now gone). However,
    +   some access information is still needed so that we can
    +   deduce the appropriate old iterator category. The 
    +   ``Value`` and ``Reference`` parameters fill this need.
    +   Note that this solution cleans up the issue that John
    +   Maddock raised on the reflector about the non-uniformity
    +   of the lvalue bit.
    +
    +4. The changes to the specification of ``traversal_category`` are a 
    +   direct result of the changes to ``iterator_tag``.
     
    -XXX
    \ No newline at end of file
    
    From 7946d32cef073b21dc1681c5dd59cc25a04c4cc0 Mon Sep 17 00:00:00 2001
    From: Jeremy Siek 
    Date: Mon, 17 Nov 2003 16:33:28 +0000
    Subject: [PATCH 245/265] added my name to the Author list
    
    [SVN r20828]
    ---
     doc/issues.rst | 8 ++++----
     1 file changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/doc/issues.rst b/doc/issues.rst
    index 4ac2f07..0d5e155 100755
    --- a/doc/issues.rst
    +++ b/doc/issues.rst
    @@ -5,11 +5,11 @@
     .. _N1550: http://www.boost-consulting.com/writing/n1550.html
     .. _N1530: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1530.html
     
    -:Author: David Abrahams
    -:Contact: dave@boost-consulting.com
    -:Organization: `Boost Consulting`_
    +:Author: David Abrahams and Jeremy Siek
    +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu
    +:Organization: `Boost Consulting`_, Indiana University Bloomington
     :date: $Date$
    -:Copyright: Copyright David Abrahams 2003. Use, modification and
    +:Copyright: Copyright David Abrahams, Jeremy Siek 2003. Use, modification and
           distribution is subject to the Boost Software License,
           Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
           at http://www.boost.org/LICENSE_1_0.txt)
    
    From 4cc5f9a4d65bc894f0c6dbbc86bf488ae70875e1 Mon Sep 17 00:00:00 2001
    From: Dave Abrahams 
    Date: Mon, 17 Nov 2003 16:52:15 +0000
    Subject: [PATCH 246/265] iterator_categories reformed, test added
    
    [SVN r20829]
    ---
     test/Jamfile                 |  1 +
     test/iterator_categories.cpp | 91 ++++++++++++++++++++++++++++++++++++
     2 files changed, 92 insertions(+)
     create mode 100755 test/iterator_categories.cpp
    
    diff --git a/test/Jamfile b/test/Jamfile
    index 639541c..1a7b9a1 100644
    --- a/test/Jamfile
    +++ b/test/Jamfile
    @@ -34,6 +34,7 @@ test-suite iterator
         [ run counting_iterator_test.cpp ]
         [ run permutation_iterator_test.cpp : : : # on 
         ]
    +    [ compile iterator_categories.cpp ]
         [ run zip_iterator_test.cpp ]
           
         [ run ../../utility/iterator_adaptor_examples.cpp ]
    diff --git a/test/iterator_categories.cpp b/test/iterator_categories.cpp
    new file mode 100755
    index 0000000..e36f2c9
    --- /dev/null
    +++ b/test/iterator_categories.cpp
    @@ -0,0 +1,91 @@
    +// Copyright David Abrahams 2003. Use, modification and distribution is
    +// subject to the Boost Software License, Version 1.0. (See accompanying
    +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
    +
    +#include 
    +
    +using namespace boost;
    +
    +// Utility function which converts an iterator_category into a
    +// traversal tag
    +template 
    +typename iterator_category_to_traversal::type c2t(C)
    +{
    +    typedef typename iterator_category_to_traversal::type result;
    +    return result();
    +}
    +
    +struct v
    +{
    +    v();
    +    ~v();
    +};
    +
    +//
    +// Test conversions from iterator_tag<...> to old-style iterator categories
    +//
    +
    +// These "solid" tag types ensure exact matching of iterator
    +// classification, because unlike the std:: iterator tags, they're not
    +// inter-convertible
    +struct output_iter {};
    +struct input_iter {};
    +struct input_output_iter {};
    +struct forward_iter {};
    +struct bidirectional_iter {};
    +struct random_access_iter{} ;
    +
    +// Convert various old-style categories into "solid" tags.
    +input_iter         cat(std::input_iterator_tag);
    +output_iter        cat(std::output_iterator_tag);
    +input_output_iter  cat(boost::detail::input_output_iterator_tag);
    +forward_iter       cat(std::forward_iterator_tag);
    +bidirectional_iter cat(std::bidirectional_iterator_tag);
    +random_access_iter cat(std::random_access_iterator_tag);
    +
    +random_access_iter  x1 = cat(iterator_tag());
    +random_access_iter  x2 = cat(iterator_tag());
    +bidirectional_iter  x3 = cat(iterator_tag());
    +forward_iter        x4 = cat(iterator_tag());
    +input_output_iter   x5 = cat(iterator_tag());
    +input_iter          x6 = cat(iterator_tag());
    +output_iter         x7 = cat(iterator_tag());
    +
    +
    +//
    +// Test conversion from old-style iterator categories to traversal categories
    +//
    +
    +// These "solid" tag types ensure exact matching of iterator
    +// classification, because unlike the traversal tags, they're not
    +// inter-convertible
    +struct incrementable_traversal {};
    +struct single_pass_traversal {};
    +struct forward_traversal {};
    +struct bidirectional_traversal {};
    +struct random_access_traversal {} ;
    +
    +// Convert various traversal categories into "solid" tags
    +incrementable_traversal trav(incrementable_traversal_tag);
    +single_pass_traversal   trav(single_pass_traversal_tag);
    +forward_traversal       trav(forward_traversal_tag);
    +bidirectional_traversal trav(bidirectional_traversal_tag);
    +random_access_traversal trav(random_access_traversal_tag);
    +
    +// Show that full types of tags that are already traversal categories
    +// are preserved
    +iterator_tag yz1
    +     = c2t(iterator_tag());
    +
    +// Test traversal extraction from both old-style and new-style tags
    +random_access_traversal  yy1 = trav(c2t(iterator_tag()));
    +bidirectional_traversal  yy2 = trav(c2t(iterator_tag()));
    +forward_traversal        yy3 = trav(c2t(iterator_tag()));
    +single_pass_traversal    yy4 = trav(c2t(iterator_tag()));
    +incrementable_traversal  yy5 = trav(c2t(iterator_tag()));
    +
    +random_access_traversal  z1 = trav(c2t(std::random_access_iterator_tag()));
    +bidirectional_traversal  z2 = trav(c2t(std::bidirectional_iterator_tag()));
    +forward_traversal        z3 = trav(c2t(std::forward_iterator_tag()));
    +single_pass_traversal    z4 = trav(c2t(std::input_iterator_tag()));
    +incrementable_traversal  z5 = trav(c2t(std::output_iterator_tag()));
    
    From 104faa5ab336f7b5084f95e1b6b851d4966bc063 Mon Sep 17 00:00:00 2001
    From: Jeremy Siek 
    Date: Mon, 17 Nov 2003 16:52:29 +0000
    Subject: [PATCH 247/265] new file
    
    [SVN r20830]
    ---
     doc/ref_problem.rst | 63 +++++++++++++++++++++++++++++++++++++++++++++
     1 file changed, 63 insertions(+)
     create mode 100644 doc/ref_problem.rst
    
    diff --git a/doc/ref_problem.rst b/doc/ref_problem.rst
    new file mode 100644
    index 0000000..2f2908a
    --- /dev/null
    +++ b/doc/ref_problem.rst
    @@ -0,0 +1,63 @@
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    + Problem with ``reference`` and old/new iterator category correspondance
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    +
    +.. _N1550: http://www.boost-consulting.com/writing/n1550.html
    +.. _N1530: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1530.html
    +
    +:Author: David Abrahams and Jeremy Siek
    +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu
    +:Organization: `Boost Consulting`_, Indiana University Bloomington
    +:date: $Date$
    +:Copyright: Copyright David Abrahams, Jeremy Siek 2003. Use, modification and
    +      distribution is subject to the Boost Software License,
    +      Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
    +      at http://www.boost.org/LICENSE_1_0.txt)
    +
    +.. _`Boost Consulting`: http://www.boost-consulting.com
    +
    +==============
    + Introduction
    +==============
    +
    +The new iterator categories are intended to correspond to the old
    +iterator categories, as specified in a diagram in N1550_. For example,
    +an iterator categorized as a mutable Forward Iterator under the old
    +scheme is now a Writable, Lvalue, and Foward Traversal iterator.
    +However, there is a problem with this correspondance, the new iterator
    +categories place requirements on the ``iterator_traits::reference``
    +type whereas the standard iterator requirements say nothing about the
    +``reference`` type . In particular, the new Readable Iterator
    +requirements say that the return type of ``*a`` must be
    +``iterator_traits::reference`` and the Lvalue Iterator requirements
    +says that ``iterator_traits::reference`` must be ``T&`` or ``const
    +T&``.
    +
    +
    +====================
    + Proposed Resolution
    +====================
    +
    +Change the standard requirements to match the requirements of the new
    +iterators. (more details to come)
    +
    +
    +==========
    + Rationale
    +==========
    +
    +The lack of specification in the standard of the ``reference`` type is
    +certainly a defect. Without specification, it is entirely useless in a
    +generic function. The current practice in the community is generally
    +to assume there are requirements on the ``reference`` type, such as
    +those proposed in the new iterator categories.
    +
    +There is some danger in *adding* requirements to existing concepts.
    +This will mean that some existing iterator types will no longer meet
    +the iterator requirements. However, we feel that the impact of this is
    +small enough to warrant going ahead with this change.
    +
    +An alternative solution would be to leave the standard requirements as
    +is, and to remove the requirements for the ``reference`` type in the
    +new iterator concepts. We are not in favor of this approach because it
    +extends what we see as a defect further into the future.
    
    From f25ff7a1a40d5c952ba4984cf5eb687a87ccb18f Mon Sep 17 00:00:00 2001
    From: Dave Abrahams 
    Date: Mon, 17 Nov 2003 17:15:26 +0000
    Subject: [PATCH 248/265] Edits for clarity and correctness.
    
    [SVN r20831]
    ---
     doc/issues.html | 451 ++++++++++++++++++------------------------------
     doc/issues.rst  | 124 +++++++------
     2 files changed, 241 insertions(+), 334 deletions(-)
    
    diff --git a/doc/issues.html b/doc/issues.html
    index 713f1ba..5b89021 100755
    --- a/doc/issues.html
    +++ b/doc/issues.html
    @@ -4,7 +4,7 @@
     
     
     
    -Issues With N1550 and N1530
    +Problem with is_writable and is_swappable in N1550
     
     
     
    -
    -

    Issues With N1550 and N1530

    +
    +

    Problem with is_writable and is_swappable in N1550

    - + - + - + - @@ -224,301 +224,194 @@ at http://www.b

    Table of Contents

    Introduction

    -

    Several issues with N1550 (New Iterator Concepts) were raised in -the run-up before the fall 2003 C++ Committee meeting, in a thread -beginning with John Maddock's posting c++std-lib-12187. In -looking at those issues, several other problems came up. This -document addresses those issues and discusses some potential -solutions and their impact on N1530 (Iterator Facade and Adaptor).

    -
    -
    -

    The Issues

    -
    -

    Non-Uniformity of the "lvalue_iterator Bit"

    -

    The proposed iterator_tag class template accepts an "access -bits" parameter which includes a bit to indicate the iterator's -lvalueness (whether its dereference operator returns a reference -to its value_type. The relevant part of N1550 says:

    -
    -The purpose of the lvalue_iterator part of the -iterator_access enum is to communicate to iterator_tag -whether the reference type is an lvalue so that the appropriate -old category can be chosen for the base class. The -lvalue_iterator bit is not recorded in the -iterator_tag::access data member.
    -

    The lvalue_iterator bit is not recorded because N1550 aims to -improve orthogonality of the iterator concepts, and a new-style -iterator's lvalueness is detectable by examining its reference -type. This inside/outside difference is awkward and confusing.

    -
    -
    -

    Redundancy of Some Explicit Access Category Flags

    -

    Shortly after N1550 was accepted, we discovered that an iterator's -lvalueness can be determined knowing only its value_type. This -predicate can be calculated even for old-style iterators (on whose -reference type the standard places few requirements). A trait -in the Boost iterator library does it by relying on the compiler's -unwillingness to bind an rvalue to a T& function template -parameter. Similarly, it is possible to detect an iterator's -readability knowing only its value_type. Thus, any interface -which asks the user to explicitly describe an iterator's -lvalue-ness or readability seems to introduce needless complexity.

    -
    -
    -

    New Access Traits Templates Wrong For Some Iterators

    -
    -

    is_writable_iterator

    -

    The part of the is_writable_iterator trait definition which -applies to old-style iterators is:

    +

    The is_writable and is_swappable traits classes in N1550 +provide a mechanism for determining at compile time if an iterator +type is a model of the new Writable Iterator and Swappable Iterator +concepts, analogous to iterator_traits<X>::iterator_category +for the old iterator concepts. For backward compatibility, +is_writable and is_swappable not only work with new +iterators, but they also are intended to work for old +iterators (iterators that meet the requirements for one of the +iterator concepts in the current standard). In the case of old +iterators, the writability and swapability is deduced based on the +iterator_category and also the reference type. The +specification for this deduction gives false positives for forward +iterators that have non-assignable value types.

    +

    To review, the part of the is_writable trait definition which +applies to old iterators is:

     if (cat is convertible to output_iterator_tag)
    -         return true;
    -    else if (
    -         cat is convertible to forward_iterator_tag
    +    return true;
    +else if (cat is convertible to forward_iterator_tag
              and iterator_traits<Iterator>::reference is a 
                  mutable reference)
    -        return true;
    -    else
    -        return false;
    -
    -

    The current forward iterator requirements place no constraints on -the iterator's reference type, so the logic above will give -false negatives for some otherwise-writable forward iterators whose -reference type is not a mutable reference. Also, it will -report false positives for any forward, bidirectional, or random -access iterator whose reference is a mutable reference but -whose value_type is not assignable (e.g. has a private -assignment operator).

    -
    -
    -

    is_swappable_iterator

    -

    Similarly, the part of is_swappable_iterator which applies to -old-style iterators is:

    -
    -else if (cat is convertible to forward_iterator_tag) {
    -    if (iterator_traits<Iterator>::reference is a const reference)
    -        return false;
    -    else
    -        return true;
    -} else 
    +    return true;
    +else
         return false;
     
    -

    In this case false positives are possible for non-writable forward -iterators whose reference type is not a reference, or as above, -any forward, bidirectional, or random access iterator whose -reference is not a constant reference but whose value_type -is not assignable (e.g., because it has a private assignment -operator).

    -

    False negatives can be "reasoned away": since it is part of a -writable iterator's concept definition that -is_writable<I>::value is true, any iterator for which -it is false is by definition not writable. This seems like a -perverse use of logic, though.

    -

    It might be reasonable to conclude that it is a defect that the -standard allows forward iterators with a reference type other -than value_type cv&, but that still leaves the problem -of old-style iterators whose value_type is not assignable. It -is not possible to correctly compute writability and swappability -for those old-style iterators without intervention -(specializations of is_writable_iterator and -is_swappable_iterator) from a user.

    +

    Suppose the value_type of the iterator It has a private +assignment operator:

    +
    +class B {
    +public:
    +  ...
    +private:
    +  B& operator=(const B&);
    +};
    +
    +

    and suppose the reference type of the iterator is B&. In +that case, is_writable<It>::value will be true when in fact +attempting to write into B will cause an error.

    +

    The same problem applies to is_swappable.

    -
    -
    -

    No Use Cases for Some Access Traits

    -
    -

    is_swappable_iterator

    -

    is_swappable_iterator<I> is supposed to yield true if -iter_swap(x,y) is valid for instances x and y of type -I. The only argument we have heard for -is_swappable_iterator goes something like this:

    -
    -"If is_swappable_iterator yields false, you -could fall back to using copy construction and assignment on -the value_type instead."
    -

    This line of reasoning, however, falls down when closely examined. -To achieve the same effect using copy construction and assignment -on the iterator's value_type, the iterator must be readable and -writable, and its value_type must be copy-constructible. But -then, iter_swap must work in that case, because its default -implementation just calls swap on the dereferenced iterators. -The only purpose for the swappable iterator concept is to represent -iterators which do not fulfill the properties listed above, but -which are nonetheless swappable because the user has provided an -overload or specialization of iter_swap. In other words, -generic code which wants to swap the referents of two iterators -should always call iter_swap instead of doing the -assignments.

    -
    -
    -

    is_writable_iterator

    -

    Try to imagine a case where is_writable_iterator can be used to -choose behavior. Since the only requirement on a writable iterator -is that we can assign into its referent, the only use for -is_writable_iterator in selecting behavior is to modify a -sequence when the sequence is mutable, and to not modify it +

    +

    Proposed Resolution

    +
      +
    1. Remove the is_writable and is_swappable traits, and remove the +requirements in the Writable Iterator and Swappable Iterator concepts +that require their models to support these traits.

      +
    2. +
    3. Change the is_readable specification to be: +is_readable<X>::type is true_type if the +result type of X::operator* is convertible to +iterator_traits<X>::value_type and is false_type otherwise.

      -

      There is no precedent for generic functions which modify their -arguments only if the arguments are non-const reference, and with -good reason: the simple fact that data is mutable does not mean -that a user intends it to be mutated. We provide const and -non-const overloads for functions like operator[], but -these do not modify data; they merely return a reference to data -which preserves the object's mutability properties. We can do the -same with iterators using their reference types; the -accessibility of an assignment operator on the value_type, -which determines writability, does not change that.

      -

      The one plausible argument we can imagine for -is_writable_iterator and is_swappable_iterator is that they -can be used to remove algorithms from an overload set using a -SFINAE technique like enable_if, thus minimizing unintentional -matches due to Koenig Lookup. If it means requiring explicit -indications of writability and swappability from new-style iterator -implementors, however, it seems to be too small a gain to be worth -the cost. That's especially true since we can't get many existing -old-style iterators to meet the same requirements.

      -
    -
    -
    -

    Naming Issues

    -
    -

    Traversal Concepts and Tags

    -

    Howard Hinnant pointed out some inconsistencies with the naming of -these tag types:

    +

    Remove the requirement for support of the is_readable trait from +the Readable Iterator concept.

    + + + +
      +
    1. Change iterator_tag to:

      -incrementable_iterator_tag            // ++r, r++
      -single_pass_iterator_tag              // adds a == b, a != b
      -forward_traversal_iterator_tag        // adds multi-pass capability
      -bidirectional_traversal_iterator_tag  // adds --r, r--
      -random_access_traversal_iterator_tag  // adds r+n,n+r,r-n,r[n],etc.
      +template <class Value, class Reference, class Traversal>
      +struct iterator_tag;
       
      -

      Howard thought that it might be better if all tag names contained -the word "traversal".

      -

      It's not clear that would result in the best possible names, -though. For example, incrementable iterators can only make a -single pass over their input. What really distinguishes single -pass iterators from incrementable iterators is not that they can -make a single pass, but that they are equality comparable. Forward -traversal iterators really distinguish themselves by introducing -multi-pass capability. Without entering a "Parkinson's Bicycle -Shed" type of discussion, it might be worth giving the names of -these tags (and the associated concepts) some extra attention.

      -
    -
    -

    Access Traits

    -

    The names is_readable, is_writable, and is_swappable -are probably too general for their semantics. In particular, a -swappable iterator is only swappable in the same sense that a -mutable iterator is mutable: the trait refers to the iterator's -referent. It would probably be better to add the _iterator -suffix to each of these names.

    -
    -
    -
    -
    -

    Proposed Solution (in progress)

    -

    We believe that is_readable_iterator is a fine name for the -proposed is_readable trait and will use that from here on. In -order to avoid confusion, however, and because we aren't terribly -convinced of any answer yet, we are going to phrase this solution -in terms of the existing traversal concept and tag names. We'll -propose a few possible traversal naming schemes at the end of this -section.

    -
    -

    Overview

    -

    Following the dictum that what we can't do well probably shouldn't -be done at all, we'd like to solve many of the problems above by -eliminating details and simplifying the library as proposed. In -particular, we'd eliminate is_writable and is_swappable, -and remove the requirements which say that writable, and swappable -iterators must support these traits. is_readable_iterator has -proven to be useful and will be retained, but since it can be -implemented with no special hints from the iterator, it will not be -mentioned in the readable iterator requirements. Since we don't -want to require the user to explicitly specify access category -information, we'll change iterator_tag so that it computes the -old-style category in terms of the iterator's traversal category, -reference, and value_type.

    -
    -
    -

    Future Enhancements

    -

    For C++0x, we could consider a change to iterator_traits which -allows the user to avoid the use of iterator_tag (or similar -devices) altogether and write a new-style iterator by specifying -only a traversal tag. This change is not being proposed as it does -not constitute a "pure bolt-on":

    +

    The argument for Value must be the value_type of the +iterator, possibly const-qualified, Reference must be the +return type of operator* *, and Traversal the +traversal tag for the iterator.

    + + + + +
    Author:David Abrahams
    Author:David Abrahams and Jeremy Siek
    Contact:dave@boost-consulting.com
    Contact:dave@boost-consulting.com, jsiek@osl.iu.edu
    Organization:Boost Consulting
    Organization:Boost Consulting, Indiana University Bloomington
    date:$Date$
    Copyright:Copyright David Abrahams 2003. Use, modification and +
    Copyright:Copyright David Abrahams, Jeremy Siek 2003. Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
    + + + + +
    [*]Instead of saying "return type of operator*", we could have +said iterator_traits<X>::reference. However, the standard +specifies nothing about iterator_traits<X>::reference in +many cases, which we believe is a defect. Furthermore, in some +cases it explicitly differs from the return type of +operator*, for example see istreambuf_iterator.
    +
      +
    1. Change the specification of traversal_category to:

      -iterator_traits<I>::iterator_category
      -  = if (I::iterator_category is a type) // use mpl::has_xxx (SFINAE)
      -       return I::iterator_category
      -
      -    // Only old-style output iterators may have a void value_type 
      -    // or difference_type
      -    if (iterator_value_type<I>::type is void
      -        || iterator_difference_type<I>::type is void
      -    )
      -       return std::output_iterator_tag
      -
      -    t = iterator_traversal<I>::type
      -    
      -    if (I is an lvalue iterator)
      -    {
      -       if (t is convertible to random_access_traversal_tag)
      -          return std::random_access_iterator_tag
      -       if (t is convertible to bidirectional_traversal_tag)
      -          return std::bidirectional_iterator_tag
      -       else if (t is convertible to forward_traversal_tag)
      -          return std::forward_iterator_tag
      -    }
      -
      -    if (t is convertible to single_pass_traversal_tag
      -        && I is a readable iterator
      -    )
      -       return input_output_iterator_tag // (**)
      +traversal-category(Iterator) =
      +    let cat = iterator_traits<Iterator>::iterator_category
      +    if (cat is convertible to incrementable_iterator_tag)
      +      return cat; // Iterator is a new iterator
      +    else if (cat is convertible to random_access_iterator_tag)
      +        return random_access_traversal_tag;
      +    else if (cat is convertible to bidirectional_iterator_tag)
      +        return bidirectional_traversal_tag;
      +    else if (cat is convertible to forward_iterator_tag)
      +        return forward_traversal_tag;
      +    else if (cat is convertible to input_iterator_tag)
      +        return single_pass_iterator_tag;
      +    else if (cat is convertible to output_iterator_tag)
      +        return incrementable_iterator_tag;
           else
      -       return std::output_iterator_tag
      +        return null_category_tag;
       
      +
    2. +
    -
    -

    Impact on N1530 (Iterator Facade and Adaptor)

    -

    XXX

    -
    +
    +

    Rationale

    +
      +
    1. There are two reasons for removing is_writable +and is_swappable. The first is that we do not know of +a way to fix the specification so that it gives the correct +answer for all iterators. Second, there was only a weak +motivation for having is_writable and is_swappable +there in the first place. The main motivation was simply +uniformity: we have tags for the old iterator categories +so we should have tags for the new iterator categories. +While having tags and the capability to dispatch based +on the traversal categories is often used, we see +less of a need for dispatching based on writability +and swappability, since typically algorithms +that need these capabilities have no alternative if +they are not provided.
    2. +
    3. We discovered that the is_readable trait can be implemented +using only the iterator type itself and its value_type. +Therefore we remove the requirement for is_readable from the +Readable Iterator concept, and change the definition of +is_readable so that it works for any iterator type.
    4. +
    5. With is_writable and is_swappable gone, and +is_readable no longer in need of special hints, +there is no reason for the iterator_tag class to provide +information about the access capabilities of an iterator. +This new version provides only information about the traversal +capabilities and the old iterator category tag. Instead of accessing +the traversal category as a nested typedef ::traversal, +the iterator_tag itself will be convertible to the traversal +tag. The access_bits parameter is no longer needed for +specifying the access member (which is now gone). However, +some access information is still needed so that we can +deduce the appropriate old iterator category. The +Value and Reference parameters fill this need. +Note that this solution cleans up the issue that John +Maddock raised on the reflector (c++std-lib-12187) about the non-uniformity +of the lvalue bit.
    6. +
    7. The changes to the specification of traversal_category are a +direct result of the changes to iterator_tag.
    8. +
    diff --git a/doc/issues.rst b/doc/issues.rst index 0d5e155..007fd24 100755 --- a/doc/issues.rst +++ b/doc/issues.rst @@ -23,17 +23,18 @@ ============== The ``is_writable`` and ``is_swappable`` traits classes in N1550_ -provide a mechanism for determining at compile time if a type is a -model of the new Writable Iterator and Swappable Iterator concepts, -analogous to ``iterator_traits::iterator_category`` for the old -iterator concepts. For backward compatibility, ``is_writable`` and -``is_swappable`` not only work with new iterators, but they also are -intended to work for old iterators (iterators that meet the -requirements for one of the iterator concepts in the current -standard). In the case of old iterators, the writability and -swapability is deduced based on the ``iterator_category`` and also the -``reference`` type. The specification for this deduction gives false -positives for forward iterators that have non-assignable value types. +provide a mechanism for determining at compile time if an iterator +type is a model of the new Writable Iterator and Swappable Iterator +concepts, analogous to ``iterator_traits::iterator_category`` +for the old iterator concepts. For backward compatibility, +``is_writable`` and ``is_swappable`` not only work with new +iterators, but they also are intended to work for old +iterators (iterators that meet the requirements for one of the +iterator concepts in the current standard). In the case of old +iterators, the writability and swapability is deduced based on the +``iterator_category`` and also the ``reference`` type. The +specification for this deduction gives false positives for forward +iterators that have non-assignable value types. To review, the part of the ``is_writable`` trait definition which applies to old iterators is:: @@ -47,8 +48,8 @@ applies to old iterators is:: else return false; -Suppose the ``value_type`` of the iterator has a private assignment -operator:: +Suppose the ``value_type`` of the iterator ``It`` has a private +assignment operator:: class B { public: @@ -57,9 +58,9 @@ operator:: B& operator=(const B&); }; -and suppose the ``reference`` type of the iterator is ``B&``. Then -``is_writable`` will deduce true when in fact attempting to write into -``B`` will cause an error. +and suppose the ``reference`` type of the iterator is ``B&``. In +that case, ``is_writable::value`` will be true when in fact +attempting to write into ``B`` will cause an error. The same problem applies to ``is_swappable``. @@ -81,64 +82,78 @@ The same problem applies to ``is_swappable``. Remove the requirement for support of the ``is_readable`` trait from the Readable Iterator concept. +.. We should give some attention to the UnaryTypeTrait concept, + which requires the trait to be derived from either true_type or + false_type (as of the last LWG meeting). + 3. Change ``iterator_tag`` to:: template struct iterator_tag; - The argument for ``Value`` must be the value type of the - iterator, ``Reference`` must be the return type of - ``operator*`` [*]_, and ``Traversal`` the traversal tag for the - iterator. + The argument for ``Value`` must be the ``value_type`` of the + iterator, possibly const-qualified, ``Reference`` must be the + return type of ``operator*`` [*]_, and ``Traversal`` the + traversal tag for the iterator. - ``iterator_tag`` is required to be convertible to both the - ``Traversal`` tag and also to the appropriate old iterator category - tag, as specified by the following pseudo-code:: +.. I think the language above is still too informal. There is no + "the iterator", when considering iterator_tag in isolation. + Perhaps that language belongs in a non-normative note - inherit-category(Value, Reference, Traversal) = + ``iterator_tag`` is required to be + convertible to both ``Traversal`` tag and also to the + ``iterator_category`` type specified by the following + pseudo-code:: + + old-category(Value, Reference, Traversal) = if (Reference is a reference - and Traversal is convertible to forward_traversal_tag) { + and Traversal is convertible to forward_traversal_tag) + { if (Traversal is convertible to random_access_traversal_tag) return random_access_iterator_tag; else if (Traversal is convertible to bidirectional_traversal_tag) return bidirectional_iterator_tag; else return forward_iterator_tag; - } else if (Traversal is convertible to single_pass_traversal_tag - and Reference is convertible to Value) { + } + else if (Traversal is convertible to single_pass_traversal_tag + and Reference is convertible to Value) + { if (Value is const) return input_iterator_tag; else return input_output_iterator_tag; } else return output_iterator_tag; - - + +.. I reformatted the code for legibility; sorry. + .. [*] Instead of saying "return type of operator*", we could have said ``iterator_traits::reference``. However, the standard - specifies nothing about ``iterator_traits::reference``, - which we believe is a defect. Once the defect is fixed, - the above could be rephrased. + specifies nothing about ``iterator_traits::reference`` in + many cases, which we believe is a defect. Furthermore, in some + cases it explicitly differs from the return type of + ``operator*``, for example see ``istreambuf_iterator``. 4. Change the specification of ``traversal_category`` to:: traversal-category(Iterator) = - let cat = iterator_traits::iterator_category - if (cat convertible to incrementable_iterator_tag) - return cat; // Iterator is a new iterator - else if (cat is convertible to random_access_iterator_tag) - return random_access_traversal_tag; - else if (cat is convertible to bidirectional_iterator_tag) - return bidirectional_traversal_tag; - else if (cat is convertible to forward_iterator_tag) - return forward_traversal_tag; - else if (cat is convertible to input_iterator_tag) - return single_pass_iterator_tag; - else if (cat is convertible to output_iterator_tag) - return incrementable_iterator_tag; - else - return null_category_tag; + let cat = iterator_traits::iterator_category + if (cat is convertible to incrementable_iterator_tag) + return cat; // Iterator is a new iterator + else if (cat is convertible to random_access_iterator_tag) + return random_access_traversal_tag; + else if (cat is convertible to bidirectional_iterator_tag) + return bidirectional_traversal_tag; + else if (cat is convertible to forward_iterator_tag) + return forward_traversal_tag; + else if (cat is convertible to input_iterator_tag) + return single_pass_iterator_tag; + else if (cat is convertible to output_iterator_tag) + return incrementable_iterator_tag; + else + return null_category_tag; ========== @@ -150,7 +165,7 @@ The same problem applies to ``is_swappable``. a way to fix the specification so that it gives the correct answer for all iterators. Second, there was only a weak motivation for having ``is_writable`` and ``is_swappable`` - there in the first place. The main motivation was simply + there in the first place. The main motivation was simply uniformity: we have tags for the old iterator categories so we should have tags for the new iterator categories. While having tags and the capability to dispatch based @@ -160,12 +175,11 @@ The same problem applies to ``is_swappable``. that need these capabilities have no alternative if they are not provided. -2. We discovered that the ``is_readable`` trait can be - implemented without special hints from the iterator. - Therefore we remove the requirement for ``is_readable`` - from the Readable Iterator concept, and change - the definition of ``is_readable`` so that it works - for any iterator type. +2. We discovered that the ``is_readable`` trait can be implemented + using only the iterator type itself and its ``value_type``. + Therefore we remove the requirement for ``is_readable`` from the + Readable Iterator concept, and change the definition of + ``is_readable`` so that it works for any iterator type. 3. With ``is_writable`` and ``is_swappable`` gone, and ``is_readable`` no longer in need of special hints, @@ -181,7 +195,7 @@ The same problem applies to ``is_swappable``. deduce the appropriate old iterator category. The ``Value`` and ``Reference`` parameters fill this need. Note that this solution cleans up the issue that John - Maddock raised on the reflector about the non-uniformity + Maddock raised on the reflector (``c++std-lib-12187``) about the non-uniformity of the lvalue bit. 4. The changes to the specification of ``traversal_category`` are a From 50e645261c393efcabcf265ca41c70ca7c8ec153 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 17 Nov 2003 20:21:40 +0000 Subject: [PATCH 249/265] responses to Dave's comments [SVN r20835] --- doc/issues.rst | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/doc/issues.rst b/doc/issues.rst index 007fd24..8c443b6 100755 --- a/doc/issues.rst +++ b/doc/issues.rst @@ -86,20 +86,32 @@ The same problem applies to ``is_swappable``. which requires the trait to be derived from either true_type or false_type (as of the last LWG meeting). +.. I must not have been there for that. Could you handle + giving it attention? -JGS + + 3. Change ``iterator_tag`` to:: template struct iterator_tag; - The argument for ``Value`` must be the ``value_type`` of the - iterator, possibly const-qualified, ``Reference`` must be the - return type of ``operator*`` [*]_, and ``Traversal`` the - traversal tag for the iterator. + If ``iterator_tag`` is to be used as the ``iterator_category`` + for iterator type ``X``, then the argument for ``Value`` must be + the ``value_type`` for iterator ``X``, possibly const-qualified + to indicate a non-writable iterator. The argument for + ``Reference`` must be the + return type of ``operator*`` [*]_, and the argument for ``Traversal`` + must be the traversal tag for the iterator. .. I think the language above is still too informal. There is no "the iterator", when considering iterator_tag in isolation. Perhaps that language belongs in a non-normative note +.. I'm not so sure it makes sense to talk of iterator_tag in + isolation. I've added some more words to spell out the + connection between "the iterator" and the iterator_tag. -JGS + + ``iterator_tag`` is required to be convertible to both ``Traversal`` tag and also to the ``iterator_category`` type specified by the following @@ -127,6 +139,7 @@ The same problem applies to ``is_swappable``. return output_iterator_tag; .. I reformatted the code for legibility; sorry. +.. No problemo. -JGS .. [*] Instead of saying "return type of operator*", we could have said ``iterator_traits::reference``. However, the standard @@ -135,6 +148,13 @@ The same problem applies to ``is_swappable``. cases it explicitly differs from the return type of ``operator*``, for example see ``istreambuf_iterator``. +.. Hmm, istreambuf_iterator does not fit nicely into the new iterator + categories. It's reference type is charT& but the return type + of operator* is charT. In the new concepts, these are required to be + the same type. We'll have to deal with this in the + reference problem paper. -JGS + + 4. Change the specification of ``traversal_category`` to:: @@ -195,8 +215,8 @@ The same problem applies to ``is_swappable``. deduce the appropriate old iterator category. The ``Value`` and ``Reference`` parameters fill this need. Note that this solution cleans up the issue that John - Maddock raised on the reflector (``c++std-lib-12187``) about the non-uniformity - of the lvalue bit. + Maddock raised on the reflector (``c++std-lib-12187``) about the + non-uniformity of the lvalue bit. 4. The changes to the specification of ``traversal_category`` are a direct result of the changes to ``iterator_tag``. From 76880f6ce22cc5c90f66324bbbf9c1bd265ab619 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 18 Nov 2003 02:58:15 +0000 Subject: [PATCH 250/265] initial commit [SVN r20837] --- .../iterator/detail/any_conversion_eater.hpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100755 include/boost/iterator/detail/any_conversion_eater.hpp diff --git a/include/boost/iterator/detail/any_conversion_eater.hpp b/include/boost/iterator/detail/any_conversion_eater.hpp new file mode 100755 index 0000000..7d283df --- /dev/null +++ b/include/boost/iterator/detail/any_conversion_eater.hpp @@ -0,0 +1,19 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef ANY_CONVERSION_EATER_DWA20031117_HPP +# define ANY_CONVERSION_EATER_DWA20031117_HPP + +namespace boost { namespace iterator.old { namespace detail { + +// This type can be used in traits to "eat" up the one user-defined +// implicit conversion allowed. +struct any_conversion_eater +{ + template + any_conversion_eater(T const&); +}; + +}}} // namespace boost::iterator.old::detail + +#endif // ANY_CONVERSION_EATER_DWA20031117_HPP From 8d5717081eeaf768e1f671c278a9f10243f7046a Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 18 Nov 2003 03:00:39 +0000 Subject: [PATCH 251/265] Factor out any_conversion_eater [SVN r20838] --- include/boost/iterator/is_lvalue_iterator.hpp | 10 +++------- include/boost/iterator/is_readable_iterator.hpp | 10 +++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/include/boost/iterator/is_lvalue_iterator.hpp b/include/boost/iterator/is_lvalue_iterator.hpp index 9a31322..d77b977 100755 --- a/include/boost/iterator/is_lvalue_iterator.hpp +++ b/include/boost/iterator/is_lvalue_iterator.hpp @@ -8,8 +8,10 @@ #include #include -// should be the last #include #include +#include + +// should be the last #include #include namespace boost { @@ -36,12 +38,6 @@ namespace detail #endif - struct any_conversion_eater - { - template - any_conversion_eater(T const&); - }; - // Guts of is_lvalue_iterator. Value is the iterator's value_type // and the result is computed in the nested rebind template. template diff --git a/include/boost/iterator/is_readable_iterator.hpp b/include/boost/iterator/is_readable_iterator.hpp index 40ab89f..52df758 100755 --- a/include/boost/iterator/is_readable_iterator.hpp +++ b/include/boost/iterator/is_readable_iterator.hpp @@ -7,20 +7,16 @@ #include #include -// should be the last #include #include +#include + +// should be the last #include #include namespace boost { namespace detail { - struct any_conversion_eater - { - template - any_conversion_eater(T const&); - }; - // Guts of is_readable_iterator. Value is the iterator's value_type // and the result is computed in the nested rebind template. template From a8a68dbb7bb3985872d57cb1312a14358ec0d090 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 18 Nov 2003 03:02:40 +0000 Subject: [PATCH 252/265] fix emacs-o [SVN r20839] --- include/boost/iterator/detail/any_conversion_eater.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/iterator/detail/any_conversion_eater.hpp b/include/boost/iterator/detail/any_conversion_eater.hpp index 7d283df..50cc73c 100755 --- a/include/boost/iterator/detail/any_conversion_eater.hpp +++ b/include/boost/iterator/detail/any_conversion_eater.hpp @@ -4,7 +4,7 @@ #ifndef ANY_CONVERSION_EATER_DWA20031117_HPP # define ANY_CONVERSION_EATER_DWA20031117_HPP -namespace boost { namespace iterator.old { namespace detail { +namespace boost { namespace iterator { namespace detail { // This type can be used in traits to "eat" up the one user-defined // implicit conversion allowed. @@ -14,6 +14,6 @@ struct any_conversion_eater any_conversion_eater(T const&); }; -}}} // namespace boost::iterator.old::detail +}}} // namespace boost::iterator::detail #endif // ANY_CONVERSION_EATER_DWA20031117_HPP From e295f71a855feda005bf21eab2944453639dd7eb Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 18 Nov 2003 03:04:15 +0000 Subject: [PATCH 253/265] fix emacs-o #2 [SVN r20840] --- include/boost/iterator/detail/any_conversion_eater.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/iterator/detail/any_conversion_eater.hpp b/include/boost/iterator/detail/any_conversion_eater.hpp index 50cc73c..25fa644 100755 --- a/include/boost/iterator/detail/any_conversion_eater.hpp +++ b/include/boost/iterator/detail/any_conversion_eater.hpp @@ -4,7 +4,7 @@ #ifndef ANY_CONVERSION_EATER_DWA20031117_HPP # define ANY_CONVERSION_EATER_DWA20031117_HPP -namespace boost { namespace iterator { namespace detail { +namespace boost { namespace detail { // This type can be used in traits to "eat" up the one user-defined // implicit conversion allowed. @@ -14,6 +14,6 @@ struct any_conversion_eater any_conversion_eater(T const&); }; -}}} // namespace boost::iterator::detail +}} // namespace boost::detail #endif // ANY_CONVERSION_EATER_DWA20031117_HPP From 4ec68b7a0e489cf0f2eaed7cfb54380eccd2c124 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 18 Nov 2003 16:03:24 +0000 Subject: [PATCH 254/265] Note missing link [SVN r20845] --- doc/iterator_adaptor_ref.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/iterator_adaptor_ref.rst b/doc/iterator_adaptor_ref.rst index 7226341..a51e2e9 100644 --- a/doc/iterator_adaptor_ref.rst +++ b/doc/iterator_adaptor_ref.rst @@ -43,7 +43,7 @@ Base m_iterator; }; -__ : +__ : THE LINK HERE IS MISSING! ``iterator_adaptor`` requirements --------------------------------- From 943d2c872b21b0a47ba0ad5cd933ab9a7d157bbc Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Wed, 19 Nov 2003 01:05:00 +0000 Subject: [PATCH 255/265] removing iterator_tag [SVN r20850] --- doc/issues.rst | 77 ++++---------------------------------------------- 1 file changed, 5 insertions(+), 72 deletions(-) diff --git a/doc/issues.rst b/doc/issues.rst index 8c443b6..ed02354 100755 --- a/doc/issues.rst +++ b/doc/issues.rst @@ -77,82 +77,15 @@ The same problem applies to ``is_swappable``. ``is_readable::type`` is ``true_type`` if the result type of ``X::operator*`` is convertible to ``iterator_traits::value_type`` and is ``false_type`` - otherwise. - + otherwise. Also, ``is_readable`` is required to satisfy + the requirements for the UnaryTypeTrait concept + (defined in the type traits proposal). + Remove the requirement for support of the ``is_readable`` trait from the Readable Iterator concept. -.. We should give some attention to the UnaryTypeTrait concept, - which requires the trait to be derived from either true_type or - false_type (as of the last LWG meeting). -.. I must not have been there for that. Could you handle - giving it attention? -JGS - - -3. Change ``iterator_tag`` to:: - - template - struct iterator_tag; - - If ``iterator_tag`` is to be used as the ``iterator_category`` - for iterator type ``X``, then the argument for ``Value`` must be - the ``value_type`` for iterator ``X``, possibly const-qualified - to indicate a non-writable iterator. The argument for - ``Reference`` must be the - return type of ``operator*`` [*]_, and the argument for ``Traversal`` - must be the traversal tag for the iterator. - -.. I think the language above is still too informal. There is no - "the iterator", when considering iterator_tag in isolation. - Perhaps that language belongs in a non-normative note - -.. I'm not so sure it makes sense to talk of iterator_tag in - isolation. I've added some more words to spell out the - connection between "the iterator" and the iterator_tag. -JGS - - - ``iterator_tag`` is required to be - convertible to both ``Traversal`` tag and also to the - ``iterator_category`` type specified by the following - pseudo-code:: - - old-category(Value, Reference, Traversal) = - if (Reference is a reference - and Traversal is convertible to forward_traversal_tag) - { - if (Traversal is convertible to random_access_traversal_tag) - return random_access_iterator_tag; - else if (Traversal is convertible to bidirectional_traversal_tag) - return bidirectional_iterator_tag; - else - return forward_iterator_tag; - } - else if (Traversal is convertible to single_pass_traversal_tag - and Reference is convertible to Value) - { - if (Value is const) - return input_iterator_tag; - else - return input_output_iterator_tag; - } else - return output_iterator_tag; - -.. I reformatted the code for legibility; sorry. -.. No problemo. -JGS - -.. [*] Instead of saying "return type of operator*", we could have - said ``iterator_traits::reference``. However, the standard - specifies nothing about ``iterator_traits::reference`` in - many cases, which we believe is a defect. Furthermore, in some - cases it explicitly differs from the return type of - ``operator*``, for example see ``istreambuf_iterator``. - -.. Hmm, istreambuf_iterator does not fit nicely into the new iterator - categories. It's reference type is charT& but the return type - of operator* is charT. In the new concepts, these are required to be - the same type. We'll have to deal with this in the - reference problem paper. -JGS +3. Remove ``iterator_tag``. From b0b5699a01c316dd689d32a182fd32b71b067742 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Wed, 19 Nov 2003 01:23:55 +0000 Subject: [PATCH 256/265] added more stuff about removing iterator_tag [SVN r20851] --- doc/issues.rst | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/doc/issues.rst b/doc/issues.rst index ed02354..5ddb61f 100755 --- a/doc/issues.rst +++ b/doc/issues.rst @@ -85,9 +85,7 @@ The same problem applies to ``is_swappable``. the Readable Iterator concept. -3. Remove ``iterator_tag``. - - +3. Remove the ``iterator_tag`` class. 4. Change the specification of ``traversal_category`` to:: @@ -134,23 +132,21 @@ The same problem applies to ``is_swappable``. Readable Iterator concept, and change the definition of ``is_readable`` so that it works for any iterator type. -3. With ``is_writable`` and ``is_swappable`` gone, and +3. The purpose of the ``iterator_tag`` class was to + bundle the traversal and access category tags + into the ``iterator_category`` typedef. + With ``is_writable`` and ``is_swappable`` gone, and ``is_readable`` no longer in need of special hints, - there is no reason for the ``iterator_tag`` class to provide + there is no reason for iterators to provide information about the access capabilities of an iterator. - This new version provides only information about the traversal - capabilities and the old iterator category tag. Instead of accessing - the traversal category as a nested typedef ``::traversal``, - the ``iterator_tag`` itself will be convertible to the traversal - tag. The ``access_bits`` parameter is no longer needed for - specifying the access member (which is now gone). However, - some access information is still needed so that we can - deduce the appropriate old iterator category. The - ``Value`` and ``Reference`` parameters fill this need. - Note that this solution cleans up the issue that John - Maddock raised on the reflector (``c++std-lib-12187``) about the - non-uniformity of the lvalue bit. + Thus there is no need for the ``iterator_tag``. The + traversal tag can be directly used for the + ``iterator_category``. If a new iterator is intended to be backward + compatible with old iterator concepts, a tag type + that is convertible to both one of the new traversal tags + and also to an old iterator tag can be created and use + for the ``iterator_category``. 4. The changes to the specification of ``traversal_category`` are a - direct result of the changes to ``iterator_tag``. + direct result of the removal of ``iterator_tag``. From 633bb0762e74de1a5e1f87505d55c0cf70091ce4 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Wed, 19 Nov 2003 01:24:28 +0000 Subject: [PATCH 257/265] new version [SVN r20852] --- doc/issues.html | 303 ++++-------------------------------------------- 1 file changed, 25 insertions(+), 278 deletions(-) diff --git a/doc/issues.html b/doc/issues.html index 5b89021..8087b45 100755 --- a/doc/issues.html +++ b/doc/issues.html @@ -3,200 +3,9 @@ - + Problem with is_writable and is_swappable in N1550 - +
    @@ -223,13 +32,13 @@ at http://www.b
    -

    Introduction

    +

    Introduction

    The is_writable and is_swappable traits classes in N1550 provide a mechanism for determining at compile time if an iterator type is a model of the new Writable Iterator and Swappable Iterator @@ -271,7 +80,7 @@ attempting to write into B wil

    The same problem applies to is_swappable.

    -

    Proposed Resolution

    +

    Proposed Resolution

    1. Remove the is_writable and is_swappable traits, and remove the requirements in the Writable Iterator and Swappable Iterator concepts @@ -281,68 +90,14 @@ that require their models to support these traits.

      is_readable<X>::type is true_type if the result type of X::operator* is convertible to iterator_traits<X>::value_type and is false_type -otherwise.

      +otherwise. Also, is_readable is required to satisfy +the requirements for the UnaryTypeTrait concept +(defined in the type traits proposal).

      Remove the requirement for support of the is_readable trait from the Readable Iterator concept.

    2. -
    - -
      -
    1. Change iterator_tag to:

      -
      -template <class Value, class Reference, class Traversal>
      -struct iterator_tag;
      -
      -

      The argument for Value must be the value_type of the -iterator, possibly const-qualified, Reference must be the -return type of operator* *, and Traversal the -traversal tag for the iterator.

      +
    2. Remove the iterator_tag class.

    3. -
    - - - - - - - -
    [*]Instead of saying "return type of operator*", we could have -said iterator_traits<X>::reference. However, the standard -specifies nothing about iterator_traits<X>::reference in -many cases, which we believe is a defect. Furthermore, in some -cases it explicitly differs from the return type of -operator*, for example see istreambuf_iterator.
    -
    1. Change the specification of traversal_category to:

       traversal-category(Iterator) =
      @@ -366,7 +121,7 @@ traversal-category(Iterator) =
       
    -

    Rationale

    +

    Rationale

    1. There are two reasons for removing is_writable and is_swappable. The first is that we do not know of @@ -387,32 +142,24 @@ using only the iterator type itself and its is_readable from the Readable Iterator concept, and change the definition of is_readable so that it works for any iterator type.
    2. -
    3. With is_writable and is_swappable gone, and +
    4. The purpose of the iterator_tag class was to +bundle the traversal and access category tags +into the iterator_category typedef. +With is_writable and is_swappable gone, and is_readable no longer in need of special hints, -there is no reason for the iterator_tag class to provide +there is no reason for iterators to provide information about the access capabilities of an iterator. -This new version provides only information about the traversal -capabilities and the old iterator category tag. Instead of accessing -the traversal category as a nested typedef ::traversal, -the iterator_tag itself will be convertible to the traversal -tag. The access_bits parameter is no longer needed for -specifying the access member (which is now gone). However, -some access information is still needed so that we can -deduce the appropriate old iterator category. The -Value and Reference parameters fill this need. -Note that this solution cleans up the issue that John -Maddock raised on the reflector (c++std-lib-12187) about the non-uniformity -of the lvalue bit.
    5. +Thus there is no need for the iterator_tag. The +traversal tag can be directly used for the +iterator_category. If a new iterator is intended to be backward +compatible with old iterator concepts, a tag type +that is convertible to both one of the new traversal tags +and also to an old iterator tag can be created and use +for the iterator_category.
    6. The changes to the specification of traversal_category are a -direct result of the changes to iterator_tag.
    7. +direct result of the removal of iterator_tag.
    - - From bdc13043269ebc5b42a2d981382c980c974750e1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 19 Nov 2003 20:08:00 +0000 Subject: [PATCH 258/265] Got everything working with GCC [SVN r20864] --- include/boost/pending/iterator_tests.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp index 66e21aa..4be1044 100644 --- a/include/boost/pending/iterator_tests.hpp +++ b/include/boost/pending/iterator_tests.hpp @@ -201,6 +201,8 @@ void bidirectional_iterator_test(Iterator i, T v1, T v2) // mutable_bidirectional_iterator_test +template struct undefined; + // Preconditions: [i,i+N) is a valid range template void random_access_iterator_test(Iterator i, int N, TrueVals vals) From 522195fd64cff2701b49cc73443618cc94480a2c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 20 Nov 2003 21:36:54 +0000 Subject: [PATCH 259/265] Stop making the incorrect assumption that x == j[n] is legitimate whenever x = j[n] and x == x are. j[n] may be a proxy convertible to typeof(x) and x == x may use a templated operator==, which wouldn't match the proxy. [SVN r20887] --- include/boost/pending/iterator_tests.hpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp index 4be1044..5be7b0f 100644 --- a/include/boost/pending/iterator_tests.hpp +++ b/include/boost/pending/iterator_tests.hpp @@ -25,6 +25,8 @@ # include # include # include // for detail::dummy_constructor +# include +# include namespace boost { @@ -38,6 +40,11 @@ struct dummyT { int m_x; }; +} + +BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT) + +namespace boost { // Tests whether type Iterator satisfies the requirements for a // TrivialIterator. @@ -211,10 +218,12 @@ void random_access_iterator_test(Iterator i, int N, TrueVals vals) const Iterator j = i; int c; + typedef typename boost::detail::iterator_traits::value_type value_type; + for (c = 0; c < N-1; ++c) { assert(i == j + c); assert(*i == vals[c]); - assert(*i == j[c]); + assert(*i == boost::implicit_cast(j[c])); assert(*i == *(j + c)); assert(*i == *(c + j)); ++i; @@ -228,7 +237,7 @@ void random_access_iterator_test(Iterator i, int N, TrueVals vals) for (c = 0; c < N-1; ++c) { assert(i == k - c); assert(*i == vals[N - 1 - c]); - assert(*i == j[N - 1 - c]); + assert(*i == boost::implicit_cast(j[N - 1 - c])); Iterator q = k - c; assert(*i == *q); assert(i > j); From f18906ac6bb12afdce8229851476957d5ea116e4 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 22 Nov 2003 01:18:37 +0000 Subject: [PATCH 260/265] Removed access category tags from iterator library, made corresponding changes elsewhere. boost/iterator and libs/iterator/test were updated from branch "simplify" [SVN r20905] --- include/boost/iterator/counting_iterator.hpp | 55 +- include/boost/iterator/detail/categories.hpp | 361 +--------- include/boost/iterator/detail/config_def.hpp | 61 +- .../boost/iterator/detail/config_undef.hpp | 1 + .../detail/facade_iterator_category.hpp | 214 ++++++ .../iterator/detail/minimum_category.hpp | 98 +++ include/boost/iterator/filter_iterator.hpp | 46 +- include/boost/iterator/is_lvalue_iterator.hpp | 18 +- .../boost/iterator/is_readable_iterator.hpp | 4 + include/boost/iterator/iterator_adaptor.hpp | 135 ++-- .../boost/iterator/iterator_archetypes.hpp | 656 ++++++++++-------- .../boost/iterator/iterator_categories.hpp | 524 ++++---------- include/boost/iterator/iterator_concepts.hpp | 113 +-- include/boost/iterator/iterator_facade.hpp | 190 ++--- include/boost/iterator/new_iterator_tests.hpp | 56 +- include/boost/iterator/transform_iterator.hpp | 85 ++- include/boost/iterator/zip_iterator.hpp | 78 +-- test/Jamfile | 4 +- test/concept_tests.cpp | 111 +-- test/counting_iterator_test.cpp | 2 +- test/filter_iterator_test.cpp | 15 +- test/indirect_iterator_test.cpp | 3 +- test/is_lvalue_iterator.cpp | 90 ++- test/iterator_adaptor_test.cpp | 77 +- test/iterator_archetype_cc.cpp | 13 +- test/iterator_categories.cpp | 91 --- test/reverse_iterator_test.cpp | 2 - test/static_assert_same.hpp | 8 +- test/transform_iterator_test.cpp | 52 +- test/unit_tests.cpp | 60 +- test/zip_iterator_test.cpp | 116 +--- 31 files changed, 1501 insertions(+), 1838 deletions(-) create mode 100755 include/boost/iterator/detail/facade_iterator_category.hpp create mode 100755 include/boost/iterator/detail/minimum_category.hpp delete mode 100755 test/iterator_categories.cpp diff --git a/include/boost/iterator/counting_iterator.hpp b/include/boost/iterator/counting_iterator.hpp index d168e2d..d44be21 100644 --- a/include/boost/iterator/counting_iterator.hpp +++ b/include/boost/iterator/counting_iterator.hpp @@ -15,7 +15,12 @@ namespace boost { -template class counting_iterator; +template < + class Incrementable + , class CategoryOrTraversal + , class Difference +> +class counting_iterator; namespace detail { @@ -67,35 +72,38 @@ namespace detail }; BOOST_STATIC_ASSERT(is_numeric::value); - template + + template struct counting_iterator_base { - typedef typename mpl::apply_if< - is_same + typedef typename detail::ia_dflt_help< + CategoryOrTraversal , mpl::apply_if< is_numeric - , mpl::identity - , BOOST_ITERATOR_CATEGORY + , mpl::identity + , iterator_traversal > - , mpl::identity - >::type category; + >::type traversal; - typedef typename mpl::apply_if< - is_same + typedef typename detail::ia_dflt_help< + Difference , mpl::apply_if< is_numeric , numeric_difference , iterator_difference > - , mpl::identity >::type difference; typedef iterator_adaptor< - counting_iterator // self - , Incrementable // Base - , Incrementable // value_type - , category - , Incrementable const& // reference + counting_iterator // self + , Incrementable // Base + , Incrementable // Value +# ifndef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY + const // MSVC won't strip this. Instead we enable Thomas' + // criterion (see boost/iterator/detail/facade_iterator_category.hpp) +# endif + , traversal + , Incrementable const& // reference , difference > type; }; @@ -128,11 +136,20 @@ namespace detail }; } -template +template < + class Incrementable + , class CategoryOrTraversal = use_default + , class Difference = use_default +> class counting_iterator - : public detail::counting_iterator_base::type + : public detail::counting_iterator_base< + Incrementable, CategoryOrTraversal, Difference + >::type { - typedef typename detail::counting_iterator_base::type super_t; + typedef typename detail::counting_iterator_base< + Incrementable, CategoryOrTraversal, Difference + >::type super_t; + friend class iterator_core_access; public: diff --git a/include/boost/iterator/detail/categories.hpp b/include/boost/iterator/detail/categories.hpp index 5a2e7eb..841ac4c 100644 --- a/include/boost/iterator/detail/categories.hpp +++ b/include/boost/iterator/detail/categories.hpp @@ -1,360 +1 @@ -// (C) Copyright Thomas Witt 2002. 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_DETAIL_CATEGORIES_HPP -# define BOOST_ITERATOR_DETAIL_CATEGORIES_HPP - -# include -# include - -# include - -# include -# include - -# include -# include -# include -# include -# include -# include -# include - -# include - -namespace boost -{ - - // faked new old-style categories needed to make new->old mapping - // work - namespace detail - { - struct null_category_tag {}; - struct input_output_iterator_tag : std::input_iterator_tag, std::output_iterator_tag {}; - } - - // - // Access Categories - // - struct readable_iterator_tag - { - typedef std::input_iterator_tag max_category; - }; - - struct writable_iterator_tag - { - typedef std::output_iterator_tag max_category; - }; - - struct swappable_iterator_tag - { - typedef detail::null_category_tag max_category; - }; - - struct readable_writable_iterator_tag - : virtual readable_iterator_tag - , virtual writable_iterator_tag - , virtual swappable_iterator_tag - { - typedef detail::input_output_iterator_tag max_category; - }; - - struct readable_lvalue_iterator_tag - : virtual readable_iterator_tag - { - typedef std::random_access_iterator_tag max_category; - }; - - struct writable_lvalue_iterator_tag - : virtual public readable_writable_iterator_tag - , virtual public readable_lvalue_iterator_tag - { - typedef std::random_access_iterator_tag max_category; - }; - - // - // Traversal Categories - // - struct incrementable_traversal_tag - { - typedef std::output_iterator_tag max_category; - }; - - struct single_pass_traversal_tag - : incrementable_traversal_tag - { - typedef detail::input_output_iterator_tag max_category; - }; - - struct forward_traversal_tag - : single_pass_traversal_tag - { - typedef std::forward_iterator_tag max_category; - }; - - struct bidirectional_traversal_tag - : forward_traversal_tag - { - typedef std::bidirectional_iterator_tag max_category; - }; - - struct random_access_traversal_tag - : bidirectional_traversal_tag - { - typedef std::random_access_iterator_tag max_category; - }; - - struct error_iterator_tag { }; - - namespace detail - { - // - // Tag detection meta functions - // - - // I bet this is defined somewhere else. Let's wait and see. - struct error_type; - -# ifndef BOOST_NO_IS_CONVERTIBLE - - // True iff T is a tag "derived" from Tag - template - struct is_tag - : mpl::or_< - is_convertible - - // Because we can't actually get forward_iterator_tag to - // derive from input_output_iterator_tag, we need this - // case. - , mpl::and_< - is_convertible - , is_convertible - > - > - {}; - - -# else - template - struct is_tag; -# endif - - // Generate specializations which will allow us to find - // null_category_tag as a minimum old-style category for new-style - // iterators which don't have an actual old-style category. We - // need that so there is a valid base class for all new-style - // iterators. -# define BOOST_OLD_ITERATOR_CATEGORY(category) \ - template <> \ - struct is_tag \ - : mpl::true_ {}; - - BOOST_OLD_ITERATOR_CATEGORY(input_iterator_tag) - BOOST_OLD_ITERATOR_CATEGORY(output_iterator_tag) - BOOST_OLD_ITERATOR_CATEGORY(forward_iterator_tag) - BOOST_OLD_ITERATOR_CATEGORY(bidirectional_iterator_tag) - BOOST_OLD_ITERATOR_CATEGORY(random_access_iterator_tag) -# undef BOOST_OLD_ITERATOR_CATEGORY - - template <> - struct is_tag - : mpl::true_ - { - }; - -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct is_tag : mpl::true_ - {}; - -# ifdef BOOST_NO_IS_CONVERTIBLE - // Workarounds for CWPro7 which can't detect derivation at - // compile-time. - - // Fact of life: we can only detect tag refinement relationships - // among predefined tags. - // - // Algorithm: - // is_tag(T,U) -> - // T == U - // || (exists d in derived_from(T) such that is_tag(d, U)) - // - // T == U case is handled above - - // false by default - template - struct is_tag_impl : mpl::false_ - {}; - - // The generalized template dispatches to is_tag_impl because - // is_tag and is_tag are equally specialized. - // This technique simulates making is_tag more-specialized. - template - struct is_tag - : is_tag_impl - {}; - -# define BOOST_ITERATOR_DERIVED_TAG1(base, derived) \ - BOOST_ITERATOR_DERIVED_TAG1_AUX(base, _, derived) - -# define BOOST_ITERATOR_DERIVED_TAG1_AUX(base, underscore, derived) \ - template \ - struct is_tag_impl \ - : is_tag \ - { \ - }; - - // Old-style tag relations - template - struct is_tag_impl - : mpl::or_< - is_tag - , is_tag - > - { - }; - - BOOST_ITERATOR_DERIVED_TAG1(std::output_iterator, detail::input_output_iterator) - BOOST_ITERATOR_DERIVED_TAG1(std::input_iterator, detail::input_output_iterator) - BOOST_ITERATOR_DERIVED_TAG1(detail::input_output_iterator, std::forward_iterator) - BOOST_ITERATOR_DERIVED_TAG1(std::forward_iterator, std::bidirectional_iterator) - BOOST_ITERATOR_DERIVED_TAG1(std::bidirectional_iterator, std::random_access_iterator) - - // Access tag relations - BOOST_ITERATOR_DERIVED_TAG1(readable_lvalue_iterator, writable_lvalue_iterator) - BOOST_ITERATOR_DERIVED_TAG1(swappable_iterator, readable_writable_iterator) - BOOST_ITERATOR_DERIVED_TAG1(readable_writable_iterator, writable_lvalue_iterator) - - template - struct is_tag_impl - : mpl::or_< - is_tag - , is_tag - > - { - }; - - BOOST_ITERATOR_DERIVED_TAG1(writable_iterator, readable_writable_iterator) - - // Traversal tag relations - BOOST_ITERATOR_DERIVED_TAG1(bidirectional_traversal, random_access_traversal) - BOOST_ITERATOR_DERIVED_TAG1(forward_traversal, bidirectional_traversal) - BOOST_ITERATOR_DERIVED_TAG1(single_pass_traversal, forward_traversal) - BOOST_ITERATOR_DERIVED_TAG1(incrementable_traversal, single_pass_traversal) - -# endif // BOOST_NO_IS_CONVERTIBLE workarounds - -# endif // ndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - template - struct known_tag - : mpl::apply_if, mpl::identity, Else> - {}; - - template - struct max_known_traversal_tag - : known_tag< - Tag, random_access_traversal_tag - , known_tag< - Tag, bidirectional_traversal_tag - , known_tag< - Tag, forward_traversal_tag - , known_tag< - Tag, single_pass_traversal_tag - , known_tag< - Tag, incrementable_traversal_tag - , error_iterator_tag - > - > - > - > - > - {}; - - // Doesn't cope with these odd combinations: readable+swappable, - // writable+swappable. That doesn't matter for the sake of - // new-style tag base computation, which is all it's used for - // anyway. - template - struct max_known_access_tag - : known_tag< - Tag, writable_lvalue_iterator_tag - , known_tag< - Tag, readable_lvalue_iterator_tag - , known_tag< - Tag, readable_writable_iterator_tag - , known_tag< - Tag, writable_iterator_tag - , known_tag< - Tag, readable_iterator_tag - , mpl::apply_if< - is_tag - , mpl::identity - , error_iterator_tag - > - > - > - > - > - > - {}; - - // - // Returns the minimum category type or error_type - // if T1 and T2 are unrelated. - // - // For compilers not supporting is_convertible this only - // works with the new boost return and traversal category - // types. The exact boost _types_ are required. No derived types - // will work. - // - // - template - struct minimum_category - : mpl::apply_if< - is_tag - , mpl::identity - , mpl::if_< - is_tag - , T2 - , error_type - > - > - { - BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2)) - }; - -# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) - // Deal with ETI - template <> struct minimum_category { typedef minimum_category type; }; -# endif - - // - // Tag classification for use in iterator_adaptor - // - template - struct is_access_tag - : mpl::or_< - is_tag - , mpl::or_< - is_tag - , is_tag - > - > - {}; - - template - struct is_traversal_tag - : is_tag - {}; - - } // namespace detail - -} // namespace boost - -#include - -#endif // BOOST_ITERATOR_DETAIL_CATEGORIES_HPP +#error obsolete diff --git a/include/boost/iterator/detail/config_def.hpp b/include/boost/iterator/detail/config_def.hpp index 6789d4a..c31d71c 100644 --- a/include/boost/iterator/detail/config_def.hpp +++ b/include/boost/iterator/detail/config_def.hpp @@ -18,7 +18,66 @@ #include // for prior #include -#define BOOST_ITERATOR_CONFIG_DEF // if you get an error here, you have nested config_def #inclusion. +#ifdef BOOST_ITERATOR_CONFIG_DEF +# error you have nested config_def #inclusion. +#else +# define BOOST_ITERATOR_CONFIG_DEF +#endif + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531)) + +// Recall that in general, compilers without partial specialization +// can't strip constness. Consider counting_iterator, which normally +// passes a const Value to iterator_facade. As a result, any code +// which makes a std::vector of the iterator's value_type will fail +// when its allocator declares functions overloaded on reference and +// const_reference (the same type). +// +// Furthermore, Borland 5.5.1 drops constness in enough ways that we +// end up using a proxy for operator[] when we otherwise shouldn't. +// Using reference constness gives it an extra hint that it can +// return the value_type from operator[] directly, but is not +// strictly neccessary. Not sure how best to resolve this one. + +# define BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY 1 + +#endif + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531)) \ + || (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER)) +# define BOOST_NO_LVALUE_RETURN_DETECTION + +# if 0 // test code + struct v {}; + + typedef char (&no)[3]; + + template + no foo(T const&, ...); + + template + char foo(T&, int); + + + struct value_iterator + { + v operator*() const; + }; + + template + struct lvalue_deref_helper + { + static T& x; + enum { value = (sizeof(foo(*x,0)) == 1) }; + }; + + int z2[(lvalue_deref_helper::value == 1) ? 1 : -1]; + int z[(lvalue_deref_helper::value) == 1 ? -1 : 1 ]; +# endif + +#endif #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ || BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) \ diff --git a/include/boost/iterator/detail/config_undef.hpp b/include/boost/iterator/detail/config_undef.hpp index f58df62..f93adae 100644 --- a/include/boost/iterator/detail/config_undef.hpp +++ b/include/boost/iterator/detail/config_undef.hpp @@ -18,6 +18,7 @@ #undef BOOST_NO_IS_CONVERTIBLE_TEMPLATE #undef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY #undef BOOST_ARG_DEPENDENT_TYPENAME +#undef BOOST_NO_LVALUE_RETURN_DETECTION #ifdef BOOST_ITERATOR_CONFIG_DEF # undef BOOST_ITERATOR_CONFIG_DEF diff --git a/include/boost/iterator/detail/facade_iterator_category.hpp b/include/boost/iterator/detail/facade_iterator_category.hpp new file mode 100755 index 0000000..9b2aa1a --- /dev/null +++ b/include/boost/iterator/detail/facade_iterator_category.hpp @@ -0,0 +1,214 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef FACADE_ITERATOR_CATEGORY_DWA20031118_HPP +# define FACADE_ITERATOR_CATEGORY_DWA20031118_HPP + +# include + +# include + +# include // used in iterator_tag inheritance logic +# include +# include +# include +# include + +# include +# include +# include +# include + +# include + +# include // try to keep this last + +# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY +# include +# endif + +// +// iterator_category deduction for iterator_facade +// + +// forward declaration +namespace boost { struct use_default; } + +namespace boost { namespace detail { + +struct input_output_iterator_tag + : std::input_iterator_tag +{ + // Using inheritance for only input_iterator_tag helps to avoid + // ambiguities when a stdlib implementation dispatches on a + // function which is overloaded on both input_iterator_tag and + // output_iterator_tag, as STLPort does, in its __valid_range + // function. I claim it's better to avoid the ambiguity in these + // cases. + operator std::output_iterator_tag() const + { + return std::output_iterator_tag(); + } +}; + +// +// True iff the user has explicitly disabled writability of this +// iterator. Pass the iterator_facade's Value parameter and its +// nested ::reference type. +// +template +struct iterator_writability_disabled +# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic? + : mpl::or_< + is_const + , python::detail::is_reference_to_const + , is_const + > +# else + : is_const +# endif +{}; + + +// +// Convert an iterator_facade's traversal category, Value parameter, +// and ::reference type to an appropriate old-style category. +// +// If writability has been disabled per the above metafunction, the +// result will not be convertible to output_iterator_tag. +// +// Otherwise, if Traversal == single_pass_traversal_tag, the following +// conditions will result in a tag that is convertible both to +// input_iterator_tag and output_iterator_tag: +// +// 1. Reference is a reference to non-const +// 2. Reference is not a reference and is convertible to Value +// +template +struct iterator_facade_default_category + : mpl::apply_if< + mpl::and_< + is_reference + , is_convertible + > + , mpl::apply_if< + is_convertible + , mpl::identity + , mpl::if_< + is_convertible + , std::bidirectional_iterator_tag + , std::forward_iterator_tag + > + > + , typename mpl::apply_if< + mpl::and_< + is_convertible + + , mpl::or_< // check for readability + is_same + , is_convertible + > + > + , mpl::if_< + iterator_writability_disabled + , std::input_iterator_tag + , input_output_iterator_tag + > + + , mpl::identity + > + > +{ +}; + +// True iff T is convertible to an old-style iterator category. +template +struct is_iterator_category + : mpl::or_< + is_convertible + , is_convertible + > +{ +}; + +template +struct is_iterator_traversal + : is_convertible +{}; + +// +// A composite iterator_category tag convertible to Category (a pure +// old-style category) and Traversal (a pure traversal tag). +// Traversal must be a strict increase of the traversal power given by +// Category. +// +template +struct iterator_category_with_traversal + : Category, Traversal +{ +# if 0 + // Because of limitations on multiple user-defined conversions, + // this should be a good test of whether convertibility is enough + // in the spec, or whether we need to specify inheritance. + operator Category() const { return Category(); } + operator Traversal() const { return Traversal(); } +# endif + +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + // Make sure this isn't used to build any categories where + // convertibility to Traversal is redundant. Should just use the + // Category element in that case. + BOOST_STATIC_ASSERT( + !(is_convertible< + typename iterator_category_to_traversal::type + , Traversal + >::value)); + + BOOST_STATIC_ASSERT(is_iterator_category::value); + BOOST_STATIC_ASSERT(!is_iterator_category::value); + BOOST_STATIC_ASSERT(!is_iterator_traversal::value); + BOOST_STATIC_ASSERT(is_iterator_traversal::value); +# endif +}; + +// Computes an iterator_category tag whose traversal is Traversal and +// which is appropriate for an iterator +template +struct facade_iterator_category_impl +{ +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + BOOST_STATIC_ASSERT(!is_iterator_category::value); +# endif + + typedef typename iterator_facade_default_category< + Traversal,ValueParam,Reference + >::type category; + + typedef typename mpl::if_< + is_same< + Traversal + , typename iterator_category_to_traversal::type + > + , category + , iterator_category_with_traversal + >::type type; +}; + +// +// Compute an iterator_category for iterator_facade +// +template +struct facade_iterator_category + : mpl::apply_if< + is_iterator_category + , mpl::identity // old-style categories are fine as-is + , facade_iterator_category_impl + > +{ +}; + +}} // namespace boost::detail + +# include + +#endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP diff --git a/include/boost/iterator/detail/minimum_category.hpp b/include/boost/iterator/detail/minimum_category.hpp new file mode 100755 index 0000000..b1fcd9f --- /dev/null +++ b/include/boost/iterator/detail/minimum_category.hpp @@ -0,0 +1,98 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef MINIMUM_CATEGORY_DWA20031119_HPP +# define MINIMUM_CATEGORY_DWA20031119_HPP + +# include +# include + +# include + +namespace boost { namespace detail { +// +// Returns the minimum category type or error_type +// if T1 and T2 are unrelated. +// +// For compilers not supporting is_convertible this only +// works with the new boost return and traversal category +// types. The exact boost _types_ are required. No derived types +// will work. +// +// +template +struct minimum_category_impl; + +template +struct error_not_related_by_convertibility; + +template <> +struct minimum_category_impl +{ + template struct apply + { + typedef T2 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + { + typedef T1 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + { + BOOST_STATIC_ASSERT((is_same::value)); + typedef T1 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + : error_not_related_by_convertibility + { + }; +}; + +template +struct minimum_category +{ + typedef minimum_category_impl< + ::boost::is_convertible::value + , ::boost::is_convertible::value + > outer; + + typedef typename outer::template apply inner; + typedef typename inner::type type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2)) +}; + +template <> +struct minimum_category +{ + template + struct apply : minimum_category + {}; +}; + +# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) +template <> +struct minimum_category +{ + typedef int type; +}; +# endif + +}} // namespace boost::detail + +#endif // MINIMUM_CATEGORY_DWA20031119_HPP diff --git a/include/boost/iterator/filter_iterator.hpp b/include/boost/iterator/filter_iterator.hpp index cd490dc..fee0184 100644 --- a/include/boost/iterator/filter_iterator.hpp +++ b/include/boost/iterator/filter_iterator.hpp @@ -13,28 +13,42 @@ #include #include +#include +#include + namespace boost { + template + class filter_iterator; + namespace detail + { + template + struct filter_iterator_base + { + typedef iterator_adaptor< + filter_iterator + , Iterator + , use_default + , typename mpl::if_< + is_convertible< + typename iterator_traversal::type + , bidirectional_traversal_tag + > + , forward_traversal_tag + , use_default + >::type + > type; + }; + } + template class filter_iterator - : public iterator_adaptor< - filter_iterator, Iterator - , use_default - , typename detail::minimum_category< - bidirectional_traversal_tag - , typename traversal_category::type - >::type - > + : public detail::filter_iterator_base::type { - typedef iterator_adaptor< - filter_iterator, Iterator - , use_default - , typename detail::minimum_category< - bidirectional_traversal_tag - , typename traversal_category::type - >::type - > super_t; + typedef typename detail::filter_iterator_base< + Predicate, Iterator + >::type super_t; friend class iterator_core_access; diff --git a/include/boost/iterator/is_lvalue_iterator.hpp b/include/boost/iterator/is_lvalue_iterator.hpp index d77b977..4938151 100755 --- a/include/boost/iterator/is_lvalue_iterator.hpp +++ b/include/boost/iterator/is_lvalue_iterator.hpp @@ -4,16 +4,19 @@ #ifndef IS_LVALUE_ITERATOR_DWA2003112_HPP # define IS_LVALUE_ITERATOR_DWA2003112_HPP -#include -#include #include -#include +#include +#include + #include -// should be the last #include +// should be the last #includes +#include #include +#ifndef BOOST_NO_IS_CONVERTIBLE + namespace boost { namespace detail @@ -122,7 +125,7 @@ namespace detail {}; template - struct is_mutable_lvalue_iterator_impl + struct is_non_const_lvalue_iterator_impl : is_lvalue_iterator_impl< BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits::value_type >::template rebind @@ -135,10 +138,13 @@ BOOST_TT_AUX_BOOL_TRAIT_DEF1( is_lvalue_iterator,T,::boost::detail::is_readable_lvalue_iterator_impl::value) BOOST_TT_AUX_BOOL_TRAIT_DEF1( - is_mutable_lvalue_iterator,T,::boost::detail::is_mutable_lvalue_iterator_impl::value) + is_non_const_lvalue_iterator,T,::boost::detail::is_non_const_lvalue_iterator_impl::value) } // namespace boost +#endif + #include +#include #endif // IS_LVALUE_ITERATOR_DWA2003112_HPP diff --git a/include/boost/iterator/is_readable_iterator.hpp b/include/boost/iterator/is_readable_iterator.hpp index 52df758..60d6ff0 100755 --- a/include/boost/iterator/is_readable_iterator.hpp +++ b/include/boost/iterator/is_readable_iterator.hpp @@ -13,6 +13,8 @@ // should be the last #include #include +#ifndef BOOST_NO_IS_CONVERTIBLE + namespace boost { namespace detail @@ -99,6 +101,8 @@ BOOST_TT_AUX_BOOL_TRAIT_DEF1( } // namespace boost +#endif + #include #endif // IS_READABLE_ITERATOR_DWA2003112_HPP diff --git a/include/boost/iterator/iterator_adaptor.hpp b/include/boost/iterator/iterator_adaptor.hpp index af14283..50694a1 100644 --- a/include/boost/iterator/iterator_adaptor.hpp +++ b/include/boost/iterator/iterator_adaptor.hpp @@ -26,12 +26,32 @@ #include #include +#ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY +# include +#else +# include +#endif + #include #include namespace boost { + // Used as a default template argument internally, merely to + // indicate "use the default", this can also be passed by users + // explicitly in order to specify that the default should be used. + struct use_default; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // the incompleteness of use_default causes massive problems for + // is_convertible (naturally). This workaround is fortunately not + // needed for vc6/vc7. + template + struct is_convertible + : mpl::false_ {}; +# endif + namespace detail { @@ -142,63 +162,51 @@ namespace boost class Derived , class Base , class Value - , class Category + , class Traversal , class Reference , class Difference > struct iterator_adaptor_base { - private: // intermediate results - - typedef typename mpl::apply_if< - mpl::or_< - is_same - , mpl::or_< - is_access_tag - , is_traversal_tag - > - > - , BOOST_ITERATOR_CATEGORY - , mpl::identity - >::type category; - - typedef typename detail::ia_dflt_help< - Reference - , mpl::apply_if< - is_same - , iterator_reference - , mpl::identity - > - >::type reference; - - public: // return type typedef iterator_facade< Derived - + +# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY + , typename detail::ia_dflt_help< + Value + , mpl::apply_if< + is_same + , iterator_value + , remove_reference + > + >::type +# else , typename detail::ia_dflt_help< Value, iterator_value >::type - - , typename mpl::apply_if< - is_access_tag - , mpl::identity - , access_category_tag - >::type +# endif + + , typename detail::ia_dflt_help< + Traversal + , iterator_traversal + >::type + + , typename detail::ia_dflt_help< + Reference + , mpl::apply_if< + is_same + , iterator_reference + , add_reference + > + >::type - , typename mpl::apply_if< - is_traversal_tag - , mpl::identity - , traversal_category_tag - >::type - - , reference - , typename detail::ia_dflt_help< Difference, iterator_difference >::type > type; }; + template int static_assert_convertible_to(T); } // @@ -215,8 +223,8 @@ namespace boost // const. If const, a conforming compiler strips constness for the // value_type. If not supplied, iterator_traits::value_type is used // - // Category - the iterator_category of the resulting iterator. If not - // supplied, iterator_traits::iterator_category is used. + // Category - the traversal category of the resulting iterator. If not + // supplied, iterator_traversal::type is used. // // Reference - the reference type of the resulting iterator, and in // particular, the result type of operator*(). If not supplied but @@ -230,19 +238,19 @@ namespace boost class Derived , class Base , class Value = use_default - , class Category = use_default + , class Traversal = use_default , class Reference = use_default , class Difference = use_default > class iterator_adaptor : public detail::iterator_adaptor_base< - Derived, Base, Value, Category, Reference, Difference + Derived, Base, Value, Traversal, Reference, Difference >::type { friend class iterator_core_access; typedef typename detail::iterator_adaptor_base< - Derived, Base, Value, Category, Reference, Difference + Derived, Base, Value, Traversal, Reference, Difference >::type super_t; public: @@ -287,17 +295,18 @@ namespace boost // ); return m_iterator == x.base(); } - + + typedef typename iterator_category_to_traversal< + typename super_t::iterator_category + >::type my_traversal; + +# define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \ + typedef int assertion[sizeof(detail::static_assert_convertible_to(my_traversal()))]; +// BOOST_STATIC_ASSERT((is_convertible::value)); + void advance(typename super_t::difference_type n) { -# if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) // seems to get instantiated incorrectly - BOOST_STATIC_ASSERT( - (detail::is_tag< - random_access_traversal_tag - , BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal - >::value) - ); -# endif + BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag) m_iterator += n; } @@ -305,14 +314,7 @@ namespace boost void decrement() { -# if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) // seems to get instantiated incorrectly - BOOST_STATIC_ASSERT( - (detail::is_tag< - bidirectional_traversal_tag - , BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal - >::value) - ); -# endif + BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag) --m_iterator; } @@ -322,12 +324,7 @@ namespace boost typename super_t::difference_type distance_to( iterator_adaptor const& y) const { - BOOST_STATIC_ASSERT( - (detail::is_tag< - random_access_traversal_tag - , BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal - >::value) - ); + BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag) // Maybe readd with same_distance // BOOST_STATIC_ASSERT( // (detail::same_category_and_difference::value) @@ -335,6 +332,8 @@ namespace boost return y.base() - m_iterator; } +# undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL + private: // data members Base m_iterator; }; diff --git a/include/boost/iterator/iterator_archetypes.hpp b/include/boost/iterator/iterator_archetypes.hpp index e9439e7..b0ab188 100644 --- a/include/boost/iterator/iterator_archetypes.hpp +++ b/include/boost/iterator/iterator_archetypes.hpp @@ -8,341 +8,449 @@ #define BOOST_ITERATOR_ARCHETYPES_HPP #include -#include -#include #include #include +#include + +#include + #include +#include #include #include #include +#include +#include +#include +#include +#include +#include +#include #include -namespace boost +namespace boost { + +template +struct access_archetype; + +template +struct traversal_archetype; + +namespace iterator_archetypes { + enum { + readable_iterator_bit = 1 + , writable_iterator_bit = 2 + , swappable_iterator_bit = 4 + , lvalue_iterator_bit = 8 + }; - template - struct access_archetype; + // Not quite tags, since dispatching wouldn't work. + typedef mpl::int_::type readable_iterator_t; + typedef mpl::int_::type writable_iterator_t; + + typedef mpl::int_< + (readable_iterator_bit|writable_iterator_bit) + >::type readable_writable_iterator_t; + + typedef mpl::int_< + (readable_iterator_bit|lvalue_iterator_bit) + >::type readable_lvalue_iterator_t; + + typedef mpl::int_< + (lvalue_iterator_bit|writable_iterator_bit) + >::type writable_lvalue_iterator_t; + + typedef mpl::int_::type swappable_iterator_t; + typedef mpl::int_::type lvalue_iterator_t; - template - struct traversal_archetype; + template + struct has_access + : mpl::equal_to< + mpl::bitand_ + , Base + > + {}; +} - namespace detail { - - template - struct assign_proxy - { +namespace detail +{ + template + struct assign_proxy + { assign_proxy& operator=(T); - }; + }; - template - struct read_write_proxy : - assign_proxy - { + template + struct read_proxy + { operator T(); - }; + }; - template - struct arrow_proxy - { + template + struct read_write_proxy + : assign_proxy + , read_proxy + { + }; + + template + struct arrow_proxy + { T const* operator->() const; - }; + }; - struct no_operator_brackets {}; + struct no_operator_brackets {}; - template - struct readable_operator_brackets - { - ValueType operator[](std::ptrdiff_t n) const; - }; + template + struct readable_operator_brackets + { + read_proxy operator[](std::ptrdiff_t n) const; + }; - template - struct writable_operator_brackets - { + template + struct writable_operator_brackets + { read_write_proxy operator[](std::ptrdiff_t n) const; - }; + }; - template - struct operator_brackets : - mpl::if_< is_tag, - mpl::if_< is_tag, - writable_operator_brackets< Value >, - mpl::if_< is_tag, - readable_operator_brackets, - no_operator_brackets > >, - no_operator_brackets >::type - { - }; + template + struct operator_brackets + : mpl::aux::msvc_eti_base< + typename mpl::apply_if< + is_convertible + , mpl::apply_if< + iterator_archetypes::has_access< + AccessCategory + , iterator_archetypes::writable_iterator_t + > + , mpl::identity > + , mpl::if_< + iterator_archetypes::has_access< + AccessCategory + , iterator_archetypes::readable_iterator_t + > + , readable_operator_brackets + , no_operator_brackets + > + > + , mpl::identity + >::type + >::type + {}; + + template + struct traversal_archetype_impl + { + template struct archetype; + }; - template - struct traversal_archetype_impl - { - template struct archetype; - }; + template + struct traversal_archetype_ + : mpl::aux::msvc_eti_base< + typename traversal_archetype_impl::template archetype + >::type + {}; - template - struct traversal_archetype_ - : mpl::aux::msvc_eti_base< - typename traversal_archetype_impl::template archetype - >::type - {}; + template <> + struct traversal_archetype_impl + { + template + struct archetype + { + typedef void difference_type; - template <> - struct traversal_archetype_impl - { - template - struct archetype - { - typedef void difference_type; + Derived& operator++(); + Derived operator++(int) const; + }; + }; - Derived& operator++(); - Derived operator++(int) const; - }; - }; + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public equality_comparable< traversal_archetype_ >, + public traversal_archetype_ + { + }; + }; - template <> - struct traversal_archetype_impl - { - template - struct archetype - : public equality_comparable< traversal_archetype_ >, - public traversal_archetype_ - { - }; - }; - - template - bool operator==(traversal_archetype_ const&, - traversal_archetype_ const&); + template + bool operator==(traversal_archetype_ const&, + traversal_archetype_ const&); #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // doesn't seem to pick up != from equality_comparable - template - bool operator!=(traversal_archetype_ const&, - traversal_archetype_ const&); + template + bool operator!=(traversal_archetype_ const&, + traversal_archetype_ const&); #endif - template <> - struct traversal_archetype_impl - { - template - struct archetype - : public traversal_archetype_ - { - typedef std::ptrdiff_t difference_type; - }; - }; + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + typedef std::ptrdiff_t difference_type; + }; + }; - template <> - struct traversal_archetype_impl - { - template - struct archetype - : public traversal_archetype_ - { - Derived& operator--(); - Derived operator--(int) const; - }; - }; + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + Derived& operator--(); + Derived operator--(int) const; + }; + }; - template <> - struct traversal_archetype_impl - { - template - struct archetype - : public partially_ordered >, - public traversal_archetype_ - { - Derived& operator+=(std::ptrdiff_t); - Derived& operator-=(std::ptrdiff_t); - }; - }; + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public partially_ordered >, + public traversal_archetype_ + { + Derived& operator+=(std::ptrdiff_t); + Derived& operator-=(std::ptrdiff_t); + }; + }; - template - Derived& operator+(traversal_archetype_ const&, - std::ptrdiff_t); + template + Derived& operator+(traversal_archetype_ const&, + std::ptrdiff_t); - template - Derived& operator+(std::ptrdiff_t, - traversal_archetype_ const&); + template + Derived& operator+(std::ptrdiff_t, + traversal_archetype_ const&); - template - Derived& operator-(traversal_archetype_ const&, - std::ptrdiff_t); + template + Derived& operator-(traversal_archetype_ const&, + std::ptrdiff_t); - template - std::ptrdiff_t operator-(traversal_archetype_ const&, - traversal_archetype_ const&); + template + std::ptrdiff_t operator-(traversal_archetype_ const&, + traversal_archetype_ const&); - template - bool operator<(traversal_archetype_ const&, - traversal_archetype_ const&); + template + bool operator<(traversal_archetype_ const&, + traversal_archetype_ const&); - struct bogus_type; + struct bogus_type; + template + struct convertible_type + : mpl::if_< is_const, + typename remove_const::type, + bogus_type > + {}; + +} // namespace detail + + +template struct undefined; + +template +struct iterator_access_archetype_impl +{ + template struct archetype; +}; + +template +struct iterator_access_archetype + : mpl::aux::msvc_eti_base< + typename iterator_access_archetype_impl< + AccessCategory + >::template archetype + >::type +{ +}; + +template <> +struct iterator_access_archetype_impl< + iterator_archetypes::readable_iterator_t +> +{ template - struct convertible_type - : mpl::if_< is_const, - typename remove_const::type, - bogus_type > - {}; + struct archetype + { + typedef typename remove_cv::type value_type; + typedef Value reference; + typedef Value* pointer; - } // namespace detail + value_type operator*() const; + detail::arrow_proxy operator->() const; + }; +}; - template struct undefined; - - template - struct access_archetype_impl - { - template struct archetype; - }; - - template - struct access_archetype - : mpl::aux::msvc_eti_base< - typename access_archetype_impl::template archetype - >::type - { - }; - - template <> - struct access_archetype_impl - { - template - struct archetype - { - typedef typename remove_cv::type value_type; - typedef Value reference; - typedef Value* pointer; - - value_type operator*() const; - - detail::arrow_proxy operator->() const; - }; - }; - - template <> - struct access_archetype_impl - { - template - struct archetype - { +template <> +struct iterator_access_archetype_impl< + iterator_archetypes::writable_iterator_t +> +{ + template + struct archetype + { # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - BOOST_STATIC_ASSERT(!is_const::value); + BOOST_STATIC_ASSERT(!is_const::value); # endif - typedef void value_type; - typedef void reference; - typedef void pointer; + typedef void value_type; + typedef void reference; + typedef void pointer; - detail::assign_proxy operator*() const; - }; - }; + detail::assign_proxy operator*() const; + }; +}; - template <> - struct access_archetype_impl - { - template - struct archetype - : public virtual access_archetype - { - typedef detail::read_write_proxy reference; - - detail::read_write_proxy operator*() const; - }; - }; - - template <> - struct access_archetype_impl - { - template - struct archetype - : public virtual access_archetype - { - typedef Value& reference; - - Value& operator*() const; - Value* operator->() const; - }; - }; - - template <> - struct access_archetype_impl - { - template - struct archetype - : public virtual access_archetype - { -# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - BOOST_STATIC_ASSERT((!is_const::value)); -# endif - }; - }; - - - template - struct iterator_archetype; - - template - struct traversal_archetype_base - : detail::operator_brackets< - typename remove_cv::type - , AccessCategory - , TraversalCategory - > - , detail::traversal_archetype_< - iterator_archetype - , Value - , TraversalCategory +template <> +struct iterator_access_archetype_impl< + iterator_archetypes::readable_writable_iterator_t +> +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, iterator_archetypes::readable_iterator_t > - { - }; + { + typedef detail::read_write_proxy reference; - template - struct iterator_archetype - : public traversal_archetype_base - , public access_archetype + detail::read_write_proxy operator*() const; + }; +}; - // These broken libraries require derivation from std::iterator - // (or related magic) in order to handle iter_swap and other - // iterator operations -# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ - || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) - , public std::iterator< - iterator_tag - , typename access_archetype::value_type - , typename traversal_archetype_base< - Value, AccessCategory, TraversalCategory - >::difference_type - > +template <> +struct iterator_access_archetype_impl +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, iterator_archetypes::readable_iterator_t + > + { + typedef Value& reference; + + Value& operator*() const; + Value* operator->() const; + }; +}; + +template <> +struct iterator_access_archetype_impl +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, iterator_archetypes::readable_lvalue_iterator_t + > + { +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + BOOST_STATIC_ASSERT((!is_const::value)); # endif + }; +}; + + +template +struct iterator_archetype; + +template +struct traversal_archetype_base + : detail::operator_brackets< + typename remove_cv::type + , AccessCategory + , TraversalCategory + > + , detail::traversal_archetype_< + iterator_archetype + , Value + , TraversalCategory + > +{ +}; + +namespace detail +{ + template + struct iterator_archetype_base + : iterator_access_archetype + , traversal_archetype_base { - // Derivation from std::iterator above caused ambiguity, so now - // we have to declare all the types here. + typedef iterator_access_archetype access; + + typedef typename detail::facade_iterator_category< + TraversalCategory + , typename mpl::apply_if< + iterator_archetypes::has_access< + AccessCategory, iterator_archetypes::writable_iterator_t + > + , remove_const + , add_const + >::type + , typename access::reference + >::type iterator_category; + + // Needed for some broken libraries (see below) + typedef boost::iterator< + iterator_category + , Value + , typename traversal_archetype_base< + Value, AccessCategory, TraversalCategory + >::difference_type + , typename access::pointer + , typename access::reference + > workaround_iterator_base; + }; +} + +template +struct iterator_archetype + : public detail::iterator_archetype_base + + // These broken libraries require derivation from std::iterator + // (or related magic) in order to handle iter_swap and other + // iterator operations # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) - typedef typename access_archetype::value_type value_type; - - typedef typename access_archetype::pointer pointer; - - typedef typename access_archetype::reference reference; - - typedef typename traversal_archetype_base< - Value, AccessCategory, TraversalCategory - >::difference_type difference_type; + , public detail::iterator_archetype_base< + Value, AccessCategory, TraversalCategory + >::workaround_iterator_base +# endif +{ + // Derivation from std::iterator above caused references to nested + // types to be ambiguous, so now we have to redeclare them all + // here. +# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ + || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) + + typedef detail::iterator_archetype_base< + Value,AccessCategory,TraversalCategory + > base; + + typedef typename base::value_type value_type; + typedef typename base::reference reference; + typedef typename base::pointer pointer; + typedef typename base::difference_type difference_type; + typedef typename base::iterator_category iterator_category; # endif - - typedef iterator_tag iterator_category; - iterator_archetype(); - iterator_archetype(iterator_archetype const&); + iterator_archetype(); + iterator_archetype(iterator_archetype const&); - iterator_archetype& operator=(iterator_archetype const&); + iterator_archetype& operator=(iterator_archetype const&); - // Optional conversion from mutable - // iterator_archetype(iterator_archetype::type, AccessCategory, TraversalCategory> const&); - }; + // Optional conversion from mutable + // iterator_archetype(iterator_archetype::type, AccessCategory, TraversalCategory> const&); +}; } // namespace boost diff --git a/include/boost/iterator/iterator_categories.hpp b/include/boost/iterator/iterator_categories.hpp index cbf1f2f..7b4f9ae 100644 --- a/include/boost/iterator/iterator_categories.hpp +++ b/include/boost/iterator/iterator_categories.hpp @@ -4,425 +4,159 @@ // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. -// TODO: -// Add separate category tag for operator[]. - #ifndef BOOST_ITERATOR_CATEGORIES_HPP -#define BOOST_ITERATOR_CATEGORIES_HPP +# define BOOST_ITERATOR_CATEGORIES_HPP -#include -#include +# include +# include +# include -#include -#include +# include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT +# include +# include # include -#endif +# include -#include +# include -#include // must be last #include - -#if BOOST_WORKAROUND(__MWERKS__, <=0x2407) -# define BOOST_NO_IS_CONVERTIBLE // "Convertible does not provide enough/is not working" -#endif +# include namespace boost { - namespace detail - { - // Helper metafunction for std_category below - template - struct match_tag - : mpl::apply_if, mpl::identity, Next> - { - }; - - // Converts a possibly user-defined category tag to the - // most-derived standard tag which is a base of that tag. - template - struct std_category - : match_tag< - Category, std::random_access_iterator_tag - , match_tag -# else - , void -# endif - > - > - > - > - > - { - }; - - // std_to_new_tags -- - // - // A metafunction which converts any standard tag into its - // corresponding new-style traversal tag. - // - // Also, instantiations are metafunction classes which convert a - // reference type into a corresponding new-style access tag. - template struct std_to_new_tags -# if BOOST_WORKAROUND(BOOST_MSVC, == 1300) // handle ETI - { - typedef void type; - template struct apply { typedef void type; }; - } -# endif - ; - -# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // handle ETI - template <> struct std_to_new_tags {}; -# endif - - // - // Specializations for specific standard tags - // - template <> - struct std_to_new_tags - { - typedef single_pass_traversal_tag type; - - template - struct apply - : mpl::identity {}; - - }; - - template <> - struct std_to_new_tags - { - typedef incrementable_traversal_tag type; - - template - struct apply - : mpl::identity {}; - }; - - template <> - struct std_to_new_tags - { - typedef forward_traversal_tag type; - - template - struct apply - : mpl::if_< - python::detail::is_reference_to_const - , boost::readable_lvalue_iterator_tag - , boost::writable_lvalue_iterator_tag - > - {}; - }; - - template <> - struct std_to_new_tags - : std_to_new_tags - { - typedef bidirectional_traversal_tag type; - }; - - template <> - struct std_to_new_tags - : std_to_new_tags - { - typedef random_access_traversal_tag type; - }; - - template - struct old_tag_converter - : std_to_new_tags< - typename std_category::type - > - { - }; - - template - struct iter_category_to_traversal - : std_to_new_tags< - typename std_category::type - > - {}; - - template - struct iter_category_to_access - : mpl::apply1< - iter_category_to_traversal - , Reference - > - {}; - -# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) - // Deal with ETI - template <> struct iter_category_to_access {}; - template <> struct iter_category_to_traversal {}; -# endif - - // A metafunction returning true iff T is boost::iterator_tag - template - struct is_boost_iterator_tag; - -#if BOOST_WORKAROUND(__MWERKS__, <= 0x2407) - // - // has_xxx fails, so we have to use - // something less sophisticated. - // - // The solution depends on the fact that only - // std iterator categories work with is_xxx_iterator - // meta functions, as BOOST_NO_IS_CONVERTIBLE is - // defined for cwpro7. - // - template - struct is_new_iterator_tag - : mpl::not_< - mpl::or_< - is_tag - , is_tag - > - > - {}; - -#elif BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \ - || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) - - template - struct is_new_iterator_tag - : is_boost_iterator_tag - { - }; - -#else - - BOOST_MPL_HAS_XXX_TRAIT_DEF(traversal) - - template - struct is_new_iterator_tag - : mpl::if_< - is_class - , has_traversal - , mpl::false_ - >::type - { - }; - -#endif - - } // namespace detail +// +// Traversal Categories +// +struct incrementable_traversal_tag {}; - namespace detail { - - template - struct get_traversal_category { - typedef typename NewCategoryTag::traversal type; - }; - - // Remove all writability from the given access tag. This - // functionality is part of new_category_to_access in order to - // support deduction of the proper default access category for - // iterator_adaptor; when the reference type is a reference to - // constant we must strip writability. - template - struct remove_access_writability - : mpl::apply_if< - is_tag - , mpl::identity - - , mpl::apply_if< - is_tag - , mpl::identity - - , mpl::if_< - is_tag - // Is this OK? I think it may correct be for all - // legitimate cases, because at this point the - // iterator is not readable, so it could not have - // been any more than writable + swappable. - , swappable_iterator_tag - , AccessTag - > - > - > - {}; +struct single_pass_traversal_tag + : incrementable_traversal_tag {}; - template - struct new_category_to_access - : mpl::apply_if< - python::detail::is_reference_to_const - , remove_access_writability - , mpl::identity - > - {}; +struct forward_traversal_tag + : single_pass_traversal_tag {}; + +struct bidirectional_traversal_tag + : forward_traversal_tag {}; + +struct random_access_traversal_tag + : bidirectional_traversal_tag {}; - template - struct access_category_tag - : mpl::apply_if< - is_new_iterator_tag - , new_category_to_access - , iter_category_to_access +namespace detail +{ + // + // Convert a "strictly old-style" iterator category to a traversal + // tag. This is broken out into a separate metafunction to reduce + // the cost of instantiating iterator_category_to_traversal, below, + // for new-style types. + // + template + struct old_category_to_traversal + : mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , void + > + > + > > - { - }; - - template - struct traversal_category_tag - : mpl::apply_if< - is_new_iterator_tag - , get_traversal_category - , iter_category_to_traversal - > - { - }; - -# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) - // Deal with ETI - template <> struct access_category_tag { typedef void type; }; - template <> struct traversal_category_tag { typedef void type; }; -# endif - - // iterator_tag_base - a metafunction to compute the appropriate - // old-style tag (if any) to use as a base for a new-style tag. - template - struct iterator_tag_base - : minimum_category< - typename KnownAccessTag::max_category - , typename KnownTraversalTag::max_category - > - {}; - -# if BOOST_WORKAROUND(BOOST_MSVC,<=1200) - template <> - struct iterator_tag_base - : mpl::false_ {}; // just using false_ so that the result will be - // a legal base class -# endif - - // specialization for this special case. Otherwise we get - // input_output_iterator_tag, because the standard hierarchy has a - // sudden anomalous distinction between readability and - // writability at the level of input iterator/output iterator. - template <> - struct iterator_tag_base< - readable_lvalue_iterator_tag,single_pass_traversal_tag> - { - typedef std::input_iterator_tag type; - }; - - } // namespace detail - - template - struct access_category - : detail::access_category_tag< - typename detail::iterator_traits::iterator_category - , typename detail::iterator_traits::reference> + > {}; - template - struct traversal_category - : detail::traversal_category_tag< - typename detail::iterator_traits::iterator_category +# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) + template <> + struct old_category_to_traversal + { + typedef int type; + }; +# endif + + template + struct pure_traversal_tag + : mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , void + > + > + > + > > { }; + +# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) + template <> + struct pure_traversal_tag + { + typedef int type; + }; +# endif + +} // namespace detail + + +// +// Convert an iterator category into a traversal tag +// +template +struct iterator_category_to_traversal + : mpl::apply_if< // if already convertible to a traversal tag, we're done. + is_convertible + , mpl::identity + , detail::old_category_to_traversal + > +{}; + +// Trait to get an iterator's traversal category +template +struct iterator_traversal + : iterator_category_to_traversal< + typename boost::detail::iterator_traits::iterator_category + > +{}; # ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT - // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work - // out well. Instantiating the nested apply template also - // requires instantiating iterator_traits on the - // placeholder. Instead we just specialize it as a metafunction - // class. +// Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work +// out well. Instantiating the nested apply template also +// requires instantiating iterator_traits on the +// placeholder. Instead we just specialize it as a metafunction +// class. template <> - struct access_category - { - template - struct apply : access_category - {}; - }; - - template <> - struct traversal_category - { - template - struct apply : traversal_category - {}; - }; -# endif - -# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - - template - struct access_category - : mpl::if_< - is_const - , readable_lvalue_iterator_tag - , writable_lvalue_iterator_tag> - { - }; - - template - struct traversal_category - { - typedef random_access_traversal_tag type; - }; - -# endif - - template - struct iterator_tag - : detail::iterator_tag_base< - typename detail::max_known_access_tag::type - , typename detail::max_known_traversal_tag::type - >::type - { - typedef AccessTag access; - typedef TraversalTag traversal; - }; - - namespace detail - { -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +struct iterator_traversal +{ template - struct is_boost_iterator_tag - : mpl::false_ {}; - - template - struct is_boost_iterator_tag > - : mpl::true_ {}; -# else - template - struct is_boost_iterator_tag - { - typedef char (&yes)[1]; - typedef char (&no)[2]; - - template - static yes test(mpl::identity >*); - static no test(...); - - static mpl::identity* inst; - BOOST_STATIC_CONSTANT(bool, value = sizeof(test(inst)) == sizeof(yes)); - typedef mpl::bool_ type; - }; + struct apply : iterator_traversal + {}; +}; +template <> +struct iterator_traversal + : iterator_traversal +{}; # endif - } } // namespace boost diff --git a/include/boost/iterator/iterator_concepts.hpp b/include/boost/iterator/iterator_concepts.hpp index 31dd265..c549999 100644 --- a/include/boost/iterator/iterator_concepts.hpp +++ b/include/boost/iterator/iterator_concepts.hpp @@ -15,16 +15,20 @@ #include #include -#include -#include -#include -#include -#include -#include // Use boost::detail::iterator_traits to work around some MSVC/Dinkumware problems. #include +#include +#include + +#include +#include +#include +#include + +#include + // Use boost/limits to work around missing limits headers on some compilers #include @@ -56,7 +60,6 @@ namespace boost_concepts { public: typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits::value_type value_type; typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits::reference reference; - typedef BOOST_DEDUCED_TYPENAME ::boost::access_category::type access_category; void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); @@ -64,8 +67,6 @@ namespace boost_concepts { boost::function_requires< boost::DefaultConstructibleConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); - reference r = *i; // or perhaps read(x) value_type v(r); boost::ignore_unused_variable_warning(v); @@ -73,19 +74,19 @@ namespace boost_concepts { Iterator i; }; - template + template < + typename Iterator + , typename ValueType = typename boost::detail::iterator_traits::value_type + > class WritableIteratorConcept { public: - typedef typename boost::access_category::type access_category; - + void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); boost::function_requires< boost::EqualityComparableConcept >(); boost::function_requires< boost::DefaultConstructibleConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); - *i = v; // a good alternative could be something like write(x, v) } ValueType v; @@ -95,11 +96,8 @@ namespace boost_concepts { template class SwappableIteratorConcept { public: - typedef typename boost::access_category::type access_category; void constraints() { - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); - std::iter_swap(i1, i2); } Iterator i1; @@ -107,25 +105,25 @@ namespace boost_concepts { }; template - class ReadableLvalueIteratorConcept { - public: - typedef typename boost::detail::iterator_traits::value_type value_type; - typedef typename boost::detail::iterator_traits::reference reference; - typedef typename boost::access_category::type access_category; + class ReadableLvalueIteratorConcept + { + public: + typedef typename boost::detail::iterator_traits::value_type value_type; + typedef typename boost::detail::iterator_traits::reference reference; - void constraints() { - boost::function_requires< ReadableIteratorConcept >(); + void constraints() + { + boost::function_requires< ReadableIteratorConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); - - typedef boost::mpl::or_< - boost::is_same, - boost::is_same > correct_reference; + typedef boost::mpl::or_< + boost::is_same + , boost::is_same + > correct_reference; - BOOST_STATIC_ASSERT(correct_reference::value); + BOOST_STATIC_ASSERT(correct_reference::value); - reference v = *i; - boost::ignore_unused_variable_warning(v); + reference v = *i; + boost::ignore_unused_variable_warning(v); } Iterator i; }; @@ -135,7 +133,6 @@ namespace boost_concepts { public: typedef typename boost::detail::iterator_traits::value_type value_type; typedef typename boost::detail::iterator_traits::reference reference; - typedef typename boost::access_category::type access_category; void constraints() { boost::function_requires< @@ -145,7 +142,6 @@ namespace boost_concepts { boost::function_requires< SwappableIteratorConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); BOOST_STATIC_ASSERT((boost::is_same::value)); } @@ -157,14 +153,19 @@ namespace boost_concepts { template class IncrementableIteratorConcept { public: - typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::iterator_traversal::type traversal_category; void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); boost::function_requires< boost::DefaultConstructibleConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + BOOST_STATIC_ASSERT( + (boost::is_convertible< + traversal_category + , boost::incrementable_traversal_tag + >::value + )); ++i; (void)i++; @@ -175,21 +176,26 @@ namespace boost_concepts { template class SinglePassIteratorConcept { public: - typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::iterator_traversal::type traversal_category; typedef typename boost::detail::iterator_traits::difference_type difference_type; void constraints() { boost::function_requires< IncrementableIteratorConcept >(); boost::function_requires< boost::EqualityComparableConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + BOOST_STATIC_ASSERT( + (boost::is_convertible< + traversal_category + , boost::single_pass_traversal_tag + >::value + )); } }; template class ForwardTraversalConcept { public: - typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::iterator_traversal::type traversal_category; typedef typename boost::detail::iterator_traits::difference_type difference_type; void constraints() { @@ -201,19 +207,29 @@ namespace boost_concepts { > difference_type_is_signed_integral; BOOST_STATIC_ASSERT(difference_type_is_signed_integral::value); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + BOOST_STATIC_ASSERT( + (boost::is_convertible< + traversal_category + , boost::forward_traversal_tag + >::value + )); } }; template class BidirectionalTraversalConcept { public: - typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::iterator_traversal::type traversal_category; void constraints() { boost::function_requires< ForwardTraversalConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + BOOST_STATIC_ASSERT( + (boost::is_convertible< + traversal_category + , boost::bidirectional_traversal_tag + >::value + )); --i; (void)i--; @@ -224,14 +240,19 @@ namespace boost_concepts { template class RandomAccessTraversalConcept { public: - typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::iterator_traversal::type traversal_category; typedef typename boost::detail::iterator_traits::difference_type difference_type; void constraints() { boost::function_requires< BidirectionalTraversalConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + BOOST_STATIC_ASSERT( + (boost::is_convertible< + traversal_category + , boost::random_access_traversal_tag + >::value + )); i += n; i = i + n; @@ -326,11 +347,11 @@ namespace detail class InteroperableConcept { public: - typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::iterator_traversal::type traversal_category; typedef typename boost::detail::iterator_traits::difference_type difference_type; - typedef typename boost::traversal_category::type + typedef typename boost::iterator_traversal::type const_traversal_category; typedef typename boost::detail::iterator_traits::difference_type const_difference_type; diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index 2ed5a16..79b2d3c 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -12,15 +12,17 @@ #include #include -#include #include + +#include #include #include +#include +#include +#include #include -#include - #include #include @@ -30,21 +32,7 @@ namespace boost { // This forward declaration is required for the friend declaration // in iterator_core_access - template class iterator_facade; - - // Used as a default template argument internally, merely to - // indicate "use the default", this can also be passed by users - // explicitly in order to specify that the default should be used. - struct use_default; - -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - // the incompleteness of use_default causes massive problems for - // is_convertible (naturally). This workaround is fortunately not - // needed for vc6/vc7. - template - struct is_convertible - : mpl::false_ {}; -# endif + template class iterator_facade; namespace detail { @@ -75,59 +63,30 @@ namespace boost #endif }; - // - // Add const qualification for iterators which are not writable - // - template - struct const_qualified_ref : - mpl::if_< is_tag< writable_iterator_tag, AccessCategory >, - Value&, - Value const& > - {}; - - // The apparent duplication here works around a Borland problem - template - struct const_qualified_ptr : - mpl::if_< is_tag< writable_iterator_tag, AccessCategory >, - Value*, - Value const* > - {}; - - // - // Generates the associated types for an iterator_facade with the - // given parameters. Additionally generates a 'base' type for - // compiler/library combinations which require user-defined - // iterators to inherit from std::iterator. + // Generates associated types for an iterator_facade with the + // given parameters. // template < - class Value - , class AccessCategory - , class TraversalCategory - , class Reference + class ValueParam + , class CategoryOrTraversal + , class Reference , class Difference > struct iterator_facade_types { - typedef iterator_tag iterator_category; - - typedef typename remove_cv::type value_type; - - typedef Difference difference_type; - - typedef typename const_qualified_ptr::type pointer; - - // The use_default support is needed for iterator_adaptor. - // For practical reasons iterator_adaptor needs to specify - // a fixed number of template arguments of iterator_facade. - // So use_default is its way to say: "What I really mean - // is your default parameter". - typedef typename mpl::if_< - is_same - , typename const_qualified_ref::type - , Reference - >::type reference; - + typedef typename facade_iterator_category< + CategoryOrTraversal, ValueParam, Reference + >::type iterator_category; + + typedef typename remove_const::type value_type; + + typedef typename mpl::apply_if< + detail::iterator_writability_disabled + , add_pointer::type> + , add_pointer + >::type pointer; + # if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \ || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \ @@ -141,7 +100,7 @@ namespace boost # define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1 typedef - iterator + iterator base; # endif }; @@ -205,10 +164,10 @@ namespace boost public: operator_brackets_proxy(Iterator const& iter) - : m_iter(iter) + : m_iter(iter) {} - operator reference() + operator reference() const { return *m_iter; } @@ -223,28 +182,24 @@ namespace boost Iterator m_iter; }; - template + template struct operator_brackets_result { - typedef typename access_category_tag::type access_category; - - typedef is_tag use_proxy; - typedef typename mpl::if_< - use_proxy + iterator_writability_disabled + , Value , operator_brackets_proxy - , ValueType >::type type; }; template - operator_brackets_proxy make_operator_brackets_result(Iterator const& iter, mpl::true_) + operator_brackets_proxy make_operator_brackets_result(Iterator const& iter, mpl::false_) { return operator_brackets_proxy(iter); } template - typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::false_) + typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::true_) { return *iter; } @@ -253,20 +208,20 @@ namespace boost // Macros which describe the declarations of binary operators -# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ - template < \ - class Derived1, class V1, class AC1, class TC1, class R1, class D1 \ - , class Derived2, class V2, class AC2, class TC2, class R2, class D2 \ - > \ - prefix typename detail::enable_if_interoperable< \ - Derived1, Derived2, result_type \ - >::type \ - operator op( \ - iterator_facade const& lhs \ - , iterator_facade const& rhs) +# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ + template < \ + class Derived1, class V1, class TC1, class R1, class D1 \ + , class Derived2, class V2, class TC2, class R2, class D2 \ + > \ + prefix typename detail::enable_if_interoperable< \ + Derived1, Derived2, result_type \ + >::type \ + operator op( \ + iterator_facade const& lhs \ + , iterator_facade const& rhs) -# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \ - template \ +# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \ + template \ prefix Derived operator+ args // @@ -286,8 +241,8 @@ namespace boost // to work in the absence of member template friends. public: # else - - template friend class iterator_facade; + + template friend class iterator_facade; # define BOOST_ITERATOR_FACADE_RELATION(op) \ BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, bool); @@ -306,8 +261,8 @@ namespace boost ; BOOST_ITERATOR_FACADE_PLUS_HEAD( - friend - , (iterator_facade const& + friend + , (iterator_facade const& , typename Derived::difference_type) ) ; @@ -315,7 +270,7 @@ namespace boost BOOST_ITERATOR_FACADE_PLUS_HEAD( friend , (typename Derived::difference_type - , iterator_facade const&) + , iterator_facade const&) ) ; @@ -370,26 +325,21 @@ namespace boost template < class Derived // The derived iterator type being constructed , class Value - , class AccessCategory - , class TraversalCategory - , class Reference = BOOST_DEDUCED_TYPENAME detail::const_qualified_ref::type + , class CategoryOrTraversal + , class Reference = Value& , class Difference = std::ptrdiff_t > class iterator_facade # ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE : public detail::iterator_facade_types< - Value, AccessCategory, TraversalCategory, Reference, Difference + Value, CategoryOrTraversal, Reference, Difference >::base # undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE # endif { private: - typedef typename - detail::iterator_facade_types - types; - // - // Curiously Recursive Template interface. + // Curiously Recurring Template interface. // typedef Derived derived_t; @@ -403,13 +353,17 @@ namespace boost return static_cast(*this); } + typedef detail::iterator_facade_types< + Value, CategoryOrTraversal, Reference, Difference + > associated_types; + public: - typedef typename types::value_type value_type; - typedef typename types::reference reference; - typedef typename types::difference_type difference_type; - typedef typename types::pointer pointer; - typedef typename types::iterator_category iterator_category; + typedef typename associated_types::value_type value_type; + typedef Reference reference; + typedef Difference difference_type; + typedef typename associated_types::pointer pointer; + typedef typename associated_types::iterator_category iterator_category; reference operator*() const { @@ -429,15 +383,17 @@ namespace boost , pointer >::make(*this->derived()); } - - typename detail::operator_brackets_result::type + + typename detail::operator_brackets_result::type operator[](difference_type n) const { - typedef typename - detail::operator_brackets_result::use_proxy - use_proxy; - - return detail::make_operator_brackets_result(this->derived() + n, use_proxy()); + typedef detail::iterator_writability_disabled + not_writable; + + return detail::make_operator_brackets_result( + this->derived() + n + , not_writable() + ); } Derived& operator++() @@ -615,13 +571,13 @@ namespace boost } BOOST_ITERATOR_FACADE_PLUS(( - iterator_facade const& i + iterator_facade const& i , typename Derived::difference_type n )) BOOST_ITERATOR_FACADE_PLUS(( typename Derived::difference_type n - , iterator_facade const& i + , iterator_facade const& i )) # undef BOOST_ITERATOR_FACADE_PLUS # undef BOOST_ITERATOR_FACADE_PLUS_HEAD diff --git a/include/boost/iterator/new_iterator_tests.hpp b/include/boost/iterator/new_iterator_tests.hpp index 759f8de..c16b826 100644 --- a/include/boost/iterator/new_iterator_tests.hpp +++ b/include/boost/iterator/new_iterator_tests.hpp @@ -24,15 +24,13 @@ # include // for detail::dummy_constructor # include # include +# include +# include + +# include namespace boost { -void is_readable(readable_iterator_tag) { } -void is_writable(writable_iterator_tag) { } -void is_swappable(swappable_iterator_tag) { } -void is_constant_lvalue(readable_lvalue_iterator_tag) { } -void is_mutable_lvalue(writable_lvalue_iterator_tag) { } - // Preconditions: *i == v template void readable_iterator_test(const Iterator i1, T v) @@ -45,8 +43,12 @@ void readable_iterator_test(const Iterator i1, T v) T v2 = r2; assert(v1 == v); assert(v2 == v); - typedef typename access_category::type result_category; - is_readable(result_category()); + +# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + // I think we don't really need this as it checks the same things as + // the above code. + BOOST_STATIC_ASSERT(is_readable_iterator::value); +# endif } template @@ -54,7 +56,6 @@ void writable_iterator_test(Iterator i, T v) { Iterator i2(i); // Copy Constructible *i2 = v; - is_writable(typename access_category::type()); } template @@ -65,8 +66,6 @@ void swappable_iterator_test(Iterator i, Iterator j) iter_swap(i2, j2); typename detail::iterator_traits::value_type ai = *i, aj = *j; assert(bi == aj && bj == ai); - typedef typename access_category::type result_category; - is_swappable(result_category()); } template @@ -78,12 +77,14 @@ void constant_lvalue_iterator_test(Iterator i, T v1) BOOST_STATIC_ASSERT((is_same::value)); const T& v2 = *i2; assert(v1 == v2); - typedef typename access_category::type result_category; - is_constant_lvalue(result_category()); +# ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!is_non_const_lvalue_iterator::value); +# endif } template -void mutable_lvalue_iterator_test(Iterator i, T v1, T v2) +void non_const_lvalue_iterator_test(Iterator i, T v1, T v2) { Iterator i2(i); typedef typename detail::iterator_traits::value_type value_type; @@ -91,11 +92,17 @@ void mutable_lvalue_iterator_test(Iterator i, T v1, T v2) BOOST_STATIC_ASSERT((is_same::value)); T& v3 = *i2; assert(v1 == v3); + + // A non-const lvalue iterator is not neccessarily writable, but we + // are assuming the value_type is assignable here *i = v2; + T& v4 = *i2; assert(v2 == v4); - typedef typename access_category::type result_category; - is_mutable_lvalue(result_category()); +# ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(is_non_const_lvalue_iterator::value); +# endif } template @@ -159,7 +166,6 @@ void bidirectional_readable_iterator_test(Iterator i, T v1, T v2) readable_iterator_test(i2, v2); } - // random access // Preconditions: [i,i+N) is a valid range template @@ -169,10 +175,12 @@ void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals) const Iterator j = i; int c; - for (c = 0; c < N-1; ++c) { + for (c = 0; c < N-1; ++c) + { assert(i == j + c); assert(*i == vals[c]); - assert(*i == j[c]); + typename detail::iterator_traits::value_type x = j[c]; + assert(*i == x); assert(*i == *(j + c)); assert(*i == *(c + j)); ++i; @@ -183,10 +191,12 @@ void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals) } Iterator k = j + N - 1; - for (c = 0; c < N-1; ++c) { + for (c = 0; c < N-1; ++c) + { assert(i == k - c); assert(*i == vals[N - 1 - c]); - assert(*i == j[N - 1 - c]); + typename detail::iterator_traits::value_type x = j[N - 1 - c]; + assert(*i == x); Iterator q = k - c; assert(*i == *q); assert(i > j); @@ -197,8 +207,8 @@ void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals) } } -// #if 0'd code snipped; see CVS v 1.4 if you need it back - } // namespace boost +# include + #endif // BOOST_NEW_ITERATOR_TESTS_HPP diff --git a/include/boost/iterator/transform_iterator.hpp b/include/boost/iterator/transform_iterator.hpp index cb41f07..3474ccf 100644 --- a/include/boost/iterator/transform_iterator.hpp +++ b/include/boost/iterator/transform_iterator.hpp @@ -24,6 +24,8 @@ #include #include +#include + namespace boost { template @@ -46,53 +48,38 @@ namespace boost }; #endif - // Given the transform iterator's transformation and iterator, this - // is the type used as its traits. + // Compute the iterator_adaptor instantiation to be used for transform_iterator template struct transform_iterator_base { - private: + private: + // By default, dereferencing the iterator yields the same as + // the function. Do we need to adjust the way + // function_object_result is computed for the standard + // proposal (e.g. using Doug's result_of)? + typedef typename ia_dflt_help< + Reference + , function_object_result + >::type reference; - // transform_iterator does not support writable/swappable iterators -#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - BOOST_STATIC_ASSERT((is_tag< readable_iterator_tag, typename access_category::type >::value)); -#endif - - typedef typename mpl::apply_if< - is_same< Reference, use_default > - , function_object_result - , mpl::identity - >::type result_type; + // To get the default for Value: remove any reference on the + // result type, but retain any constness to signal + // non-writability. Note that if we adopt Thomas' suggestion + // to key non-writability *only* on the Reference argument, + // we'd need to strip constness here as well. + typedef typename ia_dflt_help< + Value + , remove_reference + >::type cv_value_type; - typedef typename mpl::if_< - is_same< Value, use_default > - , typename remove_reference< result_type >::type - , Value - >::type cv_value_type; - - typedef typename mpl::if_< - is_reference< result_type > - , typename mpl::if_< - is_const< cv_value_type > - , readable_lvalue_iterator_tag - , writable_lvalue_iterator_tag - >::type - , readable_iterator_tag - >::type maximum_access_tag; - - typedef typename minimum_category< - maximum_access_tag - , typename access_category::type - >::type access_category; - - public: - typedef iterator_adaptor< - transform_iterator - , Iterator - , cv_value_type - , access_category - , result_type - > type; + public: + typedef iterator_adaptor< + transform_iterator + , Iterator + , cv_value_type + , use_default // Leave the traversal category alone + , reference + > type; }; } @@ -150,12 +137,16 @@ namespace boost return transform_iterator(it, fun); } + // Version which allows explicit specification of the UnaryFunction + // type. + // + // This generator is not provided if UnaryFunction is a function + // pointer type, because it's too dangerous: the default-constructed + // function pointer in the iterator be 0, leading to a runtime + // crash. template - // don't provide this generator if UnaryFunction is a - // function pointer type. Too dangerous. We should probably - // find a cheaper test than is_class<> typename iterators::enable_if< - is_class + is_class // We should probably find a cheaper test than is_class<> , transform_iterator >::type make_transform_iterator(Iterator it) @@ -174,4 +165,6 @@ namespace boost } // namespace boost +#include + #endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP diff --git a/include/boost/iterator/zip_iterator.hpp b/include/boost/iterator/zip_iterator.hpp index 943a347..f48ee53 100755 --- a/include/boost/iterator/zip_iterator.hpp +++ b/include/boost/iterator/zip_iterator.hpp @@ -28,6 +28,8 @@ #include #include +#include + #include #if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407) @@ -259,16 +261,17 @@ namespace boost { ) { typedef typename tuple_meta_transform< - typename Tuple::tail_type + BOOST_DEDUCED_TYPENAME Tuple::tail_type , Fun >::type transformed_tail_type; return tuples::cons< - typename mpl::apply1::type + BOOST_DEDUCED_TYPENAME mpl::apply1< + Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type + >::type , transformed_tail_type >( - f(boost::tuples::get<0>(t)), - tuple_transform(t.get_tail(), f) + f(boost::tuples::get<0>(t)), tuple_transform(t.get_tail(), f) ); } @@ -380,12 +383,12 @@ namespace boost { { typedef typename tuple_impl_specific::tuple_meta_transform< IteratorTuple - , traversal_category + , iterator_traversal<> >::type tuple_of_traversal_tags; typedef typename tuple_impl_specific::tuple_meta_accumulate< tuple_of_traversal_tags - , minimum_category + , minimum_category<> , random_access_traversal_tag >::type type; }; @@ -398,31 +401,6 @@ namespace boost { }; #endif - template - struct iterator_is_readable - : is_tag< - readable_iterator_tag - , typename access_category::type - > - { - BOOST_MPL_AUX_LAMBDA_SUPPORT(1, iterator_is_readable, (Iterator)) - }; - -# ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT - // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work - // out well. Instantiating the nested apply template also - // requires instantiating iterator_traits on the - // placeholder. Instead we just specialize it as a metafunction - // class. - template <> - struct iterator_is_readable - { - template - struct apply : iterator_is_readable - {}; - }; -# endif - // We need to call tuple_meta_accumulate with mpl::and_ as the // accumulating functor. To this end, we need to wrap it into // a struct that has exactly two arguments (that is, template @@ -446,28 +424,6 @@ namespace boost { }; # endif - // Metafunction to assert that all iterators in a tuple are - // readable. - // - // Probably not worth it, IMO. Why not a writable zip_iterator - // anyway? -- dwa. - // - template - struct all_iterators_in_tuple_readable - { - - typedef typename tuple_impl_specific::tuple_meta_transform< - IteratorTuple, - iterator_is_readable - >::type tuple_of_readability_bools; - - typedef typename tuple_impl_specific::tuple_meta_accumulate< - tuple_of_readability_bools, - and_with_two_args - , mpl::bool_ - >::type type; - }; - /////////////////////////////////////////////////////////////////// // // Class zip_iterator_base @@ -479,14 +435,6 @@ namespace boost { struct zip_iterator_base { private: -#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - // seems to give vc7's parser fits, and vc6 needs help here too - BOOST_STATIC_ASSERT( - detail::all_iterators_in_tuple_readable< - IteratorTuple - >::type::value - ); -#endif // Reference type is the type of the tuple obtained from the // iterators' reference types. typedef typename @@ -506,11 +454,6 @@ namespace boost { detail::minimum_traversal_category_in_iterator_tuple< IteratorTuple >::type traversal_category; - - // Access category is readable_iterator_tag. It has been - // asserted that all iterators in the tuple are readable. - typedef readable_iterator_tag access_category; - public: // The iterator facade type from which the zip iterator will @@ -518,7 +461,6 @@ namespace boost { typedef iterator_facade< zip_iterator, value_type, - access_category, traversal_category, reference, difference_type @@ -616,7 +558,7 @@ namespace boost { { detail::tuple_impl_specific::tuple_for_each( m_iterator_tuple, - detail::advance_iterator(n) + detail::advance_iterator(n) ); } // Incrementing a zip iterator means to increment all iterators in diff --git a/test/Jamfile b/test/Jamfile index 1a7b9a1..94a46d3 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -18,6 +18,8 @@ test-suite iterator # compilation problems. [ run is_convertible_fail.cpp ] + [ run zip_iterator_test.cpp ] + # These tests should work for just about everything. [ compile is_lvalue_iterator.cpp ] [ compile is_readable_iterator.cpp ] @@ -34,8 +36,6 @@ test-suite iterator [ run counting_iterator_test.cpp ] [ run permutation_iterator_test.cpp : : : # on ] - [ compile iterator_categories.cpp ] - [ run zip_iterator_test.cpp ] [ run ../../utility/iterator_adaptor_examples.cpp ] [ run ../../utility/counting_iterator_example.cpp ] diff --git a/test/concept_tests.cpp b/test/concept_tests.cpp index 5370f76..399911d 100644 --- a/test/concept_tests.cpp +++ b/test/concept_tests.cpp @@ -5,15 +5,16 @@ // to its suitability for any purpose. #include +#include #include -#include // remove -#include -#include "static_assert_same.hpp" // remove + +struct new_random_access + : std::random_access_iterator_tag + , boost::random_access_traversal_tag +{}; struct new_iterator - : public boost::iterator< boost::iterator_tag< - boost::writable_lvalue_iterator_tag - , boost::random_access_traversal_tag>, int> + : public boost::iterator< new_random_access, int > { int& operator*() const { return *m_x; } new_iterator& operator++() { return *this; } @@ -52,103 +53,13 @@ struct old_iterator }; old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; } -struct my_writable_lvalue_iterator_tag -{ - operator boost::writable_lvalue_iterator_tag() const; -}; - -struct my_single_pass_traversal_tag -{ - operator boost::single_pass_traversal_tag() const; -}; - -void test_tag_convertibility() -{ - // This set of tests is by no means complete. - - // Test that this is an input/output iterator -#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) - { - typedef boost::iterator_tag< - boost::writable_lvalue_iterator_tag - , boost::single_pass_traversal_tag - > tag; - - BOOST_STATIC_ASSERT(( - boost::is_convertible::value - )); - BOOST_STATIC_ASSERT(( - boost::is_convertible::value - )); - BOOST_STATIC_ASSERT(( - !boost::is_convertible::value - )); - } - - // Test that it's possible to build new sub-tags without - // derivation. Convertibility should be enough - { - typedef boost::iterator_tag< - my_writable_lvalue_iterator_tag - , my_single_pass_traversal_tag - > tag; - - BOOST_STATIC_ASSERT(( - boost::is_convertible::value - )); - BOOST_STATIC_ASSERT(( - boost::is_convertible::value - )); - BOOST_STATIC_ASSERT(( - !boost::is_convertible::value - )); - } - - // Test that a single-pass readable lvalue iterator is only an - // input iterator. Requires special case handling in - // categories.hpp - { - typedef boost::iterator_tag< - boost::readable_lvalue_iterator_tag - , boost::single_pass_traversal_tag - > tag; - BOOST_STATIC_ASSERT(( - boost::is_convertible::value - )); - BOOST_STATIC_ASSERT(( - !boost::is_convertible::value - )); - BOOST_STATIC_ASSERT(( - !boost::is_convertible::value - )); - } -#endif -} - int main() { - test_tag_convertibility(); - - typedef boost::iterator_tag< boost::writable_lvalue_iterator_tag, boost::random_access_traversal_tag > tag; - - // BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator::value)); - int test = static_assert_same::value; - test = static_assert_same::value; - - // BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator::value)); - test = static_assert_same::value; - test = static_assert_same::value; - - typedef boost::traversal_category::type traversal_category; - - // BOOST_STATIC_ASSERT(boost::detail::has_traversal::value); - BOOST_STATIC_ASSERT(boost::detail::is_new_iterator_tag::value); - - - test = static_assert_same::value; - (void)test; - + boost::iterator_traversal::type tc; + boost::random_access_traversal_tag derived = tc; + (void)derived; + boost::function_requires< boost_concepts::WritableLvalueIteratorConcept >(); boost::function_requires< diff --git a/test/counting_iterator_test.cpp b/test/counting_iterator_test.cpp index fbfe70b..73f69f9 100644 --- a/test/counting_iterator_test.cpp +++ b/test/counting_iterator_test.cpp @@ -286,7 +286,7 @@ int main() # ifndef BOOST_NO_SLIST test_container >(); # endif - + // Also prove that we can handle raw pointers. int array[2000]; test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1)); diff --git a/test/filter_iterator_test.cpp b/test/filter_iterator_test.cpp index a00af95..edf3ccf 100644 --- a/test/filter_iterator_test.cpp +++ b/test/filter_iterator_test.cpp @@ -7,13 +7,12 @@ #include #include #include -#include +#include #include #include using boost::dummyT; -BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT) struct one_or_four { @@ -38,12 +37,12 @@ int main() filter_iter(one_or_four(), array, array+N) , dummyT(1), dummyT(4)); - BOOST_STATIC_ASSERT(( - !boost::detail::is_tag< - boost::random_access_traversal_tag - , boost::traversal_category::type - >::value - )); + BOOST_STATIC_ASSERT( + (!boost::is_convertible< + boost::iterator_traversal::type + , boost::random_access_traversal_tag + >::value + )); //# endif diff --git a/test/indirect_iterator_test.cpp b/test/indirect_iterator_test.cpp index 3f28948..cad4091 100644 --- a/test/indirect_iterator_test.cpp +++ b/test/indirect_iterator_test.cpp @@ -46,8 +46,7 @@ struct my_iterator_tag : public std::random_access_iterator_tag { }; using boost::dummyT; -BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT) -BOOST_TT_BROKEN_COMPILER_SPEC(boost::shared_ptr) +BOOST_TT_BROKEN_COMPILER_SPEC(boost::shared_ptr) typedef std::vector storage; typedef std::vector pointer_ra_container; diff --git a/test/is_lvalue_iterator.cpp b/test/is_lvalue_iterator.cpp index 9c23c9c..fdace52 100755 --- a/test/is_lvalue_iterator.cpp +++ b/test/is_lvalue_iterator.cpp @@ -32,12 +32,15 @@ struct noncopyable_iterator : boost::iterator +template +struct proxy_iterator + : boost::iterator { + typedef T value_type; + #if BOOST_WORKAROUND(__GNUC__, == 2) - typedef boost::iterator base; + typedef boost::iterator base; typedef base::iterator_category iterator_category; - typedef base::value_type value_type; typedef base::difference_type difference_type; typedef base::pointer pointer; typedef base::reference reference; @@ -45,14 +48,43 @@ struct proxy_iterator : boost::iterator struct proxy { - operator v&() const; - proxy& operator=(v) const; + operator value_type&() const; + proxy& operator=(value_type) const; }; proxy operator*() const; }; -BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator::proxy) +template +struct lvalue_iterator +{ + typedef T value_type; + typedef T& reference; + typedef T difference_type; + typedef std::input_iterator_tag iterator_category; + typedef T* pointer; + + T& operator*() const; + lvalue_iterator& operator++(); + lvalue_iterator operator++(int); +}; + +template +struct constant_lvalue_iterator +{ + typedef T value_type; + typedef T const& reference; + typedef T difference_type; + typedef std::input_iterator_tag iterator_category; + typedef T const* pointer; + + T const& operator*() const; + constant_lvalue_iterator& operator++(); + constant_lvalue_iterator operator++(int); +}; + +BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator::proxy) +BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator::proxy) int main() { @@ -62,7 +94,8 @@ int main() BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::const_iterator>::value); BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator > >::value); BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator >::value); - BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator >::value); #ifndef BOOST_NO_LVALUE_RETURN_DETECTION BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator::value); #endif @@ -70,18 +103,43 @@ int main() // reference binding BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + - BOOST_STATIC_ASSERT(boost::is_mutable_lvalue_iterator::value); - BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::value); - BOOST_STATIC_ASSERT(boost::is_mutable_lvalue_iterator::iterator>::value); - BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::const_iterator>::value); - BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator > >::value); - BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator >::value); - BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + + + + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator::iterator>::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator::const_iterator>::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator > >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); #ifndef BOOST_NO_LVALUE_RETURN_DETECTION - BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator::value); #endif - BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator::value); + + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator >::value); +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator >::value); +#endif + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator >::value); + + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); return 0; } diff --git a/test/iterator_adaptor_test.cpp b/test/iterator_adaptor_test.cpp index 79b9001..961895f 100644 --- a/test/iterator_adaptor_test.cpp +++ b/test/iterator_adaptor_test.cpp @@ -14,6 +14,10 @@ #include #include +#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) +# include +# include +#endif #include # include @@ -26,7 +30,7 @@ #include "static_assert_same.hpp" -struct my_iterator_tag : public std::random_access_iterator_tag { }; +#include using boost::dummyT; @@ -83,7 +87,7 @@ struct ptr_iterator ptr_iterator , V* , V - , std::random_access_iterator_tag + , boost::random_access_traversal_tag #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) , V& #endif @@ -94,7 +98,7 @@ private: ptr_iterator , V* , V - , std::random_access_iterator_tag + , boost::random_access_traversal_tag #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) , V& #endif @@ -114,13 +118,13 @@ public: }; // Non-functional iterator for category modification checking -template -struct modify_category +template +struct modify_traversal : boost::iterator_adaptor< - modify_category + modify_traversal , Iter , boost::use_default - , Category + , Traversal > {}; @@ -179,6 +183,33 @@ struct constant_iterator : base_t(it) {} }; +char (& traversal2(boost::incrementable_traversal_tag) )[1]; +char (& traversal2(boost::single_pass_traversal_tag ) )[2]; +char (& traversal2(boost::forward_traversal_tag ) )[3]; +char (& traversal2(boost::bidirectional_traversal_tag) )[4]; +char (& traversal2(boost::random_access_traversal_tag) )[5]; + +template +struct traversal3 +{ + static typename boost::iterator_category_to_traversal::type x; + BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(traversal2(x))); + typedef char (&type)[value]; +}; + +template +typename traversal3::type traversal(Cat); + +template +int static_assert_traversal(Iter* = 0, Trav* = 0) +{ + typedef typename boost::iterator_category_to_traversal< + BOOST_DEDUCED_TYPENAME Iter::iterator_category + >::type t2; + + return static_assert_same::value; +} + int main() { @@ -219,7 +250,17 @@ main() typedef ptr_iterator Iter1; test = static_assert_same::value; test = static_assert_same::value; - test = static_assert_same::value; test = static_assert_same::value; + +#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + BOOST_STATIC_ASSERT(boost::is_readable_iterator::value); +# ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::value); +# endif +#endif + +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness + test = static_assert_same::value; +#endif } { @@ -229,19 +270,19 @@ main() test = static_assert_same::value; test = static_assert_same::value; +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness test = static_assert_same::value; +#endif - test = static_assert_same::value; - test = static_assert_same::value; - - // Test category modification - typedef modify_category ReadableIter; - test = static_assert_same::value; - - typedef modify_category IncrementableIter; - test = static_assert_same::value; - test = static_assert_same::value; +#ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::value); +#endif + + typedef modify_traversal IncrementableIter; + static_assert_traversal(); + static_assert_traversal(); } // Test the iterator_adaptor diff --git a/test/iterator_archetype_cc.cpp b/test/iterator_archetype_cc.cpp index 1edf5e5..b5badea 100644 --- a/test/iterator_archetype_cc.cpp +++ b/test/iterator_archetype_cc.cpp @@ -12,14 +12,15 @@ int main() { - { - typedef boost::iterator_archetype iter; + typedef boost::iterator_archetype< + int + , boost::iterator_archetypes::writable_lvalue_iterator_t + , boost::random_access_traversal_tag + > iter; boost::function_requires< boost_concepts::WritableLvalueIteratorConcept >(); boost::function_requires< boost_concepts::RandomAccessTraversalConcept >(); - } - return 0; // keep msvc happy + + return 0; // keep msvc happy } diff --git a/test/iterator_categories.cpp b/test/iterator_categories.cpp deleted file mode 100755 index e36f2c9..0000000 --- a/test/iterator_categories.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright David Abrahams 2003. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include - -using namespace boost; - -// Utility function which converts an iterator_category into a -// traversal tag -template -typename iterator_category_to_traversal::type c2t(C) -{ - typedef typename iterator_category_to_traversal::type result; - return result(); -} - -struct v -{ - v(); - ~v(); -}; - -// -// Test conversions from iterator_tag<...> to old-style iterator categories -// - -// These "solid" tag types ensure exact matching of iterator -// classification, because unlike the std:: iterator tags, they're not -// inter-convertible -struct output_iter {}; -struct input_iter {}; -struct input_output_iter {}; -struct forward_iter {}; -struct bidirectional_iter {}; -struct random_access_iter{} ; - -// Convert various old-style categories into "solid" tags. -input_iter cat(std::input_iterator_tag); -output_iter cat(std::output_iterator_tag); -input_output_iter cat(boost::detail::input_output_iterator_tag); -forward_iter cat(std::forward_iterator_tag); -bidirectional_iter cat(std::bidirectional_iterator_tag); -random_access_iter cat(std::random_access_iterator_tag); - -random_access_iter x1 = cat(iterator_tag()); -random_access_iter x2 = cat(iterator_tag()); -bidirectional_iter x3 = cat(iterator_tag()); -forward_iter x4 = cat(iterator_tag()); -input_output_iter x5 = cat(iterator_tag()); -input_iter x6 = cat(iterator_tag()); -output_iter x7 = cat(iterator_tag()); - - -// -// Test conversion from old-style iterator categories to traversal categories -// - -// These "solid" tag types ensure exact matching of iterator -// classification, because unlike the traversal tags, they're not -// inter-convertible -struct incrementable_traversal {}; -struct single_pass_traversal {}; -struct forward_traversal {}; -struct bidirectional_traversal {}; -struct random_access_traversal {} ; - -// Convert various traversal categories into "solid" tags -incrementable_traversal trav(incrementable_traversal_tag); -single_pass_traversal trav(single_pass_traversal_tag); -forward_traversal trav(forward_traversal_tag); -bidirectional_traversal trav(bidirectional_traversal_tag); -random_access_traversal trav(random_access_traversal_tag); - -// Show that full types of tags that are already traversal categories -// are preserved -iterator_tag yz1 - = c2t(iterator_tag()); - -// Test traversal extraction from both old-style and new-style tags -random_access_traversal yy1 = trav(c2t(iterator_tag())); -bidirectional_traversal yy2 = trav(c2t(iterator_tag())); -forward_traversal yy3 = trav(c2t(iterator_tag())); -single_pass_traversal yy4 = trav(c2t(iterator_tag())); -incrementable_traversal yy5 = trav(c2t(iterator_tag())); - -random_access_traversal z1 = trav(c2t(std::random_access_iterator_tag())); -bidirectional_traversal z2 = trav(c2t(std::bidirectional_iterator_tag())); -forward_traversal z3 = trav(c2t(std::forward_iterator_tag())); -single_pass_traversal z4 = trav(c2t(std::input_iterator_tag())); -incrementable_traversal z5 = trav(c2t(std::output_iterator_tag())); diff --git a/test/reverse_iterator_test.cpp b/test/reverse_iterator_test.cpp index cb069cd..62e1454 100644 --- a/test/reverse_iterator_test.cpp +++ b/test/reverse_iterator_test.cpp @@ -11,8 +11,6 @@ using boost::dummyT; -BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT) - // Test reverse iterator int main() { diff --git a/test/static_assert_same.hpp b/test/static_assert_same.hpp index 3bff6bf..e463192 100644 --- a/test/static_assert_same.hpp +++ b/test/static_assert_same.hpp @@ -10,13 +10,17 @@ #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template -struct static_assert_same; +struct static_assert_same_base; template -struct static_assert_same +struct static_assert_same_base { enum { value = 1 }; }; + +template +struct static_assert_same : static_assert_same_base {}; + #else # include # include diff --git a/test/transform_iterator_test.cpp b/test/transform_iterator_test.cpp index cc73846..f044add 100644 --- a/test/transform_iterator_test.cpp +++ b/test/transform_iterator_test.cpp @@ -184,17 +184,14 @@ main() for (int k2 = 0; k2 < N; ++k2) x[k2] = x[k2] * 2; - boost::input_iterator_test(boost::make_transform_iterator(y, mult_2) - , x[0] - , x[1]); + boost::input_iterator_test( + boost::make_transform_iterator(y, mult_2), x[0], x[1]); - boost::input_iterator_test(boost::make_transform_iterator(&y[0], mult_2) - , x[0] - , x[1]); + boost::input_iterator_test( + boost::make_transform_iterator(&y[0], mult_2), x[0], x[1]); - boost::random_access_readable_iterator_test(boost::make_transform_iterator(y, mult_2) - , N - , x); + boost::random_access_readable_iterator_test( + boost::make_transform_iterator(y, mult_2), N, x); } @@ -213,25 +210,34 @@ main() } - std::copy(x, - x + N, - boost::make_transform_iterator((pair_t*)values, select_first())); + std::copy( + x + , x + N + , boost::make_transform_iterator((pair_t*)values, select_first()) + ); - std::copy(y, - y + N, - boost::make_transform_iterator((pair_t*)values, select_second())); + std::copy( + y + , y + N + , boost::make_transform_iterator((pair_t*)values, select_second()) + ); - boost::random_access_readable_iterator_test(boost::make_transform_iterator((pair_t*)values, value_select_first()), - N, - x); + boost::random_access_readable_iterator_test( + boost::make_transform_iterator((pair_t*)values, value_select_first()) + , N + , x + ); - boost::random_access_readable_iterator_test(boost::make_transform_iterator((pair_t*)values, const_select_first()), - N, - x); + boost::random_access_readable_iterator_test( + boost::make_transform_iterator((pair_t*)values, const_select_first()) + , N, x + ); - boost::constant_lvalue_iterator_test(boost::make_transform_iterator((pair_t*)values, const_select_first()), x[0]); + boost::constant_lvalue_iterator_test( + boost::make_transform_iterator((pair_t*)values, const_select_first()), x[0]); - boost::mutable_lvalue_iterator_test(boost::make_transform_iterator((pair_t*)values, select_first()), x[0], 17); + boost::non_const_lvalue_iterator_test( + boost::make_transform_iterator((pair_t*)values, select_first()), x[0], 17); } diff --git a/test/unit_tests.cpp b/test/unit_tests.cpp index ed6c279..c4077eb 100644 --- a/test/unit_tests.cpp +++ b/test/unit_tests.cpp @@ -5,9 +5,12 @@ // to its suitability for any purpose. #include #include + #include "static_assert_same.hpp" + #include +#include struct X { int a; }; @@ -40,29 +43,32 @@ void category_test() using namespace boost::detail; BOOST_STATIC_ASSERT(( - !is_tag< - input_output_iterator_tag - , std::input_iterator_tag>::value)); - - BOOST_STATIC_ASSERT(( - !is_tag< - input_output_iterator_tag - , std::output_iterator_tag>::value)); - - BOOST_STATIC_ASSERT(( - is_tag< + !boost::is_convertible< std::input_iterator_tag , input_output_iterator_tag>::value)); BOOST_STATIC_ASSERT(( - is_tag< + !boost::is_convertible< std::output_iterator_tag , input_output_iterator_tag>::value)); - + BOOST_STATIC_ASSERT(( - is_tag< + boost::is_convertible< input_output_iterator_tag - , std::forward_iterator_tag>::value)); + , std::input_iterator_tag>::value)); + + BOOST_STATIC_ASSERT(( + boost::is_convertible< + input_output_iterator_tag + , std::output_iterator_tag>::value)); + +#if 0 // This seems wrong; we're not advertising + // input_output_iterator_tag are we? + BOOST_STATIC_ASSERT(( + boost::is_convertible< + std::forward_iterator_tag + , input_output_iterator_tag>::value)); +#endif int test = static_assert_min_cat< std::input_iterator_tag,input_output_iterator_tag, std::input_iterator_tag @@ -72,9 +78,11 @@ void category_test() input_output_iterator_tag,std::input_iterator_tag, std::input_iterator_tag >::value; +#if 0 test = static_assert_min_cat< input_output_iterator_tag,std::forward_iterator_tag, input_output_iterator_tag >::value; +#endif test = static_assert_min_cat< std::input_iterator_tag,std::forward_iterator_tag, std::input_iterator_tag @@ -84,29 +92,13 @@ void category_test() std::input_iterator_tag,std::random_access_iterator_tag, std::input_iterator_tag >::value; +#if 0 // This would be wrong: a random access iterator is not + // neccessarily writable, as is an output iterator. test = static_assert_min_cat< std::output_iterator_tag,std::random_access_iterator_tag, std::output_iterator_tag >::value; +#endif - BOOST_STATIC_ASSERT((is_traversal_tag< incrementable_traversal_tag >::value)); - BOOST_STATIC_ASSERT((is_traversal_tag< single_pass_traversal_tag >::value)); - BOOST_STATIC_ASSERT((is_traversal_tag< forward_traversal_tag >::value)); - BOOST_STATIC_ASSERT((is_traversal_tag< bidirectional_traversal_tag >::value)); - BOOST_STATIC_ASSERT((is_traversal_tag< random_access_traversal_tag >::value)); - - BOOST_STATIC_ASSERT((!is_traversal_tag< std::input_iterator_tag >::value)); - BOOST_STATIC_ASSERT((!is_traversal_tag< readable_iterator_tag >::value)); - - BOOST_STATIC_ASSERT((is_access_tag< readable_iterator_tag >::value)); - BOOST_STATIC_ASSERT((is_access_tag< writable_iterator_tag >::value)); - BOOST_STATIC_ASSERT((is_access_tag< swappable_iterator_tag >::value)); - BOOST_STATIC_ASSERT((is_access_tag< readable_writable_iterator_tag >::value)); - BOOST_STATIC_ASSERT((is_access_tag< readable_lvalue_iterator_tag >::value)); - BOOST_STATIC_ASSERT((is_access_tag< writable_lvalue_iterator_tag >::value)); - - BOOST_STATIC_ASSERT((!is_access_tag< std::input_iterator_tag >::value)); - BOOST_STATIC_ASSERT((!is_access_tag< incrementable_traversal_tag >::value)); - (void)test; } diff --git a/test/zip_iterator_test.cpp b/test/zip_iterator_test.cpp index d6fcc2b..f33dbd9 100755 --- a/test/zip_iterator_test.cpp +++ b/test/zip_iterator_test.cpp @@ -48,32 +48,18 @@ #include #include #include +#include #include #include #include -// Uncomment to see static assert. -// #define PROVOKE_STATIC_ASSERT - -///////////////////////////////////////////////////////////////////////////// -// -// Fake iterator for testing zip iterator categories -// -///////////////////////////////////////////////////////////////////////////// - -class fake_writable_iterator -{ -public: - typedef int& reference; - typedef int value_type; - typedef int* pointer; - typedef ptrdiff_t difference_type; - typedef boost::iterator_tag< - boost::writable_iterator_tag, - boost::forward_traversal_tag - > iterator_category; -}; - +template +struct pure_traversal + : boost::detail::pure_traversal_tag< + typename boost::iterator_traversal::type + > +{}; + ///////////////////////////////////////////////////////////////////////////// // // Das Main Funktion @@ -871,25 +857,15 @@ int main( void ) // The big iterator of the previous test has vector, list, and set iterators. // Therefore, it must be bidirectional, but not random access. - bool bBigItIsBidirectionalIterator = boost::is_same< - boost::bidirectional_traversal_tag, - boost::traversal_category::type - >::value; - // - bool bBigItIsRandomAccessIterator = boost::is_same< - boost::random_access_traversal_tag, - boost::traversal_category::type - >::value; - // - bool bBigItIsReadableIterator = boost::is_same< - boost::readable_iterator_tag, - boost::access_category::type - >::value; - // - bool bBigItIsReadableLValueIterator = boost::is_same< - boost::readable_lvalue_iterator_tag, - boost::access_category::type - >::value; + bool bBigItIsBidirectionalIterator = boost::is_convertible< + boost::iterator_traversal::type + , boost::bidirectional_traversal_tag + >::value; + + bool bBigItIsRandomAccessIterator = boost::is_convertible< + boost::iterator_traversal::type + , boost::random_access_traversal_tag + >::value; // A combining iterator with all vector iterators must have random access // traversal. @@ -901,63 +877,15 @@ int main( void ) > > all_vects_type; - bool bAllVectsIsRandomAccessIterator = boost::is_same< - boost::random_access_traversal_tag, - boost::traversal_category::type + bool bAllVectsIsRandomAccessIterator = boost::is_convertible< + boost::iterator_traversal::type + , boost::random_access_traversal_tag >::value; - // - bool bAllVectsIsReadableIterator = boost::is_same< - boost::readable_iterator_tag, - boost::access_category::type - >::value; - // - bool bAllVectsIsReadableLValueIterator = boost::is_same< - boost::readable_lvalue_iterator_tag, - boost::access_category::type - >::value; - - // Test if the meta function all_iterators_readable, which is used - // for compile-time asserting, works. - // - bool bAllIteratorsReadable1 = - boost::detail::all_iterators_in_tuple_readable< - boost::tuples::tuple< - std::vector::const_iterator, - std::set::iterator - > - >::type::value; - - bool bAllIteratorsReadable2 = - boost::detail::all_iterators_in_tuple_readable< - boost::tuples::tuple< - std::vector::const_iterator, - fake_writable_iterator, - std::set::iterator - > - >::type::value; - - // Compile-time assert because of non-readable iterator. - // -#ifdef PROVOKE_STATIC_ASSERT - typedef boost::zip_iterator< - boost::tuples::tuple< - fake_writable_iterator - > - >no_compile_type; - - no_compile_type no_compile; -#endif // The big test. if( bBigItIsBidirectionalIterator && ! bBigItIsRandomAccessIterator && - bBigItIsReadableIterator && - ! bBigItIsReadableLValueIterator && - bAllVectsIsRandomAccessIterator && - ! bAllVectsIsReadableLValueIterator && - bAllVectsIsReadableIterator && - bAllIteratorsReadable1 && - ! bAllIteratorsReadable2 + bAllVectsIsRandomAccessIterator ) { ++num_successful_tests; @@ -977,6 +905,6 @@ int main( void ) << "\nNumber of failed tests: " << static_cast(num_failed_tests) << std::endl; - return 0; + return num_failed_tests; } From f6715137cfc99e32fb72973a6ac20cd4053ced09 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 22 Nov 2003 03:20:17 +0000 Subject: [PATCH 261/265] vc6 workaround [SVN r20906] --- include/boost/iterator/detail/minimum_category.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/boost/iterator/detail/minimum_category.hpp b/include/boost/iterator/detail/minimum_category.hpp index b1fcd9f..50fe6f5 100755 --- a/include/boost/iterator/detail/minimum_category.hpp +++ b/include/boost/iterator/detail/minimum_category.hpp @@ -58,9 +58,15 @@ template <> struct minimum_category_impl { template struct apply +# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) + { + typedef void type; + }; +# else : error_not_related_by_convertibility { }; +# endif }; template From dfc09c4b2611e96ebafa3e8a8de859057adf3e14 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 22 Nov 2003 13:57:57 +0000 Subject: [PATCH 262/265] Make sure a precise copy of n1550 is in the CVS. [SVN r20908] --- doc/new-iter-concepts.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 07b8595..17f65ab 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -8,7 +8,7 @@ Systems Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:Number: N1530=03-0133 +:Number: N1550=03-0133 :copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com @@ -157,7 +157,7 @@ Changes to Algorithm Requirements For the next working paper (but not for TR1), the committee should consider the following changes to the type requirements of -algorithms. These changes are phrased as textual +algorithms. These changes are phrased as phrased as textual substitutions, listing the algorithms to which each textual substitution applies. From b63814d3f21c2f1fb27ab1ae69618644364a841f Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 23 Nov 2003 17:07:04 +0000 Subject: [PATCH 263/265] Check *implicit* convertibility from reference to value [SVN r20925] --- include/boost/iterator/iterator_concepts.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/iterator/iterator_concepts.hpp b/include/boost/iterator/iterator_concepts.hpp index c549999..76b75a5 100644 --- a/include/boost/iterator/iterator_concepts.hpp +++ b/include/boost/iterator/iterator_concepts.hpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -68,7 +69,8 @@ namespace boost_concepts { boost::DefaultConstructibleConcept >(); reference r = *i; // or perhaps read(x) - value_type v(r); + value_type v = r; + value_type v2 = *i; boost::ignore_unused_variable_warning(v); } Iterator i; From ca1ee306b7db7220829ef7701101195eafcbb12e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 23 Nov 2003 17:07:36 +0000 Subject: [PATCH 264/265] Remove bogus check for use_default [SVN r20926] --- include/boost/iterator/detail/facade_iterator_category.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/boost/iterator/detail/facade_iterator_category.hpp b/include/boost/iterator/detail/facade_iterator_category.hpp index 9b2aa1a..f5b1d4b 100755 --- a/include/boost/iterator/detail/facade_iterator_category.hpp +++ b/include/boost/iterator/detail/facade_iterator_category.hpp @@ -104,10 +104,8 @@ struct iterator_facade_default_category mpl::and_< is_convertible - , mpl::or_< // check for readability - is_same - , is_convertible - > + // check for readability + , is_convertible > , mpl::if_< iterator_writability_disabled From 09ea8d27e2e3c6ea4a0ea27f3abadb82e1e7f0a1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 24 Nov 2003 05:02:46 +0000 Subject: [PATCH 265/265] Documentation updates, added GNUMakefile for building [SVN r20931] --- doc/GNUmakefile | 232 +++++++++++ doc/counting_iterator.html | 207 +++++++++- doc/facade-and-adaptor.html | 664 +++++++++++++++++------------- doc/facade-and-adaptor.rst | 87 ++-- doc/filter_iterator.html | 208 +++++++++- doc/function_output_iterator.html | 197 ++++++++- doc/index.html | 328 ++++++++++++--- doc/index.rst | 98 +++-- doc/indirect_iterator.html | 213 +++++++++- doc/iterator_adaptor.html | 340 +++++++++++---- doc/iterator_adaptor_abstract.rst | 10 +- doc/iterator_adaptor_body.rst | 10 +- doc/iterator_adaptor_ref.rst | 104 +++-- doc/iterator_facade.html | 492 ++++++++++++++++------ doc/iterator_facade.rst | 2 + doc/iterator_facade_body.rst | 23 +- doc/iterator_facade_ref.rst | 315 +++++++------- doc/new-iter-concepts.html | 276 ++++--------- doc/new-iter-concepts.rst | 263 ++++-------- doc/permutation_iterator.html | 198 ++++++++- doc/style.tex | 77 +--- 21 files changed, 3074 insertions(+), 1270 deletions(-) create mode 100755 doc/GNUmakefile diff --git a/doc/GNUmakefile b/doc/GNUmakefile new file mode 100755 index 0000000..a536710 --- /dev/null +++ b/doc/GNUmakefile @@ -0,0 +1,232 @@ +# GNUmakefile for postprocessing PDF files +# +# © 2000 IBM Corporation. +# Licensed under the GNU GPL. + +######################################################################## +# Make sure that the following macros are correct for your setup +######################################################################## +# ... System utilities +RMRF = /bin/rm -rf +MV = /bin/mv +EGREP = /bin/egrep +ECHO = /bin/echo +PERL = /usr/bin/perl +CAT = /bin/cat +TOUCH = /bin/touch +ZIP = /usr/bin/zip + +# ... TeX & postprocessors +PPOWER4 = ppower4 +PDFLATEX = pdflatex +METAPOST = mpost +FIG2DEV = fig2dev +BIBTEX = bibtex +FOLIAGECUTTER = foliageCutter --verbose +RST2LATEX = rst2latex --documentclass book --documentoptions 10pt,twoside,pdftex # --use-latex-toc +RST2HTML = rst2html + +TEX = latex +export TEX +######################################################################## +# End of user servicable parts; don't fiddle with the remainder of this +# makefile unless you know what you do. +# +# You have been warned ;=) +######################################################################## + +# ... Variables +TEXFILES = $(strip $(wildcard *.tex)) +RSTFILES = $(strip $(wildcard *.rst)) +-include GNUmakefile.local +TEXSTEMS = $(strip $(patsubst %.tex,%,${TEXFILES})) +RSTSTEMS = $(strip $(patsubst %.rst,%,${RSTFILES})) +CUTFOILS = $(strip $(patsubst %,%---toc.tex,${TEXSTEMS})) +PDFFILES = $(strip $(patsubst %.tex,%.pdf,${TEXFILES})) +PRINTS = $(patsubst %.pdf,%-print.pdf,${PDFFILES}) +PRINTZIP = prints.zip +SLIDEZIP = slides.zip + +# ... Depend +DEPENDFILE = .depend +GENFILE = .generated + +# ... List of extensions and files generated +texcrap = *.mpx *.log *.aux *.blg *-print.brf *-print.tex *.out + +mpxcrap = mpxerr.tex mpxerr.pdf + +generated = *.out *.[0-9] *.[0-9][0-9] *.bbl *.brf \ + *.mp *.mmp *.pdf .depend *.ps TMP-*.pdf *.ftoc\ + ${PRINTZIP} ${SLIDEZIP} ${GENFILE} ${DEPENDFILE} \ + ${texcrap} ${mpxcrap} ${CUTFOILS} $(strip $(wildcard *---*.tex)) + + +# ... canned command to run PDFLaTeX +define run-pdflatex +@${ECHO} "" +@${ECHO} "---- Running PDFLaTeX on $<" && ${PDFLATEX} $< +@${ECHO} "---- Running PDFLaTeX on $< again" && ${PDFLATEX} $< +-@(${EGREP} -qi 'Rerun to get' $*.log && \ + ${ECHO} "---- Rerunning PDFLaTeX on $* to get cross-refs right" && \ + ${PDFLATEX} $<) || \ + ${ECHO} "---- No cross-refs correcting PDFLaTeX rerun required for $*" +-@(${EGREP} -qi $*.ftoc $*.log && \ + ${ECHO} "---- Rerunning PDFLaTeX on $* for FTOC" && \ + ${PDFLATEX} $<) || \ + ${ECHO} "---- No FTOC PDFLaTeX run required for $*" +-@(${EGREP} -qi 'Warning: Citation' $*.log && \ + ${ECHO} "---- Running BIBTeX on $*" && \ + ${BIBTEX} $* && \ + ${ECHO} "---- Running PDFLaTeX on $<" && \ + ${PDFLATEX} $<) || \ + ${ECHO} "---- No BIBTeX run required for $*" +-@(${EGREP} -qi 'Warning: .+undefined references' $*.log && \ + ${ECHO} "---- Running PDFLaTeX on $<" && \ + ${PDFLATEX} $<) || \ + ${ECHO} "---- No further PDFLaTex run required for $<" +@${ECHO} "Generated: $@ {$<}" >> ${GENFILE} +@${RMRF} ${texcrap} +endef + +# ... canned command to run PDFLaTeX for printable versions +define run-pdflatex-for-print +@${ECHO} "" +@${ECHO} "---- Running PDFLaTeX on $*-print.tex" && ${PDFLATEX} $*-print.tex +@${ECHO} "---- Running PDFLaTeX on $< again" && ${PDFLATEX} $< +-@(${EGREP} -qi 'Warning: Citation' $*-print.log && \ + ${ECHO} "---- Running BIBTeX on $*-print" && \ + ${BIBTEX} $*-print && \ + ${ECHO} "---- Running PDFLaTeX on $*-print.tex" && \ + ${PDFLATEX} $*-print.tex) || \ + ${ECHO} "---- No BIBTeX run required for $*" +-@(${EGREP} -qi 'Warning: .+undefined references' $*-print.log && \ + ${ECHO} "---- Running PDFLaTeX on $*-print" && \ + ${PDFLATEX} $*-print.tex) || \ + ${ECHO} "---- No further PDFLaTex run required for $*-print" +@${ECHO} "Generated: $@ {$<}" >> ${GENFILE} +@${RMRF} ${texcrap} +endef + +# DWA begin modifications +# ... Rule: How to generate TeX from ReST +%.tex: %.txt + @${ECHO} "---- Running rst2latex on $<" + ${RST2LATEX} $< $@ + @${ECHO} "Generated: $@ {$<}" >> ${GENFILE} + +# ... Rule: How to generate TeX from ReST +%.tex: %.rst + @${ECHO} "---- Running rst2latex on $<" + ${RST2LATEX} $< $@ + @${ECHO} "Generated: $@ {$<}" >> ${GENFILE} + +# ... Rule: How to generate HTML from ReST +%.html: %.txt + @${ECHO} "---- Running rst2html on $<" + ${RST2HTML} $< $@ + @${ECHO} "Generated: $@ {$<}" >> ${GENFILE} + +# ... Rule: How to generate HTML from ReST +%.html: %.rst + @${ECHO} "---- Running rst2html on $<" + ${RST2HTML} $< $@ + @${ECHO} "Generated: $@ {$<}" >> ${GENFILE} +# DWA end modifications + +# ... Rule: How to generate PDF from TeX +%.pdf: %.tex + $(run-pdflatex) + @${MV} $@ TMP-$@ + @${ECHO} "---- Running PPower4 on $*" + ${PPOWER4} -v TMP-$@ $@ + @${RMRF} TMP-$@ + @${ECHO} "Postprocessed: $*.pdf {$*.pdf}" >> ${GENFILE} + +# ... Rule: How to generate printable PDF from TeX +%-print.pdf: %.tex + ${PERL} -pe 's/^\\documentclass\[(.*?)\]/\\documentclass\[$$1,prints\]/;' < $< > $*-print.tex + $(run-pdflatex-for-print) + @${ECHO} "Generated: $*-print.pdf {$*.pdf}" >> ${GENFILE} + +# ... Rule: How to generate cut foils from TeX master +%---toc.tex: %.tex + ${FOLIAGECUTTER} --prefix=$* $< + +# ... Rule: How to generate MetaPost from FIG +%.mp: %.fig + @${ECHO} "---- Running Fig2Dev (mp) on $<" + ${FIG2DEV} -L mp $< $@ + @${ECHO} "Generated: $@ {$<}" >> ${GENFILE} + +# ... Rule: How to generate MultiMetaPost from FIG +%.mmp: %.fig + @${ECHO} "---- Running Fig2Dev (mmp) on $<" + ${FIG2DEV} -L mmp $< $@ + @${ECHO} "Generated: $@ {$<}" >> ${GENFILE} + +# ... Rule: How to generate includable PS from FIG via MetaPost +%.mps: %.fig + @${ECHO} "---- Running Fig2Dev (mps) on $<" + ${FIG2DEV} -L mp $< $*.mps.mp + @${RMRF} $*.mps.[0-9] + ${METAPOST} $*.mps.mp + @${MV} $*.mps.0 $@ + @${ECHO} "Generated: $@ {$<}" >> ${GENFILE} + +# ... Rule: How to generate includable PS files from MultiMetaPost +%.0: %.mmp + @${ECHO} "---- Running MetaPost on $<" + @${RMRF} $*.[0-9] $*.[0-9][0-9] + ${METAPOST} $< + @${ECHO} "Generated: $*.0{...} {$<}" >> ${GENFILE} + +cleanup-crap: + @${RMRF} ${mpxcrap} + +# ... Target: all +all: cleanup-crap .depend ${PDFFILES} ${PRINTS} ${PRINTZIP} ${SLIDEZIP} + @${ECHO} "" + @${TOUCH} ${GENFILE} + @${CAT} ${GENFILE} + @${RMRF} ${GENFILE} + +# ... Target: ZIP files +zip zips: ${PRINTZIP} ${SLIDEZIP} + +# ... Target: ZIP file containing printable versions of slides +${PRINTZIP}: .depend ${PDFFILES} + @${RMRF} ${PRINTZIP} + ${ZIP} -r ${PRINTZIP} ${PRINTS} + @${ECHO} "Generated: ${PRINTZIP}" >> ${GENFILE} + +# ... Target: ZIP file containing screen versions of slides + ${SLIDEZIP}: .depend ${PDFFILES} + @${RMRF} ${SLIDEZIP} + ${ZIP} -r ${SLIDEZIP} ${PDFFILES} + @${ECHO} "Generated: ${SLIDEZIP}" >> ${GENFILE} + +# ... Target: clean up +clean: + ${RMRF} ${generated} + +# ... Target: create dependencies +depend: .depend + +# ... Target: dependency file (parse TEXFILES for multiinclude and includegraphics) +.depend: GNUmakefile ${TEXFILES} + ${RMRF} $@ + @for t in ${TEXSTEMS} ; do \ + ${ECHO} "Scanning $$t.tex"; \ + ${PERL} -e 'my $$target = shift @ARGV;' -e 'while (<>) { /\\multiinclude(\[.*?\])?{(.*?)}/ && print "$$target: $$2.0\n";}' $$t.pdf < $$t.tex >> $@; \ + ${PERL} -e 'my $$target = shift @ARGV;' -e 'while (<>) { /\\includegraphics(\[.*?\])?{(.*?)\.(.*?)}/ && print "$$target: $$2.$$3\n";}' $$t.pdf < $$t.tex >> $@; \ + done + @for t in ${RSTSTEMS} ; do \ + ${ECHO} "Scanning $$t.rst"; \ + ${PERL} -e 'my $$target = shift @ARGV;' -e 'while (<>) { /^\.\. include::\s+(.*)/ && print "$$target: $$1\n";}' $$t.html < $$t.rst >> $@; \ + ${PERL} -e 'my $$target = shift @ARGV;' -e 'while (<>) { /^\.\. include::\s+(.*)/ && print "$$target: $$1\n";}' $$t.tex < $$t.rst >> $@; \ + done + + +# ... include dependency file +-include .depend diff --git a/doc/counting_iterator.html b/doc/counting_iterator.html index c5390c2..15fc046 100644 --- a/doc/counting_iterator.html +++ b/doc/counting_iterator.html @@ -9,7 +9,198 @@ - +
    @@ -52,13 +243,19 @@ the base m_iterator, as per th
    -template <class Incrementable, class Category = use_default, class Difference = use_default>
    +template <
    +    class Incrementable
    +  , unsigned Access = use_default_access
    +  , class Traversal = use_default
    +  , class Difference = use_default
    +>
     class counting_iterator
       : public iterator_adaptor<
    -        counting_iterator<Incrementable, Category, Difference>
    +        counting_iterator<Incrementable, Access, Traversal, Difference>
           , Incrementable
           , Incrementable
    -      , /* see details for category */
    +      , Access
    +      , /* see details for traversal category */
           , Incrementable const&
           , Incrementable const*
           , /* distance = Difference or a signed integral type */>
    @@ -143,7 +340,7 @@ object copy constructed from x
     
     
     
    diff --git a/doc/facade-and-adaptor.html b/doc/facade-and-adaptor.html
    index 49efb2e..a8f2a09 100755
    --- a/doc/facade-and-adaptor.html
    +++ b/doc/facade-and-adaptor.html
    @@ -8,7 +8,6 @@
     
     
     
    -
     
     
     
     
    @@ -97,12 +288,13 @@ class filter_iterator

    filter_iterator requirements

    -

    The base Iterator parameter must be a model of Readable Iterator -and Single Pass Iterator. The resulting filter_iterator will be a -model of Forward Traversal Iterator if Iterator is, otherwise the -filter_iterator will be a model of Single Pass Iterator. The -access category of the filter_iterator will be the most refined -standard access category that is modeled by Iterator.

    +

    The base Iterator parameter must be a model of Readable +Iterator and Single Pass Iterator. The resulting +filter_iterator will be a model of Forward Traversal Iterator +if Iterator is, otherwise the filter_iterator will be a +model of Single Pass Iterator. The access category of the +filter_iterator will be the same as the access category of +Iterator.

    The Predicate must be Assignable, Copy Constructible, and the @@ -189,7 +381,7 @@ filter_iterator(

    diff --git a/doc/function_output_iterator.html b/doc/function_output_iterator.html index 90e2d2f..8af8f32 100644 --- a/doc/function_output_iterator.html +++ b/doc/function_output_iterator.html @@ -9,7 +9,198 @@ - +
    @@ -60,7 +251,7 @@ template <class UnaryFunction> class function_output_iterator { public: typedef iterator_tag< - writable_iterator_tag + writable_iterator , incrementable_traversal_tag > iterator_category; typedef void value_type; @@ -158,7 +349,7 @@ return *this; diff --git a/doc/index.html b/doc/index.html index 3dfe4a0..b3a3a14 100755 --- a/doc/index.html +++ b/doc/index.html @@ -4,12 +4,203 @@ -The Boost Iterator Library Boost - +The Boost.Iterator Library Boost +