Compare commits

...

113 Commits

Author SHA1 Message Date
078dd3ec30 This commit was manufactured by cvs2svn to create tag
'Version_1_22_0'.

[SVN r10239]
2001-05-28 15:01:00 +00:00
d7023154a3 Fix broken hyperlinks
[SVN r9980]
2001-04-25 13:22:53 +00:00
9582b2223c Change all eGroups references to YahooGroups
[SVN r9979]
2001-04-25 00:24:50 +00:00
d7908fb81f added public before the typedef for "type" in non_bidirectional_category
[SVN r9711]
2001-04-05 02:32:00 +00:00
e48cdcb94f blah
[SVN r9588]
2001-03-19 19:35:51 +00:00
0846ad5fd0 added links to iterator_traits.htm
[SVN r9587]
2001-03-19 18:05:17 +00:00
84663ff2e2 added more doc
[SVN r9586]
2001-03-19 18:01:41 +00:00
6de1934420 new file
[SVN r9585]
2001-03-19 17:41:49 +00:00
a110b9fd27 new files
[SVN r9578]
2001-03-18 19:06:33 +00:00
eb06c122d1 rigged new iterator_traits for backward compatibility
[SVN r9577]
2001-03-18 18:37:49 +00:00
cbbe851adb VC++ workaround: the forward_iterator real ref check is not working
[SVN r9499]
2001-03-08 20:01:35 +00:00
f6cc2e520f parameters following a named parameter list must get their types from
the named parameter list and not use the default


[SVN r9496]
2001-03-08 19:03:44 +00:00
4e29b5aa29 removed some #if 0's
[SVN r9491]
2001-03-08 17:01:25 +00:00
d924f56ad8 added support for optional named template parameters
[SVN r9487]
2001-03-08 16:33:14 +00:00
f27fd095f7 new file, part of the iterator adaptors library
[SVN r9350]
2001-02-27 05:49:55 +00:00
d22edf735a put policies type in private
[SVN r9290]
2001-02-20 16:00:21 +00:00
af8dd117d5 Rolled back reverse_iterator_pair_generator again, as it doesn't save typing on a conforming compiler
[SVN r9279]
2001-02-19 20:41:22 +00:00
149d07cda0 Fix missing comma bug
[SVN r9274]
2001-02-19 16:22:03 +00:00
e9d9bdbb10 Reinstated reverse_iterator_pair_generator
[SVN r9264]
2001-02-18 22:21:14 +00:00
8d8f828da5 changes to order of indirect_iterator_generator param list
[SVN r9246]
2001-02-17 22:03:06 +00:00
fc15f5f710 added Category parameter to the indirect iterator
[SVN r9240]
2001-02-17 19:59:54 +00:00
ef66d28b19 added "explicit" to iterator_adaptor constructor
[SVN r9234]
2001-02-17 01:44:41 +00:00
0c8d74863f Add an implicit conversion operator to operator_arrow_proxy as CW and BCC workarounds.
[SVN r9233]
2001-02-16 23:06:57 +00:00
1c73f1f2ae made filter_iterator_generator::policies_type public
[SVN r9230]
2001-02-16 21:27:26 +00:00
ee20a630dd Remove implication that a type generator may only generate a single type
[SVN r9221]
2001-02-16 05:24:45 +00:00
c2472221ef made the typedef policies_type public in iterator_adaptor
and private in filter_iterator_generator


[SVN r9205]
2001-02-15 06:07:00 +00:00
bf45977491 removed unnecessary typedefs from counting_iterator_traits
[SVN r9203]
2001-02-15 05:51:40 +00:00
1988994bd3 added dummy_constructor to dummyT so it can be used in concept archetypes
[SVN r9181]
2001-02-13 02:03:59 +00:00
5482763a93 added missing const qualifier
[SVN r9148]
2001-02-12 04:45:02 +00:00
2c2a3eab21 Use new iterator_adaptor interface, Fixes for Borland.
[SVN r9131]
2001-02-11 19:36:43 +00:00
dca20fae75 Use BOOST_STATIC_CONSTANT
[SVN r9129]
2001-02-11 19:33:47 +00:00
e3aaf2cc91 Switch to use of BOOST_STATIC_CONSTANT where possible
[SVN r9127]
2001-02-11 19:29:28 +00:00
ea4c7c7dd9 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]
2001-02-11 18:57:31 +00:00
fd6ba58d5e Borland fixes up the wazoo. It finally works!
[SVN r9114]
2001-02-11 16:09:22 +00:00
268e70faa1 Reinstate one of John's fixes
[SVN r9113]
2001-02-11 16:06:12 +00:00
170b44763d Clean up after John Maddocks's (finally effective!) Borland fixes
[SVN r9111]
2001-02-11 14:07:11 +00:00
b2701f9f78 Borland compiler fixes
[SVN r9110]
2001-02-11 12:50:06 +00:00
ad4c5ab089 Use new iterator_adaptor<> interface
[SVN r9106]
2001-02-11 03:10:01 +00:00
c585adde71 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]
2001-02-11 03:05:50 +00:00
c5f24d0d72 A baby step that worked.
[SVN r9095]
2001-02-10 23:14:42 +00:00
dbb99b1cf3 Rolled in supposed Borland fixes from John Maddock, but not seeing any improvement yet
[SVN r9093]
2001-02-10 20:23:35 +00:00
be44a4714b 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]
2001-02-10 20:22:05 +00:00
e9f24023d4 completely removed constructor that was #if 0'd
[SVN r9076]
2001-02-10 17:57:51 +00:00
51616fa845 removed superfluous "typename"
[SVN r9068]
2001-02-10 09:34:19 +00:00
d7884b5613 *** empty log message ***
[SVN r9066]
2001-02-10 00:35:45 +00:00
15b5b66776 Improved interface to indirect_ and reverse_ iterators
[SVN r9065]
2001-02-10 00:26:55 +00:00
6f90982a45 roll back mistaken changes
[SVN r9062]
2001-02-09 21:04:09 +00:00
bfda34e9e0 try a better interface to indirect iterators
[SVN r9060]
2001-02-09 19:26:19 +00:00
5bfc03ed4a Cleaned up redundant test is_integral<T> || is_same<T,char> -> is_integral<T>
[SVN r9059]
2001-02-09 15:43:57 +00:00
490bee3a06 Factored out is_numeric computation. Borland still unhappy :(
[SVN r9057]
2001-02-09 15:21:02 +00:00
8174963a45 Rolled back Jeremy's new constructor for now; it was causing problems with counting_iterator_test
Attempted fix for Borland


[SVN r9055]
2001-02-09 15:17:17 +00:00
86e183c75e MSVC porting
[SVN r9052]
2001-02-09 05:44:13 +00:00
a94c9d0db2 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]
2001-02-09 05:26:01 +00:00
8a73dcd052 Fixed bidirectional iterator test so that --i is no longer a precondition.
[SVN r9048]
2001-02-09 04:29:11 +00:00
8496571204 Fold in Jeremy's improvement to make_reverse_iterator
[SVN r9042]
2001-02-09 03:29:11 +00:00
bafe0703a6 Beginning of a failed attempt to appease Borland
[SVN r9041]
2001-02-09 03:27:40 +00:00
b05b38810c just whitespace
[SVN r9030]
2001-02-08 04:45:18 +00:00
edf17ba001 put indirect_iterator_pair_generator back in
[SVN r9027]
2001-02-08 03:41:23 +00:00
ee9f140fae 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]
2001-02-08 03:07:33 +00:00
762e603013 rename counting_iterator() -> make_counting_iterator()
[SVN r9015]
2001-02-07 22:27:02 +00:00
6eeeb23332 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]
2001-02-07 17:22:16 +00:00
07482538ed 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]
2001-02-07 05:15:42 +00:00
d17e8dae9b codewarrior bug workaround
[SVN r8989]
2001-02-06 23:59:02 +00:00
5e1bc30db9 1st draft
[SVN r8939]
2001-02-05 05:39:43 +00:00
e8389d5f49 start of iterator concept tests
[SVN r8938]
2001-02-05 05:38:44 +00:00
332f18cf9f changed category for transform iterator traits to input iterator
[SVN r8936]
2001-02-04 23:45:57 +00:00
7aea7b7881 Factored counting_iterator stuff into boost/counting_iterator.hpp
[SVN r8935]
2001-02-04 23:37:01 +00:00
3e6796ab91 Fixed lvalue test
[SVN r8934]
2001-02-04 23:35:26 +00:00
893b5c0e25 Moved contents to boost/iterator_adaptors.hpp
[SVN r8933]
2001-02-04 23:34:29 +00:00
41c334d718 MWERKS bug workaround
[SVN r8931]
2001-02-04 20:35:23 +00:00
05336f45c4 Support for user-defined iterator categories
[SVN r8930]
2001-02-04 20:33:45 +00:00
90299982a6 Added counting_iterator_generator; updated comments
[SVN r8928]
2001-02-04 19:38:28 +00:00
93b54c15c8 Inital checkin
[SVN r8927]
2001-02-04 19:11:30 +00:00
25f9acabac corrected preconditions
[SVN r8925]
2001-02-04 19:00:03 +00:00
bb2ffadade Added lvalue test
[SVN r8922]
2001-02-04 18:25:55 +00:00
b6aa32721f Inital checkin
[SVN r8813]
2001-01-30 16:00:37 +00:00
8f41e88f85 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]
2001-01-25 04:57:16 +00:00
58b56fbabb Initial checkin
[SVN r8757]
2001-01-24 18:36:52 +00:00
9a4b0b576d added filter iterator
[SVN r8735]
2001-01-23 19:09:30 +00:00
c948483ec1 added some #ifdefs to prevent compilation of workaround code
[SVN r8688]
2001-01-21 20:28:02 +00:00
a31a89ae7d fixed some mwerks compiler errors
[SVN r8683]
2001-01-21 19:33:06 +00:00
b8ccd48fa3 Moved type<> to boost/type.hpp
[SVN r8678]
2001-01-21 06:20:20 +00:00
cf1d6a30af fixed some warnings under g++
[SVN r8600]
2001-01-15 03:10:11 +00:00
7fa5da6778 fixed dispatch for MIPSpro workaround
[SVN r8599]
2001-01-15 02:51:45 +00:00
34a9d4e702 another MIPSpro workaround
[SVN r8597]
2001-01-14 21:10:44 +00:00
42710d0967 also, advance_impl should take non-const Iter param
[SVN r8595]
2001-01-14 19:23:19 +00:00
487acf8c1c iter() should be i.iter()
[SVN r8594]
2001-01-14 19:21:29 +00:00
d6ec67f6ed added version number for MIPSpro
[SVN r8586]
2001-01-14 01:27:01 +00:00
e1b64d45e2 MIPSpro port, avoid using operators that are not defined
[SVN r8584]
2001-01-14 01:14:39 +00:00
4314dd18ae added <cstddef> for std::ptrdiff_t
[SVN r8562]
2001-01-12 18:50:21 +00:00
b634113daf added concept checking classes for purposes of documentation (they don't get invoked)
[SVN r8499]
2000-12-28 03:00:45 +00:00
0c68369f23 changed reference type of counting_iterator to avoid problems on VC++
[SVN r8474]
2000-12-17 21:53:22 +00:00
42ddb0d47b 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]
2000-12-15 21:51:02 +00:00
e6191bc913 operator[] needed to be const
[SVN r8463]
2000-12-15 19:31:16 +00:00
8cf1b8acb2 forgot #include <iterator>
[SVN r8461]
2000-12-13 23:24:55 +00:00
3852c810f3 various changes, almost forgot to check in
[SVN r8379]
2000-12-03 06:20:23 +00:00
04c0c043e0 added projection iterator to the test
[SVN r8320]
2000-11-24 20:45:26 +00:00
ffec5207fa changed names to "Inner" and "Outer"
[SVN r8318]
2000-11-24 20:05:11 +00:00
31fef5252a simplified version of iterator_adaptor, plus fix to indirect iterator
and addition of projection iterator


[SVN r8317]
2000-11-24 19:40:51 +00:00
80bcc4e643 some concept checking changes as per review comments
[SVN r8268]
2000-11-20 18:17:52 +00:00
87a3007c92 completed codewarrior workaround
[SVN r8169]
2000-11-10 16:24:39 +00:00
ea1513596d changed counting iterator policies to a template class to avoid
using template  member functions


[SVN r8157]
2000-11-07 22:22:49 +00:00
9d659841a0 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]
2000-11-04 23:15:10 +00:00
efcbd24229 port to Codewarrior 6.0
[SVN r8107]
2000-11-03 04:25:13 +00:00
3692175786 added base() function
[SVN r8098]
2000-11-02 02:29:53 +00:00
d3b8f893bc changed reference type
[SVN r8033]
2000-10-26 14:04:50 +00:00
cebe553621 ported the graph library to borland
[SVN r7965]
2000-10-17 00:16:05 +00:00
b54236986d work around for VC++ bug, triggered by overloading of remove_edge
[SVN r7860]
2000-09-27 21:02:16 +00:00
24c3beb791 rolled back the removal of the iterator_adaptor alternate code,
added the graph test file


[SVN r7851]
2000-09-26 22:09:34 +00:00
50c9214b82 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]
2000-09-26 07:29:12 +00:00
c583cf8730 removed tabs
[SVN r7835]
2000-09-25 21:19:29 +00:00
61d2d43ea5 Use iterator adaptors with STLport.
[SVN r7788]
2000-09-24 01:06:34 +00:00
76efd2456c changes for visual c++ port
[SVN r7764]
2000-09-22 04:18:51 +00:00
15 changed files with 3124 additions and 558 deletions

View File

@ -0,0 +1,199 @@
#ifndef BOOST_ITERATOR_CONCEPTS_HPP
#define BOOST_ITERATOR_CONCEPTS_HPP
#include <boost/concept_check.hpp>
#include <boost/iterator_traits.hpp>
#include <boost/type_traits/conversion_traits.hpp>
#include <boost/static_assert.hpp>
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.
//===========================================================================
// Iterator Access Concepts
template <typename Iterator>
class ReadableIteratorConcept {
public:
typedef typename boost::iterator_traits<Iterator>::value_type value_type;
typedef typename boost::iterator_traits<Iterator>::reference reference;
typedef typename boost::iterator_traits<Iterator>::return_category
return_category;
void constraints() {
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
boost::function_requires<
boost::DefaultConstructibleConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::is_convertible<return_category*,
boost::readable_iterator_tag*>::value));
reference r = *i; // or perhaps read(x)
value_type v(r);
boost::ignore_unused_variable_warning(v);
}
Iterator i;
};
template <typename Iterator, typename ValueType>
class WritableIteratorConcept {
public:
typedef typename boost::iterator_traits<Iterator>::return_category
return_category;
void constraints() {
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
boost::function_requires<
boost::DefaultConstructibleConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::is_convertible<return_category*,
boost::writable_iterator_tag*>::value));
*i = v; // an alternative could be something like write(x, v)
}
ValueType v;
Iterator i;
};
template <typename Iterator>
class ConstantLvalueIteratorConcept {
public:
typedef typename boost::iterator_traits<Iterator>::value_type value_type;
typedef typename boost::iterator_traits<Iterator>::reference reference;
typedef typename boost::iterator_traits<Iterator>::return_category
return_category;
void constraints() {
boost::function_requires< ReadableIteratorConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::is_convertible<return_category*,
boost::constant_lvalue_iterator_tag*>::value));
BOOST_STATIC_ASSERT((boost::is_same<reference,
const value_type&>::value));
reference v = *i;
boost::ignore_unused_variable_warning(v);
}
Iterator i;
};
template <typename Iterator>
class MutableLvalueIteratorConcept {
public:
typedef typename boost::iterator_traits<Iterator>::value_type value_type;
typedef typename boost::iterator_traits<Iterator>::reference reference;
typedef typename boost::iterator_traits<Iterator>::return_category
return_category;
void constraints() {
boost::function_requires< ReadableIteratorConcept<Iterator> >();
boost::function_requires<
WritableIteratorConcept<Iterator, value_type> >();
BOOST_STATIC_ASSERT((boost::is_convertible<return_category*,
boost::mutable_lvalue_iterator_tag*>::value));
BOOST_STATIC_ASSERT((boost::is_same<reference, value_type&>::value));
reference v = *i;
boost::ignore_unused_variable_warning(v);
}
Iterator i;
};
//===========================================================================
// Iterator Traversal Concepts
template <typename Iterator>
class SinglePassIteratorConcept {
public:
typedef typename boost::iterator_traits<Iterator>::traversal_category
traversal_category;
typedef typename boost::iterator_traits<Iterator>::difference_type
difference_type;
void constraints() {
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
boost::function_requires<
boost::DefaultConstructibleConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::is_convertible<traversal_category*,
boost::single_pass_iterator_tag*>::value));
// difference_type must be a signed integral type
++i;
(void)i++;
}
Iterator i;
};
template <typename Iterator>
class ForwardIteratorConcept {
public:
typedef typename boost::iterator_traits<Iterator>::traversal_category
traversal_category;
void constraints() {
boost::function_requires< SinglePassIteratorConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::is_convertible<traversal_category*,
boost::forward_iterator_tag*>::value));
}
};
template <typename Iterator>
class BidirectionalIteratorConcept {
public:
typedef typename boost::iterator_traits<Iterator>::traversal_category
traversal_category;
void constraints() {
boost::function_requires< ForwardIteratorConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::is_convertible<traversal_category*,
boost::bidirectional_iterator_tag*>::value));
--i;
(void)i--;
}
Iterator i;
};
template <typename Iterator>
class RandomAccessIteratorConcept {
public:
typedef typename boost::iterator_traits<Iterator>::traversal_category
traversal_category;
typedef typename boost::iterator_traits<Iterator>::difference_type
difference_type;
void constraints() {
boost::function_requires< BidirectionalIteratorConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::is_convertible<traversal_category*,
boost::random_access_iterator_tag*>::value));
i += n;
i = i + n;
i = n + i;
i -= n;
i = i - n;
n = i - j;
}
difference_type n;
Iterator i, j;
};
} // namespace boost_concepts
#endif // BOOST_ITERATOR_CONCEPTS_HPP

View File

@ -0,0 +1,137 @@
#ifndef BOOST_ITERATOR_TRAITS_HPP
#define BOOST_ITERATOR_TRAITS_HPP
#include <boost/config.hpp>
#include <boost/type_traits/conversion_traits.hpp>
#include <boost/type_traits/cv_traits.hpp>
#include <boost/pending/ct_if.hpp>
#include <boost/detail/iterator.hpp>
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 <typename Iterator> 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 <typename ValueType>
struct choose_lvalue_return {
typedef typename ct_if<is_const<ValueType>::value,
boost::constant_lvalue_iterator_tag,
boost::mutable_lvalue_iterator_tag>::type type;
};
template <typename Category, typename ValueType>
struct iter_category_to_return {
typedef typename ct_if<
is_convertible<Category*, std::forward_iterator_tag*>::value,
typename choose_lvalue_return<ValueType>::type,
typename ct_if<
is_convertible<Category*, std::input_iterator_tag*>::value,
boost::readable_iterator_tag,
typename ct_if<
is_convertible<Category*, std::output_iterator_tag*>::value,
boost::writable_iterator_tag,
boost::error_iterator_tag
>::type
>::type
>::type type;
};
template <typename Category>
struct iter_category_to_traversal {
typedef typename ct_if<
is_convertible<Category*, std::random_access_iterator_tag*>::value,
boost::random_access_iterator_tag,
typename ct_if<
is_convertible<Category*, std::bidirectional_iterator_tag*>::value,
boost::bidirectional_iterator_tag,
typename ct_if<
is_convertible<Category*, std::forward_iterator_tag*>::value,
boost::forward_iterator_tag,
boost::single_pass_iterator_tag>::type
>::type
>::type type;
};
struct iter_traits_from_old_traits {
template <typename Iterator> class bind {
typedef boost::detail::iterator_traits<Iterator> 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<Cat,value_type>::type return_category;
typedef iter_category_to_traversal<Cat>::type traversal_category;
};
};
template <typename Iterator>
class choose_iter_traits {
typedef typename ct_if<is_convertible<Iterator*,
new_iterator_base*>::value,
iter_traits_from_nested_types,
iter_traits_from_old_traits>::type Choice;
public:
typedef typename Choice:: template bind<Iterator> type;
};
} // namespace detail
template <typename Iterator>
class iterator_traits
: public detail::choose_iter_traits<Iterator>::type { };
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <typename T>
struct iterator_traits<T*>
{
typedef T value_type;
typedef T& reference;
typedef T* pointer;
typedef std::ptrdiff_t difference_type;
typedef typename ct_if<is_const<T>::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

View File

@ -0,0 +1,76 @@
#include <boost/iterator_concepts.hpp>
#include <boost/operators.hpp>
struct new_iterator
: public boost::iterator<std::random_access_iterator_tag, int>,
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<std::random_access_iterator_tag, int>
{
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 bar { };
void foo(bar) { }
int
main()
{
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
boost::function_requires<
boost_concepts::MutableLvalueIteratorConcept<int*> >();
boost::function_requires<
boost_concepts::RandomAccessIteratorConcept<int*> >();
boost::function_requires<
boost_concepts::ConstantLvalueIteratorConcept<const int*> >();
boost::function_requires<
boost_concepts::RandomAccessIteratorConcept<const int*> >();
#endif
boost::function_requires<
boost_concepts::MutableLvalueIteratorConcept<new_iterator> >();
boost::function_requires<
boost_concepts::RandomAccessIteratorConcept<new_iterator> >();
boost::function_requires<
boost_concepts::MutableLvalueIteratorConcept<old_iterator> >();
boost::function_requires<
boost_concepts::RandomAccessIteratorConcept<old_iterator> >();
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,606 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. I make no representations about the
-- suitability of this software for any purpose. It is provided "as is"
-- without express or implied warranty.
-->
<!--
-- Copyright (c) 1996-1999
-- Silicon Graphics Computer Systems, Inc.
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. Silicon Graphics makes no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
--
-- Copyright (c) 1994
-- Hewlett-Packard Company
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. Hewlett-Packard Company makes no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
--
-->
<Head>
<Title>Iterator Concepts</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<h1>Iterator Concepts</h1>
<p>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.</p>
One set of concepts handles the return type semantics:
<ul>
<li><a href="#concept:ReadableIterator">Readable Iterator</a></li>
<li><a href="#concept:WritableIterator">Writable Iterator</a></li>
<li><a href="#concept:MutableLvalueIterator">Mutable Lvalue Iterator</a></li>
<li><a href="#concept:ConstantLvalueIterator">Constant Lvalue Iterator</a></li>
</ul>
The other set of concepts handles iterator traversal:
<ul>
<li><a href="#concept:SinglePassIterator">Single-Pass Iterator</a></li>
<li><a href="#concept:ForwardIterator">Forward Iterator</a></li>
<li><a href="#concept:BidirectionalIterator">Bidirectional Iterator</a></li>
<li><a href="#concept:RandomAccessIterator">Random Access Iterator</a></li>
</ul>
<p></p>
<DIV ALIGN="CENTER"><A NAME="fig:graph-concepts"></A></A>
<TABLE>
<CAPTION ALIGN="TOP"><STRONG>Figure 1:</STRONG>
The iterator concepts and refinement relationships.
</CAPTION>
<TR><TD><IMG SRC="./iterator_concepts.gif" width="541" height="214"></TD></TR>
</TABLE>
</DIV>
<p></p>
<h2>Relationship with the standard iterator concepts</h2>
<p>
std::Input Iterator refines boost::Single-Pass Iterator and
boost::ReadableIterator.
<p>
std::Output Iterator refines boost::Single-Pass Iterator and
boost::Writable Iterator.
<p>
std::Forward Iterator refines boost::Forward Iterator and
boost::Constant Lvalue Iterator or boost::Mutable Lvalue Iterator.
<p>
std::Bidirectional Iterator refines boost::Bidirectional Iterator and
boost::Constant Lvalue Iterator or boost::Mutable Lvalue Iterator.
<p>
std::Random Access Iterator refines boost::Random Access Iterator and
boost::Constant Lvalue Iterator or boost::Mutable Lvalue Iterator.
<h3>Notation</h3>
<Table>
<TR>
<TD><tt>X</tt></TD>
<TD>The iterator type.</TD>
</TR>
<TR>
<TD><tt>T</tt></TD>
<TD>The value type of <tt>X</tt>.</TD>
</TR>
<TR>
<TD><tt>x</tt>, <tt>y</tt></TD>
<TD>An object of type <tt>X</tt>.</TD>
</TR>
<TR>
<TD><tt>t</tt></TD>
<TD>An object of type <tt>T</tt>.</TD>
</tr>
</table>
<p>
<hr>
<H2><A NAME="concept:ReadableIterator"></A>
Readable Iterator
</H2>
A Readable Iterator is an iterator that dereferences to produce an
rvalue that is convertible to the <tt>value_type</tt> 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.
<pre>
template &lt;class Readable Iterator&gt;
void foo(Readable Iterator x)
{
typedef std::iterator_traits&lt;Readable Iterator&gt;::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.
}
</pre>
<h3>Associated Types</h3>
<Table border>
<TR>
<TD>Value type</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::value_type</tt></TD>
<TD>
The type of the value obtained by dereferencing a LvalueIterator
</TD>
</tr>
<TR>
<TD>Return Category</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::return_category</tt></TD>
<TD>
A type convertible to <tt>boost::readable_iterator_tag</tt>
</TD>
</tr>
</Table>
<h3>Refinement of</h3>
<A href="http://www.sgi.com/Technology/STL/Assignable.html">Assignable</A>,
<A href="http://www.sgi.com/Technology/STL/EqualityComparable.html">Equality Comparable</A>,
<A href="http://www.sgi.com/Technology/STL/DefaultConstructible.html">Default Constructible</A>
<h3>Valid expressions</h3>
<Table border>
<TR><TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH><TH>Return type</TH></TR>
<TR>
<TD>Dereference</TD>
<TD><tt>*x</tt></TD>
<TD>&nbsp;</TD>
<TD>Convertible to <tt>T</tt>.</TD>
</TR>
<TR>
<TD>Member access</TD>
<TD><tt>x-&gt;m</tt></TD>
<TD><tt>T</tt> is a type with a member named <tt>m</tt>.</TD>
<TD>
&nbsp;
</TD>
</tr>
</table>
<p>
<hr>
<H2><A NAME="concept:WritableIterator"></A>
Writable Iterator
</H2>
A Writable Iterator is an iterator that can be used to store a value
using the dereference-assignment expression.
<h3>Definitions</h3>
If <tt>x</tt> is an Writable Iterator of type <tt>X</tt>, then the
expression <tt>*x = a;</tt> stores the value <tt>a</tt> into
<tt>x</tt>. Note that <tt>operator=</tt>, like other C++ functions,
may be overloaded; it may, in fact, even be a template function. In
general, then, <tt>a</tt> may be any of several different types. A
type <tt>A</tt> belongs to the <i>set of value types</i> of <tt>X</tt>
if, for an object <tt>a</tt> of type <tt>A</tt>, <tt>*x = a;</tt> is
well-defined and does not require performing any non-trivial
conversions on <tt>a</tt>.
<h3>Associated Types</h3>
<Table border>
<TR>
<TD>Return Category</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::return_category</tt></TD>
<TD>
A type convertible to <tt>boost::writable_iterator_tag</tt>
</TD>
</tr>
</Table>
<h3>Refinement of</h3>
<A href="http://www.sgi.com/Technology/STL/Assignable.html">Assignable</A>,
<A href="http://www.sgi.com/Technology/STL/EqualityComparable.html">Equality Comparable</A>,
<A href="http://www.sgi.com/Technology/STL/DefaultConstructible.html">Default Constructible</A>
<h3>Valid expressions</h3>
<Table border>
<TR>
<TH>Name</TH><TH>Expression</TH><TH>Return type</TH>
</TR>
<TR>
<TD>Dereference assignment</TD>
<TD><tt>*x = a</tt></TD>
<TD>unspecified</TD>
</TR>
</table>
<p>
<hr>
<H2><A NAME="concept:ConstantLvalueIterator"></A>
Constant Lvalue Iterator
</H2>
A Constant Lvalue Iterator is an iterator that dereferences to produce a
const reference to the pointed-to object, i.e., the associated
<tt>reference</tt> type is <tt>const T&amp;</tt>. Changing the value
of or destroying an iterator that models Constant Lvalue Iterator does
not invalidate pointers and references previously obtained from that
iterator.
<h3>Refinement of</h3>
<a href="#concept:Readable Iterator">Readable Iterator</a>
<h3>Associated Types</h3>
<Table border>
<TR>
<TD>Value type</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::value_type</tt></TD>
<TD>
The type of the value obtained by dereferencing a Constant Lvalue Iterator.
</TD>
</tr>
<TR>
<TD>Reference type</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::reference</tt></TD>
<TD>
The return type of <tt>operator*()</tt>, which must be
<tt>const T&amp;</tt>.
</TD>
</tr>
<TR>
<TD>POinter type</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::pointer</tt></TD>
<TD>
The pointer to the value type, which must be <tt>const T*</tt>.
</TD>
</tr>
<TR>
<TD>Return Category</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::return_category</tt></TD>
<TD>
A type convertible to <tt>boost::constant_lvalue_iterator_tag</tt>
</TD>
</tr>
</table>
<h3>Valid expressions</h3>
<Table border>
<TR><TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH><TH>Return type</TH></TR>
<TR>
<TD>Dereference</TD>
<TD><tt>*x</tt></TD>
<TD>&nbsp;</TD>
<TD><tt>const T&amp;</tt></TD>
</TR>
<TR>
<TD>Member access</TD>
<TD><tt>x-&gt;m</tt></TD>
<TD><tt>T</tt> is a type with a member named <tt>m</tt>.</TD>
<TD>
&nbsp;
</TD>
</tr>
</table>
<H2><A NAME="concept:MutableLvalueIterator"></A>
Mutable Lvalue Iterator
</H2>
A Mutable Lvalue Iterator is an iterator that dereferences to produce a
reference to the pointed-to object. The associated <tt>reference</tt>
type is <tt>T&amp;</tt>. Changing the value of or destroying an
iterator that models Mutable Lvalue Iterator does not invalidate
pointers and references previously obtained from that iterator.
<h3>Refinement of</h3>
<a href="#concept:Readable Iterator">Readable Iterator</a> and
<a href="#concept:WritableIterator">Writable Iterator</a>.
<h3>Associated Types</h3>
<Table border>
<TR>
<TD>Value type</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::value_type</tt></TD>
<TD>
The type of the value obtained by dereferencing a Mutable Lvalue Iterator.
</TD>
</tr>
<TR>
<TD>Reference type</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::reference</tt></TD>
<TD>
The return type of <tt>operator*()</tt>, which is
<tt>T&amp;</tt>.
</TD>
</tr>
<TR>
<TD>Pointer type</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::pointer</tt></TD>
<TD>
The pointer to the value type, which is <tt>T*</tt>.
</TD>
</tr>
<TR>
<TD>Return Category</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::return_category</tt></TD>
<TD>
A type convertible to <tt>boost::mutable_lvalue_iterator_tag</tt>
</TD>
</tr>
</table>
<h3>Valid expressions</h3>
<Table border>
<TR><TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH><TH>Return type</TH></TR>
<TR>
<TD>Dereference</TD>
<TD><tt>*x</tt></TD>
<TD>&nbsp;</TD>
<TD> <tt>T&amp;</tt> </TD>
</TR>
<TR>
<TD>Member access</TD>
<TD><tt>x-&gt;m</tt></TD>
<TD><tt>T</tt> is a type with a member named <tt>m</tt>.</TD>
<TD>
&nbsp;
</TD>
</tr>
</table>
<p>
<hr>
<H2><A NAME="concept:SinglePassIterator"></A>
Single-Pass Iterator
</H2>
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.
<h3>Associated types</h3>
<Table border>
<TR>
<TD>Difference type</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::difference_type</tt></TD>
<TD>
A signed integral type used to represent the distance from one
iterator to another, or the number of elements in a range.
</TD>
</TR>
<TR>
<TD>Traversal Category</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::traversal_category</tt></TD>
<TD>
A type convertible to <tt>boost::single_pass_iterator_tag</tt>
</TD>
</tr>
</table>
<h3>Valid expressions</h3>
<Table border>
<TR>
<TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH>
<TH>Return type</TH>
</TR>
<TR>
<TD>Preincrement</TD>
<TD><tt>++i</tt></TD><TD>&nbsp;</TD><TD><tt>X&amp;</tt></TD>
</TR>
<TR>
<TD>Postincrement</TD>
<TD><tt>(void)i++</tt></TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
</TR>
</Table>
<p>
<hr>
<H2><A NAME="concept:ForwardIterator"></A>
Forward Iterator
</H2>
The Forward Iterator is an iterator that can be incremented. Also, it
is permissible to make multiple passes through the sequence.
<h3>Refinement of</h3>
<a href="#concept:SinglePassIterator">Single-Pass Iterator</a>
<h3>Associated types</h3>
<Table border>
<TR>
<TD>Traversal Category</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::traversal_category</tt></TD>
<TD>
A type convertible to <tt>boost::forward_iterator_tag</tt>
</TD>
</tr>
</Table>
<p>
<hr>
<H2><A NAME="concept:BidirectionalIterator"></A>
Bidirectional Iterator
</H2>
An iterator that can be incremented and decremented.
<h3>Refinement of</h3>
<a href="#concept:ForwardIterator">Forward Iterator</a>
<h3>Associated types</h3>
<Table border>
<TR>
<TD>Traversal Category</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::traversal_category</tt></TD>
<TD>
A type convertible to <tt>boost::bidirectional_iterator_tag</tt>
</TD>
</tr>
</Table>
<h3>Valid expressions</h3>
<Table border>
<TR>
<TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH>
<TH>Return type</TH>
</TR>
<TR><TD>Predecrement</TD>
<TD><tt>--i</tt></TD><TD>&nbsp;</TD><TD><tt>X&amp;</tt></TD>
</TR>
<TR><TD>Postdecrement</TD>
<TD><tt>i--</tt></TD><TD>&nbsp;</TD><TD><tt>X</tt></TD>
</tr>
</table>
<p>
<hr>
<H2><A NAME="concept:RandomAccessIterator"></A>
Random Access Iterator
</H2>
An iterator that provides constant-time methods for moving forward and
backward in arbitrary-sized steps
<h3>Refinement of</h3>
<a href="#concept:BidirectionalIterator">Bidirectional Iterator</a>
<h3>Associated types</h3>
<Table border>
<TR>
<TD>Traversal Category</TD>
<TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::traversal_category</tt></TD>
<TD>
A type convertible to <tt>boost::random_access_iterator_tag</tt>
</TD>
</tr>
</Table>
<h3>Valid expressions</h3>
<Table border>
<TR><TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH>
<TH>Return type</TH>
</TR>
<TR><TD>Iterator addition</TD>
<TD><tt>i += n</tt></TD><TD>&nbsp;</TD><TD><tt>X&amp;</tt></TD>
</TR>
<TR><TD>Iterator addition</TD>
<TD><tt>i + n</tt> or <tt>n + i</tt></TD><TD>&nbsp;</TD><TD><tt>X</tt></TD>
</TR>
<TR><TD>Iterator subtraction</TD>
<TD><tt>i -= n</tt></TD><TD>&nbsp;</TD><TD><tt>X&amp;</tt></TD>
</TR>
<TR><TD>Iterator subtraction</TD>
<TD><tt>i - n</tt></TD><TD>&nbsp;</TD><TD><tt>X</tt></TD>
</TR>
<TR><TD>Difference</TD>
<TD><tt>i - j</tt></TD><TD>&nbsp;</TD><TD><tt><a href="./iterator_traits.htm">boost::iterator_traits</a>&lt;X&gt;::difference_type</tt></TD>
</TR>
<TR><TD>Element operator</TD>
<TD><tt>i[n]</tt></TD>
<TD><tt>X</tt> must be a model of
<a href="#concept:Readable Iterator">Readable Iterator</a>. </TD>
<TD>The same return type as <tt>*i</tt>.</TD>
</TR>
<TR><TD>Element assignment</TD>
<TD><tt>i[n] = t</tt></TD>
<TD><tt>X</tt> must be a model of
<a href="#concept:WritableIterator">Writable Iterator</a>.</TD>
<TD>unspecified</TD>
</tr>
</table>
<hr>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../../../people/jeremy_siek.htm">Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
</TD></TR></TABLE>
</body>
</html>

View File

@ -0,0 +1,137 @@
<html>
<!--
-- Copyright (c) Jeremy Siek 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. I make no representations about the
-- suitability of this software for any purpose. It is provided "as is"
-- without express or implied warranty.
-->
<head>
<title>Boost Iterator Traits</title>
</head>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<h1>Boost Iterator Traits</h1>
Header <tt><a href="../../boost/iterator_traits.hpp">boost/iterator_traits.hpp</a></tt>
<p>
The <tt>boost::iterator_traits</tt> class provides access to the
associated types of iterators that model the Boost <a
href="./iterator_concepts.htm">Iterator Concepts</a>, which are a
replacement for the iterator requirements in the C++ standard.
The main difference between <tt>std::iterator_traits</tt> and
<tt>boost::iterator_traits</tt> is that the <tt>iterator_category</tt>
type has been removed, and replaced with two new types:
<ul>
<li><tt>traversal_category</tt>:&nbsp;&nbsp; Can the iterator go forward, backward, etc.?
<li><tt>return_category</tt>:&nbsp;&nbsp; Is the iterator read or write only?
Is the dereferenced type an lvalue?
</ul>
<p>
An important feature of the <tt>boost::iterator_traits</tt> is that it
is <b>backwards compatible</b>, i.e., it will automatically work for
iterators for which there are valid definitions of
<tt>std::iterator_traits</tt>. The old <tt>iterator_category</tt> is
mapped to the appropriate traversal and return categories.
<p>
When creating a new iterator type that is meant to work with
<tt>boost::iterator_traits</tt>, you can either create a
specialization of <tt>boost::iterator_traits</tt> 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
<tt>new_iterator_base</tt> to let <tt>boost::iterator_traits</tt> know
that it will be able to find typedefs for <tt>traversal_category</tt>
and <tt>return_category</tt> in you iterator class.
<pre>
namespace boost {
<i>// 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.</i>
struct new_iterator_base { };
template &lt;typename Iterator&gt;
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&lt;Iterator&gt; 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;
<i>// Determine the traversal_category based on the old iterator_category</i>
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;
<i>// Determine the return_category based on the old iterator_category and value_type</i>
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 &lt;typename T&gt;
struct iterator_traits&lt;T*&gt;
{
typedef T value_type;
typedef T&amp; 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;
};
}
</pre>
<hr>
<address><a href="mailto:jsiek@lsc.nd.edu">jeremy siek</a></address>
<!-- Created: Sun Mar 18 14:06:57 EST 2001 -->
<!-- hhmts start -->
Last modified: Mon Mar 19 12:59:30 EST 2001
<!-- hhmts end -->
</body>
</html>

View File

@ -0,0 +1,215 @@
// (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 Incrementable> class counting_iterator_traits;
// template <class Incrementable> 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 <class Incrementable> struct counting_iterator_generator;
//
// A "type generator" whose nested type "type" is a counting iterator as
// described above.
//
// template <class Incrementable>
// typename counting_iterator_generator<Incrementable>::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 <boost/config.hpp>
# include <boost/detail/iterator.hpp>
# include <boost/iterator_adaptors.hpp>
# include <boost/type_traits.hpp>
# include <boost/detail/numeric_traits.hpp>
# include <boost/static_assert.hpp>
# ifndef BOOST_NO_LIMITS
# include <limits>
# 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 <bool is_integer> struct counting_iterator_traits_select;
// Incrementable is an iterator type
template <>
struct counting_iterator_traits_select<false>
{
template <class Incrementable>
struct traits
{
private:
typedef boost::detail::iterator_traits<Incrementable> 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<true>
{
template <class Incrementable>
struct traits
{
typedef typename
boost::detail::numeric_traits<Incrementable>::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 <bool is_integer> struct distance_policy_select;
// A policy for wrapped iterators
template <>
struct distance_policy_select<false>
{
template <class Distance, class Incrementable>
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<true>
{
template <class Distance, class Incrementable>
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 <class T>
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<char>::value);
# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits<T>::is_specialized);
# else
# if !defined(__BORLANDC__)
BOOST_STATIC_CONSTANT(bool, value = (
boost::is_convertible<int,T>::value && boost::is_convertible<T,int>::value));
# else
BOOST_STATIC_CONSTANT(bool, value = ::boost::is_arithmetic<T>::value);
# endif
# endif
};
// Compute the distance over arbitrary numeric and/or iterator types
template <class Distance, class Incrementable>
Distance any_distance(Incrementable start, Incrementable finish, Distance* = 0)
{
return distance_policy_select<(
is_numeric<Incrementable>::value)>::template
policy<Distance, Incrementable>::distance(start, finish);
}
} // namespace detail
template <class Incrementable>
struct counting_iterator_traits {
private:
typedef ::boost::detail::counting_iterator_traits_select<(
::boost::detail::is_numeric<Incrementable>::value
)> binder;
typedef typename binder::template traits<Incrementable> traits;
public:
typedef typename traits::difference_type difference_type;
typedef typename traits::iterator_category iterator_category;
};
template <class Incrementable>
struct counting_iterator_policies : public default_iterator_policies
{
const Incrementable& dereference(type<const Incrementable&>, const Incrementable& i) const
{ return i; }
template <class Difference, class Iterator1, class Iterator2>
Difference distance(type<Difference>, const Iterator1& x,
const Iterator2& y) const
{
return boost::detail::any_distance<Difference>(x, y);//,(Difference*)());
}
};
// A type generator for counting iterators
template <class Incrementable>
struct counting_iterator_generator
{
typedef counting_iterator_traits<Incrementable> traits;
typedef iterator_adaptor<Incrementable,
counting_iterator_policies<Incrementable>,
Incrementable,
const Incrementable&,
const Incrementable*,
typename traits::iterator_category,
typename traits::difference_type
> type;
};
// Manufacture a counting iterator for an arbitrary incrementable type
template <class Incrementable>
inline typename counting_iterator_generator<Incrementable>::type
make_counting_iterator(Incrementable x)
{
typedef typename counting_iterator_generator<Incrementable>::type result_t;
return result_t(x);
}
} // namespace boost
#endif // BOOST_COUNTING_ITERATOR_HPP_DWA20000119

View File

@ -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 <iterator>
namespace boost {
template <class UnaryFunction>
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 <class T> 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 <class UnaryFunction>
inline function_output_iterator<UnaryFunction>
make_function_output_iterator(const UnaryFunction& f = UnaryFunction()) {
return function_output_iterator<UnaryFunction>(f);
}
} // namespace boost
#endif // BOOST_FUNCTION_OUTPUT_ITERATOR_HPP

View File

@ -0,0 +1,426 @@
// (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:
// 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_
# include <boost/counting_iterator.hpp>
# include <functional>
# include <cassert>
# include <boost/operators.hpp>
# include <string>
# include <stdexcept>
# include <iterator>
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.
#ifdef __MWERKS__
template <class T>
const T& choose_finish(const T&, const T& finish, std::input_iterator_tag)
{
return finish;
}
template <class T>
const T& choose_finish(const T&, const T& finish, std::output_iterator_tag)
{
return finish;
}
template <class T>
const T& choose_finish(const T& start, const T& finish, std::random_access_iterator_tag)
{
return finish < start ? start : finish;
}
#else
template <bool is_random_access> struct finish_chooser;
template <>
struct finish_chooser<false>
{
template <class T>
struct rebind
{
static T choose(const T&, const T& finish)
{ return finish; }
};
};
template <>
struct finish_chooser<true>
{
template <class T>
struct rebind
{
static T choose(const T& start, const T& finish)
{ return finish < start ? start : finish; }
};
};
template <class Category, class Incrementable>
struct choose_finish
{
static const Incrementable choose(const Incrementable& start, const Incrementable& finish)
{
return finish_chooser<(
::boost::is_convertible<Category*,std::random_access_iterator_tag*>::value
)>::template rebind<Incrementable>::choose(start, finish);
}
};
#endif
}
template <class Incrementable>
struct half_open_range
{
typedef typename counting_iterator_generator<Incrementable>::type iterator;
private: // utility type definitions
// Using iter_t prevents compiler confusion with boost::iterator
typedef typename counting_iterator_generator<Incrementable>::type iter_t;
typedef std::less<Incrementable> less_value;
typedef typename iter_t::iterator_category category;
typedef half_open_range<Incrementable> self;
public:
typedef iter_t const_iterator;
typedef typename counting_iterator_traits<Incrementable>::value_type value_type;
typedef typename counting_iterator_traits<Incrementable>::difference_type difference_type;
typedef typename counting_iterator_traits<Incrementable>::reference reference;
typedef typename counting_iterator_traits<Incrementable>::reference const_reference;
typedef typename counting_iterator_traits<Incrementable>::pointer pointer;
typedef typename counting_iterator_traits<Incrementable>::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<Incrementable>::difference_type size_type;
half_open_range(Incrementable start, Incrementable finish)
: m_start(start),
m_finish(
#ifndef __MWERKS__
detail::choose_finish<category,Incrementable>::choose(start, finish)
#else
detail::choose_finish(start, finish, category())
#endif
)
{}
// Implicit conversion from std::pair<Incrementable,Incrementable> allows us
// to accept the results of std::equal_range(), for example.
half_open_range(const std::pair<Incrementable,Incrementable>& x)
: m_start(x.first),
m_finish(
#ifndef __MWERKS__
detail::choose_finish<category,Incrementable>::choose(x.first, x.second)
#else
detail::choose_finish(x.first, x.second, category())
#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<Incrementable,Incrementable>& x)
{
m_start = x.first;
m_finish =
#ifndef __MWERKS__
detail::choose_finish<category,Incrementable>::choose(x.first, x.second);
#else
detail::choose_finish(x.first, x.second, category();
#endif
}
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<category, std::random_access_iterator_tag>::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<category, std::random_access_iterator_tag>::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<category, std::random_access_iterator_tag>::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<category, std::random_access_iterator_tag>::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<category, std::random_access_iterator_tag>::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<category, std::random_access_iterator_tag>::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 <class Incrementable>
half_open_range<Incrementable> operator|(
half_open_range<Incrementable> x,
const half_open_range<Incrementable>& y)
{
return x |= y;
}
template <class Incrementable>
half_open_range<Incrementable> operator&(
half_open_range<Incrementable> x,
const half_open_range<Incrementable>& y)
{
return x &= y;
}
template <class Incrementable>
inline bool operator==(
const half_open_range<Incrementable>& x,
const half_open_range<Incrementable>& y)
{
const bool y_empty = y.empty();
return x.empty() ? y_empty : !y_empty && x.start() == y.start() && x.finish() == y.finish();
}
template <class Incrementable>
inline bool operator!=(
const half_open_range<Incrementable>& x,
const half_open_range<Incrementable>& y)
{
return !(x == y);
}
template <class Incrementable>
inline half_open_range<Incrementable>
make_half_open_range(Incrementable first, Incrementable last)
{
return half_open_range<Incrementable>(first, last);
}
template <class Incrementable>
bool intersects(
const half_open_range<Incrementable>& x,
const half_open_range<Incrementable>& y)
{
return x.intersects(y);
}
template <class Incrementable>
bool contains(
const half_open_range<Incrementable>& x,
const half_open_range<Incrementable>& y)
{
return x.contains(y);
}
} // namespace boost
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
namespace std {
template <class Incrementable> struct less<boost::half_open_range<Incrementable> >
: binary_function<
boost::half_open_range<Incrementable>,
boost::half_open_range<Incrementable>,bool>
{
bool operator()(
const boost::half_open_range<Incrementable>& x,
const boost::half_open_range<Incrementable>& y) const
{
less<Incrementable> cmp;
return !y.empty() && (
cmp(x.start(), y.start())
|| !cmp(y.start(), x.start())
&& cmp(x.finish(), y.finish()));
}
};
template <class Incrementable> struct less_equal<boost::half_open_range<Incrementable> >
: binary_function<
boost::half_open_range<Incrementable>,
boost::half_open_range<Incrementable>,bool>
{
bool operator()(
const boost::half_open_range<Incrementable>& x,
const boost::half_open_range<Incrementable>& y) const
{
typedef boost::half_open_range<Incrementable> range;
less<range> cmp;
return !cmp(y,x);
}
};
template <class Incrementable> struct greater<boost::half_open_range<Incrementable> >
: binary_function<
boost::half_open_range<Incrementable>,
boost::half_open_range<Incrementable>,bool>
{
bool operator()(
const boost::half_open_range<Incrementable>& x,
const boost::half_open_range<Incrementable>& y) const
{
typedef boost::half_open_range<Incrementable> range;
less<range> cmp;
return cmp(y,x);
}
};
template <class Incrementable> struct greater_equal<boost::half_open_range<Incrementable> >
: binary_function<
boost::half_open_range<Incrementable>,
boost::half_open_range<Incrementable>,bool>
{
bool operator()(
const boost::half_open_range<Incrementable>& x,
const boost::half_open_range<Incrementable>& y) const
{
typedef boost::half_open_range<Incrementable> range;
less<range> 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 <class Incrementable>
bool operator<(const half_open_range<Incrementable>& x,
const half_open_range<Incrementable>& y)
{
return !y.empty() && (
x.empty() || std::less<Incrementable>()(x.start(), y.start())
|| !std::less<Incrementable>()(y.start(), x.start())
&& std::less<Incrementable>()(x.finish(), y.finish()));
}
template <class Incrementable>
bool operator>(const half_open_range<Incrementable>& x,
const half_open_range<Incrementable>& y)
{
return y < x;
}
template <class Incrementable>
bool operator<=(const half_open_range<Incrementable>& x,
const half_open_range<Incrementable>& y)
{
return !(y < x);
}
template <class Incrementable>
bool operator>=(const half_open_range<Incrementable>& x,
const half_open_range<Incrementable>& y)
{
return !(x < y);
}
} // namespace boost
#endif
#endif // BOOST_HALF_OPEN_RANGE_HPP_

View File

@ -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 <cstddef> 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 <iterator>
#include <cstddef> // std::ptrdiff_t
#include <boost/config.hpp>
namespace boost

File diff suppressed because it is too large Load Diff

View File

@ -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) { }
@ -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 <class IntT>
inline int_iterator<IntT>
operator+(IntT n, int_iterator<IntT> t) { t += n; return t; }
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
} /* namespace boost */
#endif

View File

@ -1,52 +1,28 @@
// (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_
#ifdef BOOST_MSVC
#include <boost/pending/detail/int_iterator.hpp>
#else
#include <boost/pending/iterator_adaptors.hpp>
#endif
#include <boost/config.hpp>
#include <boost/counting_iterator.hpp>
namespace boost {
//=============================================================================
// Counting Iterator and Integer Range Class
struct counting_iterator_policies : public default_iterator_policies
{
template <class IntegerType>
IntegerType dereference(type<IntegerType>, const IntegerType& i) const
{ return i; }
};
template <class IntegerType>
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 <class IntegerType>
struct integer_range {
#ifdef BOOST_MSVC
typedef int_iterator<IntegerType> iterator;
#else
typedef iterator_adaptor<IntegerType, counting_iterator_policies,
counting_iterator_traits<IntegerType>, IntegerType> iterator;
#endif
typedef typename counting_iterator_generator<IntegerType>::type iterator;
typedef iterator const_iterator;
typedef IntegerType value_type;
typedef std::ptrdiff_t difference_type;
@ -71,6 +47,13 @@ protected:
IntegerType m_start, m_finish;
};
template <class IntegerType>
inline integer_range<IntegerType>
make_integer_range(IntegerType first, IntegerType last)
{
return integer_range<IntegerType>(first, last);
}
} // namespace boost
#endif // BOOST_INTEGER_RANGE_HPP_

View File

@ -1,510 +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 <iterator>
#include <boost/utility.hpp>
#include <boost/operators.hpp>
#include <boost/compressed_pair.hpp>
// 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 {
// Just a "type envelope"; works around some MSVC deficiencies.
template <class T>
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 <class Reference, class Iterator>
static Reference dereference(type<Reference>, const Iterator& x)
{ return *x; }
template <class Iterator>
static void increment(Iterator& x)
{ ++x; }
template <class Iterator>
static void decrement(Iterator& x)
{ --x; }
template <class Iterator, class DifferenceType>
static void advance(Iterator& x, DifferenceType n)
{ x += n; }
template <class Difference, class Iterator1, class Iterator2>
static Difference distance(type<Difference>, const Iterator1& x, const Iterator2& y)
{ return y - x; }
template <class Iterator1, class Iterator2>
static bool equal(const Iterator1& x, const Iterator2& y)
{ return x == y; }
template <class Iterator1, class Iterator2>
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 <class Derived, class Base>
struct iterator_comparisons : Base { };
template <class D1, class D2, class Base1, class Base2>
inline bool operator==(const iterator_comparisons<D1,Base1>& xb,
const iterator_comparisons<D2,Base2>& yb)
{
const D1& x = static_cast<const D1&>(xb);
const D2& y = static_cast<const D2&>(yb);
return x.policies().equal(x.iter(), y.iter());
}
template <class D1, class D2, class Base1, class Base2>
inline bool operator!=(const iterator_comparisons<D1,Base1>& xb,
const iterator_comparisons<D2,Base2>& yb)
{
const D1& x = static_cast<const D1&>(xb);
const D2& y = static_cast<const D2&>(yb);
return !x.policies().equal(x.iter(), y.iter());
}
template <class D1, class D2, class Base1, class Base2>
inline bool operator<(const iterator_comparisons<D1,Base1>& xb,
const iterator_comparisons<D2,Base2>& yb)
{
const D1& x = static_cast<const D1&>(xb);
const D2& y = static_cast<const D2&>(yb);
return x.policies().less(x.iter(), y.iter());
}
template <class D1, class D2, class Base1, class Base2>
inline bool operator>(const iterator_comparisons<D1,Base1>& xb,
const iterator_comparisons<D2,Base2>& yb)
{
const D1& x = static_cast<const D1&>(xb);
const D2& y = static_cast<const D2&>(yb);
return x.policies().less(y.iter(), x.iter());
}
template <class D1, class D2, class Base1, class Base2>
inline bool operator>=(const iterator_comparisons<D1,Base1>& xb,
const iterator_comparisons<D2,Base2>& yb)
{
const D1& x = static_cast<const D1&>(xb);
const D2& y = static_cast<const D2&>(yb);
return !x.policies().less(x.iter(), y.iter());
}
template <class D1, class D2, class Base1, class Base2>
inline bool operator<=(const iterator_comparisons<D1,Base1>& xb,
const iterator_comparisons<D2,Base2>& yb)
{
const D1& x = static_cast<const D1&>(xb);
const D2& y = static_cast<const D2&>(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 <class Iterator, class Policies,
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
class Traits,
#else
class Traits = std::iterator_traits<Iterator>,
#endif
class NonconstIterator = Iterator
>
struct iterator_adaptor :
#ifdef BOOST_RELOPS_AMBIGUITY_BUG
iterator_comparisons<
iterator_adaptor<Iterator,Policies,Traits,NonconstIterator>,
#endif
boost::iterator<typename Traits::iterator_category,
typename Traits::value_type, typename Traits::difference_type,
typename Traits::pointer, typename Traits::reference>
#ifdef BOOST_RELOPS_AMBIGUITY_BUG
>
#endif
{
typedef iterator_adaptor<Iterator, Policies, Traits,NonconstIterator> 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 <class MutableIterator, class OtherTraits>
iterator_adaptor(const iterator_adaptor<MutableIterator, Policies, OtherTraits, NonconstIterator>& rhs)
: m_iter_p(rhs.iter(), rhs.policies()) {}
template <class MutableIterator, class OtherTraits>
Self& operator=(const iterator_adaptor<MutableIterator, Policies, OtherTraits, NonconstIterator>& rhs)
{
iter() = rhs.iter();
policies() = rhs.policies();
return *this;
}
#else
template <class OtherTraits>
iterator_adaptor(const iterator_adaptor<NonconstIterator, Policies, OtherTraits, NonconstIterator>& rhs)
: m_iter_p(rhs.iter(), rhs.policies()) {}
template <class OtherTraits>
Self& operator=(const iterator_adaptor<NonconstIterator, Policies, OtherTraits, NonconstIterator>& rhs)
{
iter() = rhs.iter();
policies() = rhs.policies();
return *this;
}
#endif
reference operator*() const {
return policies().dereference(type<reference>(), 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<Iterator,Policies> 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 <class Iterator, class Policies, class Traits, class NonconstIterator>
iterator_adaptor<Iterator,Policies,Traits,NonconstIterator>
operator-(iterator_adaptor<Iterator,Policies,Traits,NonconstIterator> p, const typename Traits::difference_type x)
{
return p -= x;
}
template <class Iterator, class Policies, class Traits, class NonconstIterator>
iterator_adaptor<Iterator,Policies,Traits,NonconstIterator>
operator+(iterator_adaptor<Iterator,Policies,Traits,NonconstIterator> p, const typename Traits::difference_type x)
{
return p += x;
}
template <class Iterator, class Policies, class Traits, class NonconstIterator>
iterator_adaptor<Iterator,Policies,Traits,NonconstIterator>
operator+(const typename Traits::difference_type x, iterator_adaptor<Iterator,Policies,Traits,NonconstIterator> p)
{
return p += x;
}
template <class Iterator1, class Iterator2, class Policies, class Traits1, class Traits2, class NonconstIterator>
typename Traits1::difference_type operator-(
const iterator_adaptor<Iterator1,Policies,Traits1,NonconstIterator>& x,
const iterator_adaptor<Iterator2,Policies,Traits2,NonconstIterator>& y )
{
typedef typename Traits1::difference_type difference_type;
return x.policies().distance(type<difference_type>(), y.iter(), x.iter());
}
#ifndef BOOST_RELOPS_AMBIGUITY_BUG
template <class Iterator1, class Iterator2, class Policies, class Traits1, class Traits2, class NonconstIterator>
inline bool
operator==(const iterator_adaptor<Iterator1,Policies,Traits1,NonconstIterator>& x, const iterator_adaptor<Iterator2,Policies,Traits2,NonconstIterator>& y) {
return x.policies().equal(x.iter(), y.iter());
}
template <class Iterator1, class Iterator2, class Policies, class Traits1, class Traits2, class NonconstIterator>
inline bool
operator<(const iterator_adaptor<Iterator1,Policies,Traits1,NonconstIterator>& x, const iterator_adaptor<Iterator2,Policies,Traits2,NonconstIterator>& y) {
return x.policies().less(x.iter(), y.iter());
}
template <class Iterator1, class Iterator2, class Policies, class Traits1, class Traits2, class NonconstIterator>
inline bool
operator>(const iterator_adaptor<Iterator1,Policies,Traits1,NonconstIterator>& x,
const iterator_adaptor<Iterator2,Policies,Traits2,NonconstIterator>& y) {
return x.policies().less(y.iter(), x.iter());
}
template <class Iterator1, class Iterator2, class Policies, class Traits1, class Traits2, class NonconstIterator>
inline bool
operator>=(const iterator_adaptor<Iterator1,Policies,Traits1,NonconstIterator>& x, const iterator_adaptor<Iterator2,Policies,Traits2,NonconstIterator>& y) {
return !x.policies().less(x.iter(), y.iter());
}
template <class Iterator1, class Iterator2, class Policies, class Traits1, class Traits2, class NonconstIterator>
inline bool
operator<=(const iterator_adaptor<Iterator1,Policies,Traits1,NonconstIterator>& x,
const iterator_adaptor<Iterator2,Policies,Traits2,NonconstIterator>& y) {
return !x.policies().less(y.iter(), x.iter());
}
template <class Iterator1, class Iterator2, class Policies, class Traits1, class Traits2, class NonconstIterator>
inline bool
operator!=(const iterator_adaptor<Iterator1,Policies,Traits1,NonconstIterator>& x,
const iterator_adaptor<Iterator2,Policies,Traits2,NonconstIterator>& 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 Iterator, class ConstIterator,
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
class Traits,
class ConstTraits,
#else
class Traits = std::iterator_traits<Iterator>,
class ConstTraits = std::iterator_traits<ConstIterator>,
#endif
class Policies = default_iterator_policies>
class iterator_adaptors
{
public:
typedef iterator_adaptor<Iterator, Policies, Traits, Iterator> iterator;
typedef iterator_adaptor<ConstIterator, Policies, ConstTraits, Iterator>
const_iterator;
};
//=============================================================================
// Transform Iterator Adaptor
template <class AdaptableUnaryFunction>
struct transform_iterator_policies : public default_iterator_policies
{
transform_iterator_policies() { }
transform_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { }
template <class Reference, class Iterator>
Reference dereference(type<Reference>, const Iterator& x) const
{ return m_f(*x); }
AdaptableUnaryFunction m_f;
};
template <class AdaptableUnaryFunction, class IteratorTraits>
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 <class AdaptableUnaryFunction,
class Iterator,
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
class Traits = std::iterator_traits<Iterator>
#else
class Traits
#endif
>
struct transform_iterator
{
typedef transform_iterator_traits<AdaptableUnaryFunction,Traits>
TransTraits;
typedef iterator_adaptor<Iterator,
transform_iterator_policies<AdaptableUnaryFunction>, 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 <class Reference, class Iterator>
Reference dereference(type<Reference>, const Iterator& x) const
{ return **x; }
};
template <class IndirectIterator,
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
class IndirectTraits,
class Traits
#else
class IndirectTraits = std::iterator_traits<IndirectIterator>,
class Traits =
std::iterator_traits<typename IndirectTraits::value_type>
#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 IndirectIterator, class ConstIndirectIterator,
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
class IndirectTraits,
class ConstIndirectTraits,
class Traits
#else
class IndirectTraits =
std::iterator_traits<IndirectIterator>,
class ConstIndirectTraits =
std::iterator_traits<ConstIndirectIterator>,
class Traits =
std::iterator_traits<typename IndirectTraits::value_type>
#endif
>
struct indirect_iterators
{
typedef typename IndirectTraits::value_type Iterator;
typedef typename Traits::value_type ValueType;
typedef iterator_adaptors<IndirectIterator, ConstIndirectIterator,
indirect_traits<IndirectIterator, IndirectTraits, Traits>,
indirect_traits<ConstIndirectIterator, ConstIndirectTraits, 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 <class Reference, class Iterator>
Reference dereference(type<Reference>, const Iterator& x) const
{ return *boost::prior(x); }
template <class Iterator>
void increment(Iterator& x) const
{ --x; }
template <class Iterator>
void decrement(Iterator& x) const
{ ++x; }
template <class Iterator, class DifferenceType>
void advance(Iterator& x, DifferenceType n) const
{ x -= n; }
template <class Difference, class Iterator1, class Iterator2>
Difference distance(type<Difference>, const Iterator1& x,
const Iterator2& y) const
{ return x - y; }
template <class Iterator1, class Iterator2>
bool equal(const Iterator1& x, const Iterator2& y) const
{ return x == y; }
template <class Iterator1, class Iterator2>
bool less(const Iterator1& x, const Iterator2& y) const
{ return y < x; }
};
template <class Iterator, class ConstIterator,
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
class Traits = std::iterator_traits<Iterator>,
class ConstTraits = std::iterator_traits<ConstIterator>
#else
class Traits,
class ConstTraits
#endif
>
struct reverse_iterators
{
typedef iterator_adaptors<Iterator,ConstIterator,Traits,ConstTraits,
reverse_iterator_policies> Adaptor;
typedef typename Adaptor::iterator iterator;
typedef typename Adaptor::const_iterator const_iterator;
};
} // namespace boost
#endif
#include <boost/iterator_adaptors.hpp>

View File

@ -1,16 +1,28 @@
#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.
//
// 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)
#include <assert.h>
# include <iterator>
# include <assert.h>
# include <boost/type_traits.hpp>
# include <boost/static_assert.hpp>
# include <boost/concept_archetype.hpp> // 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; }
@ -22,7 +34,7 @@ struct dummyT {
// TrivialIterator.
// Preconditions: i != j, *i == val
template <class Iterator, class T>
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);
@ -51,7 +63,7 @@ void trivial_iterator_test(Iterator i, Iterator j, T val)
// Preconditions: i != j
template <class Iterator, class T>
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);
@ -82,17 +94,47 @@ void input_iterator_test(Iterator i, T v1, T v2)
// how to test output iterator?
template <bool is_pointer> struct lvalue_test
{
template <class Iterator> static void check(Iterator)
{
# ifndef BOOST_NO_STD_ITERATOR_TRAITS
typedef typename std::iterator_traits<Iterator>::reference reference;
typedef typename std::iterator_traits<Iterator>::value_type value_type;
# else
typedef typename Iterator::reference reference;
typedef typename Iterator::value_type value_type;
# endif
BOOST_STATIC_ASSERT(boost::is_reference<reference>::value);
BOOST_STATIC_ASSERT((boost::is_same<reference,value_type&>::value
|| boost::is_same<reference,const value_type&>::value
));
}
};
# ifdef BOOST_NO_STD_ITERATOR_TRAITS
template <> struct lvalue_test<true> {
template <class T> static void check(T) {}
};
#endif
template <class Iterator, class T>
void forward_iterator_test(Iterator i, T v1, T v2)
{
input_iterator_test(i, v1, v2);
// borland doesn't allow non-type template parameters
# if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
lvalue_test<(boost::is_pointer<Iterator>::value)>::check(i);
#endif
}
// Preconditions: *i == v1, *++i == v2
template <class Iterator, class T>
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;
@ -106,8 +148,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);
@ -120,7 +162,7 @@ template <class Iterator, class TrueVals>
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) {
@ -141,7 +183,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);