Compare commits

..
Author SHA1 Message Date
Dave Abrahams 6ca935d9fe Allow WritableIteratorConcept to be used with one parameter for
iterators with a sensible value_type


[SVN r20904]
2003-11-21 23:39:10 +00:00
Dave Abrahams dea89aa823 Added missing #include
[SVN r20896]
2003-11-20 21:42:38 +00:00
Dave Abrahams ce5d2ec4b4 Reformatting
[SVN r20895]
2003-11-20 21:42:14 +00:00
Dave Abrahams 640379ac34 Better error messages on failure
[SVN r20894]
2003-11-20 21:41:33 +00:00
Dave Abrahams 7cbe926f29 BOOST_TT_BROKEN_COMPILER_SPEC(dummyT) is now supplied with dummyT
[SVN r20893]
2003-11-20 21:41:13 +00:00
Dave Abrahams 5113e4fbec Broken compiler workarounds
[SVN r20892]
2003-11-20 21:40:50 +00:00
Dave Abrahams 66183e43f5 Broaden tests to detect more cases.
[SVN r20891]
2003-11-20 21:40:16 +00:00
Dave Abrahams 4247559960 Broken compiler workarounds, cleanup
[SVN r20890]
2003-11-20 21:38:48 +00:00
Dave Abrahams c7c6448bd5 Make zip_iterator's test run later, because it's failing on a few
compilers still.


[SVN r20889]
2003-11-20 21:38:09 +00:00
Dave Abrahams 218778bb94 Workarounds for broken compilers
[SVN r20886]
2003-11-20 21:17:54 +00:00
Dave Abrahams 4b4de44736 Workarounds for vc6 and vc7
[SVN r20885]
2003-11-20 21:17:00 +00:00
Dave Abrahams 8deb1c20fb Don't adjust default reference type computation based on
BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY


[SVN r20884]
2003-11-20 21:15:31 +00:00
Dave Abrahams 20e6d71755 undo pointless Borland workarounds
[SVN r20883]
2003-11-20 21:14:29 +00:00
Dave Abrahams 52f72c2115 Uncomment mistakenly disabled tests
[SVN r20880]
2003-11-20 16:17:55 +00:00
Dave Abrahams 6b2da49430 Borland workarounds
[SVN r20879]
2003-11-20 16:17:30 +00:00
Dave Abrahams f46f7f8091 vc6 workarounds
[SVN r20869]
2003-11-19 22:04:02 +00:00
Dave Abrahams 22670777b8 Change the way input_output_iterator_tag is convertible to
output_iterator_tag from inheritance to implicit conversion operator,
to avoid some tag dispatch ambiguities.


[SVN r20868]
2003-11-19 22:03:48 +00:00
Dave Abrahams 6270de1db0 ETI workaround
[SVN r20867]
2003-11-19 22:02:36 +00:00
Dave Abrahams 6e06e4f89e Refactored minimum_category
[SVN r20865]
2003-11-19 20:16:52 +00:00
Dave Abrahams eb73b8e0e2 Got everything working with GCC
[SVN r20864]
2003-11-19 20:08:00 +00:00
Dave Abrahams 7ffe2601a9 Commenting and cleanups after a hurried checkin last night
[SVN r20858]
2003-11-19 14:26:43 +00:00
Dave Abrahams 62b70f57a9 progress
[SVN r20853]
2003-11-19 04:25:17 +00:00
Dave Abrahams cd37eb3bfb Modified Files:
Tag: simplify
	iterator_adaptor.hpp iterator_categories.hpp
	iterator_facade.hpp
 Added Files:
  Tag: simplify
 	is_lvalue_iterator.hpp is_readable_iterator.hpp
 	detail/any_conversion_eater.hpp

The above files were moved over from HEAD and will cause confusion during the merge

Got iterator_adaptor_test.cpp working


[SVN r20843]
2003-11-18 04:19:28 +00:00
Dave Abrahams bda5890235 iterator_adaptor_test
[SVN r20842]
2003-11-18 04:08:40 +00:00
nobody d51c5ebf07 This commit was manufactured by cvs2svn to create branch 'simplify'.
[SVN r20841]
2003-11-18 03:04:16 +00:00
Dave Abrahams 6f90b8b161 iterator_categories reformed, test added
[SVN r20829]
2003-11-17 16:52:15 +00:00
Dave Abrahams 6ec791e3b9 checkpoint
[SVN r20733]
2003-11-08 04:12:18 +00:00
Dave Abrahams 20f188d971 progress
[SVN r20167]
2003-09-23 22:58:59 +00:00
Dave Abrahams 7273be17c0 Begun simplification
[SVN r20165]
2003-09-23 02:04:53 +00:00
nobody 77a89a0b89 This commit was manufactured by cvs2svn to create branch 'simplify'.
[SVN r20118]
2003-09-19 18:44:54 +00:00
Dave Abrahams 4968b50fc2 Remove outdated comment; use boost::detail::iterator_traits instead of
std::iterator_traits exclusively.


[SVN r20117]
2003-09-19 18:44:53 +00:00
Dave Abrahams cbeb7f0632 fixed up copyrights, some small progress on new adaptor category choice semantics
[SVN r20047]
2003-09-14 02:17:41 +00:00
Dave Abrahams abf8390020 Fix the implementation of operator_arrow_result so that it checks the
reference type instead of the category.


[SVN r20046]
2003-09-14 01:53:59 +00:00
Dave Abrahams 2c89e2b15a initial commit
[SVN r19978]
2003-09-09 03:22:50 +00:00
Dave Abrahams 3f49409843 Use the import rule
[SVN r19968]
2003-09-08 17:38:49 +00:00
Dave Abrahams abafc5d1be Added missing lambda support for broken compilers
[SVN r19936]
2003-09-06 14:24:01 +00:00
Dave Abrahams 2b7ed5f7a8 Added traversal_category and access_category specializations for MPL lambda support
[SVN r19921]
2003-09-04 21:15:38 +00:00
Dave Abrahams f801c39a59 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]
2003-08-28 20:18:51 +00:00
Dave Abrahams bb7ac6bd84 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]
2003-08-28 16:52:02 +00:00
Jeremy Siek f325582c40 some fixes to writable iterators
[SVN r19609]
2003-08-14 20:05:44 +00:00
Ronald Garcia 36feca8a52 Updated shared_container_iterator to use the new iterator adaptors library.
Updated the documentation and examples as well to reflect the changes.


[SVN r19535]
2003-08-11 16:29:47 +00:00
Dave Abrahams a5179f6dfc clean up formatting
[SVN r19476]
2003-08-06 14:36:16 +00:00
Jeremy Siek f98f3497b8 generated output
[SVN r19468]
2003-08-05 19:48:41 +00:00
Jeremy Siek 76af84c0e7 factoring the specialized iterator adaptors
[SVN r19467]
2003-08-05 19:42:37 +00:00
Jeremy Siek 0f42b93c3b factored iterator adaptor stuff and a few other edits
[SVN r19465]
2003-08-05 18:19:55 +00:00
Jeremy Siek 19977c757f factored iterator facade stuff into several files
[SVN r19464]
2003-08-05 16:36:51 +00:00
Dave Abrahams 508696a169 initial commit
[SVN r19349]
2003-07-29 22:25:39 +00:00
Dave Abrahams 3ab9da6a99 Added dividers
[SVN r19348]
2003-07-29 22:24:57 +00:00
Dave Abrahams bd3312cdf2 Add empty :alt: field for the logo so it doesn't produce document
title text


[SVN r19347]
2003-07-29 21:20:39 +00:00
Dave Abrahams 87f93ec521 initial commit
[SVN r19345]
2003-07-29 16:11:14 +00:00
Thomas Witt afa92675a2 Fixed struct/class mixup in indirect_iterator declaration.
[SVN r19249]
2003-07-22 07:56:08 +00:00
Thomas Witt ed8c60c20b Improved category handling in iterator_adaptor.
[SVN r19231]
2003-07-20 19:18:40 +00:00
Dave Abrahams 3fe0d4b532 * 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]
2003-07-16 19:35:46 +00:00
Beman Dawes 8a51271e3b deque libcomo workaround
[SVN r19143]
2003-07-16 10:36:53 +00:00
Dave Abrahams 52c0d22cff Bugfixes and workarounds
[SVN r19121]
2003-07-14 23:05:57 +00:00
Dave Abrahams e4447b8e83 Bug fix for code not being exercised currently.
[SVN r19118]
2003-07-14 21:31:44 +00:00
Dave Abrahams 42e873e10c 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]
2003-07-14 16:22:10 +00:00
Thomas Witt 57a40c8cd2 Added arg dependent workaround for msvc < 7.1
[SVN r19110]
2003-07-14 13:13:49 +00:00
Dave Abrahams a982c42303 Various updates and clarifications.
[SVN r19106]
2003-07-13 22:47:15 +00:00
Dave Abrahams 9db269bb5b iterator-categories.html is obsolete.
[SVN r19103]
2003-07-13 21:50:30 +00:00
Dave Abrahams e5eaaf6a55 Fix detail::enable_if -> iterators::enable_if (really this time)
^


[SVN r19102]
2003-07-13 21:45:33 +00:00
Dave Abrahams 2225787093 Fix detail::enable_if -> iterator::enable_if
[SVN r19101]
2003-07-13 20:22:47 +00:00
Dave Abrahams f19c1c4059 Moved enable_if to boost::iterators from boost::detail to avoid
conflicting with the definition in the function library.


[SVN r19092]
2003-07-13 01:27:38 +00:00
Dave Abrahams b0aef5a66d Fixup some tables. Restore the equivalence between readable
single-pass iterator and input iterator by restricting the allowed
return type of r++.


[SVN r19091]
2003-07-12 20:16:49 +00:00
Dave Abrahams dfc43d81cf Fix a couple of typos
[SVN r19089]
2003-07-12 16:39:19 +00:00
Jens Maurer eda969d7b5 add "subproject" line
[SVN r19086]
2003-07-12 10:41:38 +00:00
Dave Abrahams 4c8415a99f 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]
2003-07-12 04:15:13 +00:00
Dave Abrahams 1d6f36e35d Move to new iterator adaptors
[SVN r19074]
2003-07-11 22:18:58 +00:00
Dave Abrahams 04301ac6e9 Workaround some CWPro8 bugs
[SVN r19072]
2003-07-11 22:16:52 +00:00
Joel de Guzman a1ec9da737 Moved to boost/iterator (new version)
[SVN r19026]
2003-07-10 12:58:28 +00:00
Joel de Guzman e2a47bdbe5 Moved to boost/iterator
[SVN r19025]
2003-07-10 12:52:06 +00:00
Joel de Guzman 2b1fc22b61 Move to Iterator Adapters from sand-box
[SVN r19024]
2003-07-10 12:49:49 +00:00
Aleksey Gurtovoy 273ec4b975 BOOST_NO_MPL_AUX_HAS_XXX -> BOOST_MPL_NO_AUX_HAS_XXX
[SVN r18974]
2003-07-08 05:10:04 +00:00
Joel de Guzman 4716891117 Move from boost-sandbox
[SVN r18960]
2003-07-07 14:26:16 +00:00
Joel de Guzman 80d9e8e4c1 Move from boost-sandbox
[SVN r18959]
2003-07-07 14:20:34 +00:00
Joel de Guzman 53eb5346de Move from boost-sanbox [ JDG ]
[SVN r18958]
2003-07-07 14:14:36 +00:00
Dave Abrahams e28ca345ea added copyright/license
[SVN r18836]
2003-06-18 13:20:02 +00:00
Dave Abrahams 92d461cda1 Removed unused #include
[SVN r18474]
2003-05-20 23:20:49 +00:00
Beman Dawes 8dace06f04 add or update See www.boost.org comments
[SVN r16708]
2002-12-27 16:51:53 +00:00
Dave Abrahams ef0bff57d3 Use BOOST_WORKAROUND
[SVN r16528]
2002-12-06 19:09:22 +00:00
Dave Abrahams 5bacd289b6 Roll back MPL v2 fix as it's no longer needed and was breaking Borland
[SVN r15264]
2002-09-11 14:46:40 +00:00
Dave Abrahams 77c1698c6e mpl_v2 branch checkin
[SVN r15258]
2002-09-11 05:35:41 +00:00
Dave Abrahams 2c302ee549 operator[] workaround from "Yitzhak Sapir" <yitzhaks@actimize.com>
[SVN r15244]
2002-09-09 21:15:41 +00:00
Ronald Garcia a586f20d19 Added Shared Container Iterator adaptor to iterator adaptor library.
[SVN r15169]
2002-09-05 14:05:29 +00:00
Gennadiy Rozental 34c159dd8d Minor sunpro compartibility fix
[SVN r14741]
2002-08-08 16:42:18 +00:00
Beman Dawes b22a3adc02 Add BOOST_NO_STD_ITERATOR_TRAITS workaround
[SVN r14663]
2002-08-03 22:45:13 +00:00
Dave Abrahams 4a24e0f401 Fixed for VC7.1
[SVN r14433]
2002-07-13 12:11:06 +00:00
Dave Abrahams 3844edc4bf Fixed input iterator requirements. For a == b a++ == b++ is no longer
required. See 24.1.1/3 for details. (Thomas Witt)


[SVN r13716]
2002-05-07 11:56:08 +00:00
John Maddock fdd1601ba4 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]
2002-05-07 11:24:29 +00:00
Toon Knapen e9b33b336c added typename keyword (Bertolt Mildner)
[SVN r13675]
2002-05-06 06:44:14 +00:00
Toon Knapen 2574365b5c added support for reference named_parameters
[SVN r13638]
2002-05-03 13:52:39 +00:00
Jens Maurer 12b9366f33 BOOST_NO_LIMITS should not be used by user code; use <boost/limits.hpp> instead
BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS should not be defined when
BOOST_NO_LIMITS is defined


[SVN r13340]
2002-04-01 18:57:43 +00:00
Jeremy Siek 4772bb099e added more comments in the default_iterator_policies
[SVN r12706]
2002-02-04 20:25:45 +00:00
Dave Abrahams 2be5179020 killed tabs
[SVN r12702]
2002-02-04 20:01:51 +00:00
Douglas Gregor 8cb49713b4 half_open_range.hpp:
- counting_iterator_traits does not contain the iterator traits value_type,
    reference, pointer, etc.


[SVN r12526]
2002-01-27 14:55:20 +00:00
Toon Knapen bd666dc0e9 added include guards
[SVN r12517]
2002-01-26 09:26:09 +00:00
Dave Abrahams 57251d58cc Moved concept checks into a separate class, which makes MSVC better at dealing with them
[SVN r12255]
2002-01-09 12:14:16 +00:00
Dave Abrahams ebcb4d861a Borland workarounds
[SVN r12251]
2002-01-08 18:36:26 +00:00
Dave Abrahams 15a7a839f9 Choose proxy for operator->() only if the reference type is not a reference.
Updated workarounds for __MWERKS__ == 0x2406


[SVN r12245]
2002-01-07 15:43:30 +00:00
Dave Abrahams 76a307d31e fixes
[SVN r12146]
2001-12-24 19:27:39 +00:00
Dave Abrahams 37aee7c13b Re-enabled some STATIC_ASSERTs for MSVC, using bitwise operators to avoid ICEs.
[SVN r12030]
2001-12-13 14:34:11 +00:00
Toon Knapen 50a502bb81 uses proper template argument names : ElementIterator and IndexIterator
[SVN r11826]
2001-11-30 11:14:24 +00:00
Toon Knapen 8a4839354e permutation_iterator_adaptor and generator
[SVN r11823]
2001-11-30 10:38:36 +00:00
Jeremy Siek 4da7371246 *** empty log message ***
[SVN r11611]
2001-11-06 15:52:56 +00:00
Jeremy Siek e162a75e53 *** empty log message ***
[SVN r11609]
2001-11-06 15:28:04 +00:00
Dave Abrahams e60df6ad92 Workarounds for CWPro7, MSVC
Changed all "bind" to "select" (again), to avoid conflicting with Peter Dimov's code.


[SVN r11590]
2001-11-05 16:33:40 +00:00
Dave Abrahams 4c2b3a9d2c Cleanups for MWERKS, without changing functionality
[SVN r11585]
2001-11-05 15:25:45 +00:00
Dave Abrahams 75023a1dd3 Fixed comparison bugs; more remain.
[SVN r11581]
2001-11-05 06:25:31 +00:00
Jeremy Siek 79370a6dfb non-named parameter version of some BGL algorithms
some VC++ compiler stuff


[SVN r11576]
2001-11-04 23:24:12 +00:00
Jeremy Siek 4566798afc iterator adaptor update and related changes
[SVN r11554]
2001-11-04 02:50:10 +00:00
Jeremy Siek 3fd1c4bc5d Changed projection_iterator to not rely on the default reference,
working around a limitation of detail::iterator_traits


[SVN r11340]
2001-10-04 21:02:12 +00:00
Dave Abrahams 2d6f48d5ab Applied indirect_iterator patch from George A. Heintzelman <georgeh@aya.yale.edu>
Changed name of "bind" to "select" to avoid problems with MSVC.


[SVN r11337]
2001-10-04 19:36:28 +00:00
Dave Abrahams d1c7594344 Added borland bug fix
[SVN r11290]
2001-09-27 00:26:01 +00:00
John Maddock ac327f51e9 commit of split-config, including any changes required to existing libraries (mainly regex).
[SVN r11138]
2001-09-18 11:13:39 +00:00
Jeremy Siek 4e18b11263 metrowerks fix for decrement()
[SVN r10997]
2001-09-03 15:38:05 +00:00
Jeremy Siek 81e3df2b36 changed _MSC_VER to BOOST_MSVC
[SVN r10705]
2001-07-25 19:38:41 +00:00
Jeremy Siek ac05307515 added "Traversal" to the names
[SVN r10297]
2001-06-08 17:05:37 +00:00
Jeremy Siek 552a1e6785 replaced by iterator_categories.htm
[SVN r10296]
2001-06-08 16:58:44 +00:00
Jeremy Siek 134b8b51aa updated
[SVN r10295]
2001-06-08 15:37:16 +00:00
Jeremy Siek efecfd17b9 updated to match working group paper
[SVN r10294]
2001-06-08 15:36:30 +00:00
Jeremy Siek 799158841e this is the original
[SVN r10293]
2001-06-08 15:17:14 +00:00
Jeremy Siek 582ebfd054 updated to match changes in the headers
[SVN r10260]
2001-06-03 21:07:46 +00:00
Jeremy Siek 42e4db1539 updated to match my paper to the committee
[SVN r10259]
2001-06-03 21:06:49 +00:00
Beman Dawes d7023154a3 Fix broken hyperlinks
[SVN r9980]
2001-04-25 13:22:53 +00:00
Beman Dawes 9582b2223c Change all eGroups references to YahooGroups
[SVN r9979]
2001-04-25 00:24:50 +00:00
Jeremy Siek d7908fb81f added public before the typedef for "type" in non_bidirectional_category
[SVN r9711]
2001-04-05 02:32:00 +00:00
Jeremy Siek e48cdcb94f blah
[SVN r9588]
2001-03-19 19:35:51 +00:00
Jeremy Siek 0846ad5fd0 added links to iterator_traits.htm
[SVN r9587]
2001-03-19 18:05:17 +00:00
Jeremy Siek 84663ff2e2 added more doc
[SVN r9586]
2001-03-19 18:01:41 +00:00
Jeremy Siek 6de1934420 new file
[SVN r9585]
2001-03-19 17:41:49 +00:00
Jeremy Siek a110b9fd27 new files
[SVN r9578]
2001-03-18 19:06:33 +00:00
Jeremy Siek eb06c122d1 rigged new iterator_traits for backward compatibility
[SVN r9577]
2001-03-18 18:37:49 +00:00
Jeremy Siek cbbe851adb VC++ workaround: the forward_iterator real ref check is not working
[SVN r9499]
2001-03-08 20:01:35 +00:00
Jeremy Siek 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
Jeremy Siek 4e29b5aa29 removed some #if 0's
[SVN r9491]
2001-03-08 17:01:25 +00:00
Jeremy Siek d924f56ad8 added support for optional named template parameters
[SVN r9487]
2001-03-08 16:33:14 +00:00
Jeremy Siek f27fd095f7 new file, part of the iterator adaptors library
[SVN r9350]
2001-02-27 05:49:55 +00:00
Jeremy Siek d22edf735a put policies type in private
[SVN r9290]
2001-02-20 16:00:21 +00:00
Dave Abrahams 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
Dave Abrahams 149d07cda0 Fix missing comma bug
[SVN r9274]
2001-02-19 16:22:03 +00:00
Dave Abrahams e9d9bdbb10 Reinstated reverse_iterator_pair_generator
[SVN r9264]
2001-02-18 22:21:14 +00:00
Jeremy Siek 8d8f828da5 changes to order of indirect_iterator_generator param list
[SVN r9246]
2001-02-17 22:03:06 +00:00
Jeremy Siek fc15f5f710 added Category parameter to the indirect iterator
[SVN r9240]
2001-02-17 19:59:54 +00:00
Jeremy Siek ef66d28b19 added "explicit" to iterator_adaptor constructor
[SVN r9234]
2001-02-17 01:44:41 +00:00
Dave Abrahams 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
Jens Maurer 1c73f1f2ae made filter_iterator_generator::policies_type public
[SVN r9230]
2001-02-16 21:27:26 +00:00
Dave Abrahams ee20a630dd Remove implication that a type generator may only generate a single type
[SVN r9221]
2001-02-16 05:24:45 +00:00
Jeremy Siek 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
Jeremy Siek bf45977491 removed unnecessary typedefs from counting_iterator_traits
[SVN r9203]
2001-02-15 05:51:40 +00:00
Jeremy Siek 1988994bd3 added dummy_constructor to dummyT so it can be used in concept archetypes
[SVN r9181]
2001-02-13 02:03:59 +00:00
Dave Abrahams 5482763a93 added missing const qualifier
[SVN r9148]
2001-02-12 04:45:02 +00:00
Dave Abrahams 2c2a3eab21 Use new iterator_adaptor interface, Fixes for Borland.
[SVN r9131]
2001-02-11 19:36:43 +00:00
Dave Abrahams dca20fae75 Use BOOST_STATIC_CONSTANT
[SVN r9129]
2001-02-11 19:33:47 +00:00
Dave Abrahams e3aaf2cc91 Switch to use of BOOST_STATIC_CONSTANT where possible
[SVN r9127]
2001-02-11 19:29:28 +00:00
Jeremy Siek 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
Dave Abrahams fd6ba58d5e Borland fixes up the wazoo. It finally works!
[SVN r9114]
2001-02-11 16:09:22 +00:00
Dave Abrahams 268e70faa1 Reinstate one of John's fixes
[SVN r9113]
2001-02-11 16:06:12 +00:00
Dave Abrahams 170b44763d Clean up after John Maddocks's (finally effective!) Borland fixes
[SVN r9111]
2001-02-11 14:07:11 +00:00
John Maddock b2701f9f78 Borland compiler fixes
[SVN r9110]
2001-02-11 12:50:06 +00:00
Dave Abrahams ad4c5ab089 Use new iterator_adaptor<> interface
[SVN r9106]
2001-02-11 03:10:01 +00:00
Dave Abrahams 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
Dave Abrahams c5f24d0d72 A baby step that worked.
[SVN r9095]
2001-02-10 23:14:42 +00:00
Dave Abrahams 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
Dave Abrahams 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
Jeremy Siek e9f24023d4 completely removed constructor that was #if 0'd
[SVN r9076]
2001-02-10 17:57:51 +00:00
Jens Maurer 51616fa845 removed superfluous "typename"
[SVN r9068]
2001-02-10 09:34:19 +00:00
Dave Abrahams d7884b5613 *** empty log message ***
[SVN r9066]
2001-02-10 00:35:45 +00:00
Dave Abrahams 15b5b66776 Improved interface to indirect_ and reverse_ iterators
[SVN r9065]
2001-02-10 00:26:55 +00:00
Dave Abrahams 6f90982a45 roll back mistaken changes
[SVN r9062]
2001-02-09 21:04:09 +00:00
Dave Abrahams bfda34e9e0 try a better interface to indirect iterators
[SVN r9060]
2001-02-09 19:26:19 +00:00
Dave Abrahams 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
Dave Abrahams 490bee3a06 Factored out is_numeric computation. Borland still unhappy :(
[SVN r9057]
2001-02-09 15:21:02 +00:00
Dave Abrahams 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
Jeremy Siek 86e183c75e MSVC porting
[SVN r9052]
2001-02-09 05:44:13 +00:00
Jeremy Siek 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
Jeremy Siek 8a73dcd052 Fixed bidirectional iterator test so that --i is no longer a precondition.
[SVN r9048]
2001-02-09 04:29:11 +00:00
Dave Abrahams 8496571204 Fold in Jeremy's improvement to make_reverse_iterator
[SVN r9042]
2001-02-09 03:29:11 +00:00
Dave Abrahams bafe0703a6 Beginning of a failed attempt to appease Borland
[SVN r9041]
2001-02-09 03:27:40 +00:00
Dave Abrahams b05b38810c just whitespace
[SVN r9030]
2001-02-08 04:45:18 +00:00
Jeremy Siek edf17ba001 put indirect_iterator_pair_generator back in
[SVN r9027]
2001-02-08 03:41:23 +00:00
Jeremy Siek 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
Dave Abrahams 762e603013 rename counting_iterator() -> make_counting_iterator()
[SVN r9015]
2001-02-07 22:27:02 +00:00
Dave Abrahams 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
Dave Abrahams 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
Dave Abrahams d17e8dae9b codewarrior bug workaround
[SVN r8989]
2001-02-06 23:59:02 +00:00
Jeremy Siek 5e1bc30db9 1st draft
[SVN r8939]
2001-02-05 05:39:43 +00:00
Jeremy Siek e8389d5f49 start of iterator concept tests
[SVN r8938]
2001-02-05 05:38:44 +00:00
Jeremy Siek 332f18cf9f changed category for transform iterator traits to input iterator
[SVN r8936]
2001-02-04 23:45:57 +00:00
Dave Abrahams 7aea7b7881 Factored counting_iterator stuff into boost/counting_iterator.hpp
[SVN r8935]
2001-02-04 23:37:01 +00:00
Dave Abrahams 3e6796ab91 Fixed lvalue test
[SVN r8934]
2001-02-04 23:35:26 +00:00
Dave Abrahams 893b5c0e25 Moved contents to boost/iterator_adaptors.hpp
[SVN r8933]
2001-02-04 23:34:29 +00:00
Dave Abrahams 41c334d718 MWERKS bug workaround
[SVN r8931]
2001-02-04 20:35:23 +00:00
Dave Abrahams 05336f45c4 Support for user-defined iterator categories
[SVN r8930]
2001-02-04 20:33:45 +00:00
Dave Abrahams 90299982a6 Added counting_iterator_generator; updated comments
[SVN r8928]
2001-02-04 19:38:28 +00:00
Dave Abrahams 93b54c15c8 Inital checkin
[SVN r8927]
2001-02-04 19:11:30 +00:00
Dave Abrahams 25f9acabac corrected preconditions
[SVN r8925]
2001-02-04 19:00:03 +00:00
Dave Abrahams bb2ffadade Added lvalue test
[SVN r8922]
2001-02-04 18:25:55 +00:00
Dave Abrahams b6aa32721f Inital checkin
[SVN r8813]
2001-01-30 16:00:37 +00:00
Jeremy Siek 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
Dave Abrahams 58b56fbabb Initial checkin
[SVN r8757]
2001-01-24 18:36:52 +00:00
Jeremy Siek 9a4b0b576d added filter iterator
[SVN r8735]
2001-01-23 19:09:30 +00:00
Jeremy Siek c948483ec1 added some #ifdefs to prevent compilation of workaround code
[SVN r8688]
2001-01-21 20:28:02 +00:00
Jeremy Siek a31a89ae7d fixed some mwerks compiler errors
[SVN r8683]
2001-01-21 19:33:06 +00:00
Dave Abrahams b8ccd48fa3 Moved type<> to boost/type.hpp
[SVN r8678]
2001-01-21 06:20:20 +00:00
Jeremy Siek cf1d6a30af fixed some warnings under g++
[SVN r8600]
2001-01-15 03:10:11 +00:00
Jeremy Siek 7fa5da6778 fixed dispatch for MIPSpro workaround
[SVN r8599]
2001-01-15 02:51:45 +00:00
Jeremy Siek 34a9d4e702 another MIPSpro workaround
[SVN r8597]
2001-01-14 21:10:44 +00:00
Jeremy Siek 42710d0967 also, advance_impl should take non-const Iter param
[SVN r8595]
2001-01-14 19:23:19 +00:00
Jeremy Siek 487acf8c1c iter() should be i.iter()
[SVN r8594]
2001-01-14 19:21:29 +00:00
Jeremy Siek d6ec67f6ed added version number for MIPSpro
[SVN r8586]
2001-01-14 01:27:01 +00:00
Jeremy Siek e1b64d45e2 MIPSpro port, avoid using operators that are not defined
[SVN r8584]
2001-01-14 01:14:39 +00:00
Jens Maurer 4314dd18ae added <cstddef> for std::ptrdiff_t
[SVN r8562]
2001-01-12 18:50:21 +00:00
Jeremy Siek b634113daf added concept checking classes for purposes of documentation (they don't get invoked)
[SVN r8499]
2000-12-28 03:00:45 +00:00
Jeremy Siek 0c68369f23 changed reference type of counting_iterator to avoid problems on VC++
[SVN r8474]
2000-12-17 21:53:22 +00:00
Jeremy Siek 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
Jeremy Siek e6191bc913 operator[] needed to be const
[SVN r8463]
2000-12-15 19:31:16 +00:00
Jeremy Siek 8cf1b8acb2 forgot #include <iterator>
[SVN r8461]
2000-12-13 23:24:55 +00:00
Jeremy Siek 3852c810f3 various changes, almost forgot to check in
[SVN r8379]
2000-12-03 06:20:23 +00:00
Jeremy Siek 04c0c043e0 added projection iterator to the test
[SVN r8320]
2000-11-24 20:45:26 +00:00
Jeremy Siek ffec5207fa changed names to "Inner" and "Outer"
[SVN r8318]
2000-11-24 20:05:11 +00:00
Jeremy Siek 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
Jeremy Siek 80bcc4e643 some concept checking changes as per review comments
[SVN r8268]
2000-11-20 18:17:52 +00:00
Jeremy Siek 87a3007c92 completed codewarrior workaround
[SVN r8169]
2000-11-10 16:24:39 +00:00
Jeremy Siek 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
Jeremy Siek 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
Jeremy Siek efcbd24229 port to Codewarrior 6.0
[SVN r8107]
2000-11-03 04:25:13 +00:00
Jeremy Siek 3692175786 added base() function
[SVN r8098]
2000-11-02 02:29:53 +00:00
Jeremy Siek d3b8f893bc changed reference type
[SVN r8033]
2000-10-26 14:04:50 +00:00
Jeremy Siek cebe553621 ported the graph library to borland
[SVN r7965]
2000-10-17 00:16:05 +00:00
Jeremy Siek b54236986d work around for VC++ bug, triggered by overloading of remove_edge
[SVN r7860]
2000-09-27 21:02:16 +00:00
Jeremy Siek 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
Jeremy Siek 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
Jeremy Siek c583cf8730 removed tabs
[SVN r7835]
2000-09-25 21:19:29 +00:00
Dave Abrahams 61d2d43ea5 Use iterator adaptors with STLport.
[SVN r7788]
2000-09-24 01:06:34 +00:00
Jeremy Siek 76efd2456c changes for visual c++ port
[SVN r7764]
2000-09-22 04:18:51 +00:00
Jeremy Siek 40b7a3e8aa typo in #include
[SVN r7718]
2000-09-18 09:52:20 +00:00
Jeremy Siek 59a54ab5bd moved integer_range to its own file
[SVN r7717]
2000-09-18 09:49:29 +00:00
Jeremy Siek 7b17be08a2 move integer_range to its own file
[SVN r7716]
2000-09-18 09:47:04 +00:00
Jeremy Siek bbeeb17041 pending stuff from Boost Graph Library
[SVN r7704]
2000-09-18 08:24:47 +00:00
Beman Dawes a8d93ccb41 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]
2000-07-07 16:04:40 +00:00
49 changed files with 3662 additions and 5014 deletions
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

-188
View File
@@ -1,188 +0,0 @@
/*
: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 }
File diff suppressed because it is too large Load Diff
-822
View File
@@ -1,822 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0022)http://internet.e-mail --><HTML><HEAD><TITLE>Improved Iterator Categories and Requirements</TITLE>
<META content="text/html; charset=windows-1252" http-equiv=Content-Type>
<META content="MSHTML 5.00.2919.6307" name=GENERATOR></HEAD>
<BODY bgColor=#ffffff>
<H1>
<CENTER>Improved Iterator Categories and Requirements</CENTER></H1>
<H2>Introduction</H2>The standard iterator categories and requirements are
flawed because they use a single hierarchy of requirements to address two
orthogonal issues: <B><I>iterator traversal</I></B> and <B><I>dereference return
type</I></B>. 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.
<P>
<CENTER>
<TABLE border=1>
<TBODY>
<TR>
<TD>Output Iterator</TD>
<TD><TT>*i = a</TT> </TD></TR>
<TR>
<TD>Input Iterator</TD>
<TD><TT>*i</TT> is convertible to <TT>T</TT></TD></TR>
<TR>
<TD>Forward Iterator</TD>
<TD><TT>*i</TT> is <TT>T&amp;</TT> (or <TT>const T&amp;</TT> once <A
href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#200">issue
200</A> is resolved)</TD></TR>
<TR>
<TD>Random Access Iterator</TD>
<TD><TT>i[n]</TT> is convertible to <TT>T</TT> (which is odd because the
operational semantics say <TT>i[n]</TT> is equivalent to <TT>*(i + n)</TT>
which would have a return type of <TT>T&amp;</TT>) </TD></TR><A name=table:2>
<CAPTION><B>Table 1.</B> Summary of current dereference return type
requirements.</CAPTION></A></TABLE></CENTER>
<H2>Examples of useful iterators that do not ``fit''</H2>
<P>Because of the mixing of iterator traversal and dereference return type, many
useful iterators can not be appropriately categorized. For example,
<TT>vector&lt;bool&gt;::iterator</TT> is almost a random access iterator, but
the return type is not <TT>bool&amp;</TT> (see
<a href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#96">issue 96</a>
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
<TT>random_access_iterator_tag</TT> as its <TT>iterator_category</TT>. Also,
<TT>vector&lt;bool&gt;</TT> is not the only example of useful iterators that do
not return true references: there is the often cited example of disk-based
collections.
<P>Another example is a counting iterator, an iterator the returns a sequence of
integers when incremented and dereferenced (see <A
href="http://www.boost.org/libs/utility/counting_iterator.htm"><TT>boost::counting_iterator</TT></A>).
There are two ways to implement this iterator, 1) make the <TT>reference</TT>
type be a true reference (a reference to an integer data member of the counting
iterator) or 2) make the <TT>reference</TT> type be the same as the
<TT>value_type</TT>. Option 1) runs into the problems discussed in <A
href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#198">Issue
198</A>, 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.
<P>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 <A
href="http://www.boost.org/libs/utility/transform_iterator.htm"><TT>boost::transform_iterator</TT></A>).
For unary functions such as <TT>std::times</TT> the return type of
<TT>operator*</TT> clearly needs to be the <TT>result_type</TT> of the function
object, which is typically not a reference. However, with the current iterator
requirements, if you wrap <TT>int*</TT> with a transform iterator, you do not
get a random access iterator as expected, but an input iterator.
<P>A fourth example is found in the vertex and edge iterators of the <A
href="http://www.boost.org/libs/graph/doc/table_of_contents.html">Boost Graph
Library</A>. 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
<TT>std::input_iterator_tag</TT>, which means that, strictly speaking, you could
not use these iterators with algorithms like <TT>std::min_element()</TT>. As a
temporary solution, we introduced the concept <A
href="http://www.boost.org/libs/utility/MultiPassInputIterator.html">Multi-Pass
Input Iterator</A> to describe the vertex and edge descriptors, but as the
design notes for concept suggest, a better solution is needed.
<P>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:
<UL>
<LI>Iterators are often miss-categorized.
<LI>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. </LI></UL>
<H2>Proposal for new iterator categories and requirements</H2>The iterator
requirements should be separated into two hierarchies. One set of concepts
handles the return type semantics:
<UL>
<LI><A
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:ReadableIterator">Readable
Iterator</A>
<LI><A
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:WritableIterator">Writable
Iterator</A>
<LI><A
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:SwappableIterator">Swappable
Iterator</A>
<LI><A
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:ConstantLvalueIterator">Constant
Lvalue Iterator</A>
<LI><A
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:MutableLvalueIterator">Mutable
Lvalue Iterator</A> </LI></UL>The other set of concepts handles iterator
traversal:
<UL>
<LI><A
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:ForwardTraversalIterator">Forward
Traversal Iterator</A>
<LI><A
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:BidirectionalTraversalIterator">Bidirectional
Traversal Iterator</A>
<LI><A
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:RandomAccessTraversalIterator">Random
Access Traversal Iterator</A> </LI>
</UL>
<P>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.</P>
<P>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.</P>
<H3>New category tags and traits classes</H3>
<P>The new iterator categories will require new tag classes.</P>
<PRE>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 { };
}
</PRE>
<P>Access to the return and traversal tags will be through the
following two traits classes, which have a member typedef named
<TT>type</TT> that provides the tag type. We explain the
definitions of these classes later.</P>
<PRE>
template &lt;typename Iterator&gt;
struct return_category; // contains: typedef ... type;
template &lt;typename Iterator&gt;
struct traversal_category; // contains: typedef ... type;
</PRE>
<P>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 <TT>iterator_category</TT> typedef within
<TT>iterator_traits</TT>.
<PRE>namespace std {
template &lt;class ReturnTag, class TraversalTag&gt;
struct iterator_tag : cvt_iterator_category&lt;ReturnTag, TraversalTag&gt;::type
{
typedef ReturnTag returns;
typedef TraversalTag traversal;
};
</PRE>
<P>The <TT>cvt_iterator_category</TT> template computes the
appropriate old iterator category based on the return and traversal
category.</P>
<PRE>namespace std {
template &lt;class RC, class TC&gt;
struct cvt_iterator_category
{
<B><I>// Pseudo-code, &lt;= means inherits or same type</I></B>
if (RC &lt;= constant_lvalue_iterator_tag || RC &lt;= mutable_lvalue_iterator_tag) {
if (TC &lt;= random_access_traversal_tag)
typedef random_access_iterator_tag type;
else if (TC &lt;= bidirectional_traversal_tag)
typedef bidirectional_iterator_tag type;
else if (TC &lt;= forward_traversal_tag)
typedef forward_iterator_tag type;
else
error;
} else if (RC &lt;= readable_iterator_tag && RC &lt;= input_traversal_tag)
typedef input_iterator_tag type;
else if (RC &lt;= writable_iterator_tag && output_traversal_tag)
typedef output_iterator_tag type;
else
error;
};
}
</PRE>
<P>The following is an example of a new iterator class using the
<TT>iterator_tag</TT> class to create its <TT>iterator_category</TT>
member typedef.</P>
<PRE>
struct my_iterator {
typedef std::iterator_tag&lt;std::readable_iterator_tag,
std::random_access_traversal_tag&gt; iterator_category;
...
};
</PRE>
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 <TT>return_category</TT> and <TT>traversal_category</TT>
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
<TT>iterator_category</TT> tag.
<PRE>
template &lt;typename Iterator&gt;
class return_category
{
<B><I>// Pseudo-code</I></B>
typedef iterator_traits&lt;Iterator&gt;::iterator_category tag;
typedef iterator_traits&lt;Iterator&gt;::value_type T;
public:
if (exists(tag::returns)) // must be a new iterator
typedef tag::returns type;
else if (tag &lt;= forward_iterator_tag) {
if (is-const(T))
typedef constant_lvalue_iterator_tag type;
else
typedef mutable_lvalue_iterator_tag type;
} else if (tag &lt;= input_iterator_tag)
typedef readable_iterator_tag type;
else if (tag &lt;= output_iterator_tag)
typedef writable_iterator_tag type;
else
error;
};
template &lt;typename T&gt;
struct return_category&lt;T*&gt;
{
<B><I>// Pseudo-code</I></B>
if (is-const(T))
typedef boost::constant_lvalue_iterator_tag type;
else
typedef boost::mutable_lvalue_iterator_tag type;
};
template &lt;typename Iterator&gt;
class traversal_category
{
typedef iterator_traits&lt;Iterator&gt;::iterator_category tag;
public:
<B><I>// Pseudo-code</I></B>
if (exists(tag::traversal)) // must be a new iterator
typedef tag::traversal type;
else if (tag &lt;= random_access_iterator_tag)
typedef random_access_traversal_tag type;
else if (tag &lt;= bidirectional_iterator_tag)
typedef bidirectional_traversal_tag type;
else if (tag &lt;= is_forward_iterator_tag)
typedef forward_traversal_tag type;
else if (tag &lt;= input_iterator_tag)
typedef input_traversal_tag type;
else if (tag &lt;= out_iterator_tag)
typedef output_traversal_tag type;
else
error;
};
template &lt;typename T&gt;
struct traversal_category&lt;T*&gt;
{
typedef random_access_traversal_tag type;
};
</PRE>
<H2>Impact on the Standard Algorithms</H2>
<P>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 <TT>std::swap()</TT>
will need to be replaced with <TT>std::iter_swap()</TT>, and
<TT>std::iter_swap()</TT> will need to call <TT>std::swap()</TT>. </P>
<P>
<CENTER>
<TABLE border=1>
<TBODY>
<TR>
<TH>Algorithm</TH>
<TH>Requirement Change</TH></TR>
<TR>
<TD>find_end</TD>
<TD rowSpan=12>Forward Iterator<BR>-&gt; Forward Traversal Iterator and
Readable Iterator </TD></TR>
<TR>
<TD>find_first_of</TD></TR>
<TR>
<TD>adjacent_find</TD></TR>
<TR>
<TD>search</TD></TR>
<TR>
<TD>search_n</TD></TR>
<TR>
<TD>rotate_copy</TD></TR>
<TR>
<TD>lower_bound</TD></TR>
<TR>
<TD>upper_bound</TD></TR>
<TR>
<TD>equal_range</TD></TR>
<TR>
<TD>binary_search</TD></TR>
<TR>
<TD>min_element</TD></TR>
<TR>
<TD>max_element</TD></TR>
<TR>
<TD>iter_swap</TD>
<TD>Forward Iterator<BR>-&gt; Swappable Iterator </TD></TR>
<TR>
<TD>fill</TD>
<TD rowSpan=2>Forward Iterator<BR>-&gt; Forward Traversal Iterator and
Writable Iterator </TD></TR>
<TR>
<TD>generate</TD></TR>
<TR>
<TD>swap_ranges</TD>
<TD rowSpan=2>Forward Iterator<BR>-&gt; Forward Traversal Iterator and
Swappable Iterator </TD></TR>
<TR>
<TD>rotate</TD></TR>
<TR>
<TD>replace</TD>
<TD rowSpan=5>Forward Iterator<BR>-&gt; Forward Traversal Iterator
and<BR>Readable Iterator and Writable Iterator </TD>
<TR>
<TD>replace_if</TD></TR>
<TR>
<TD>remove</TD></TR>
<TR>
<TD>remove_if</TD></TR>
<TR>
<TD>unique</TD></TR>
<TR>
<TD>reverse</TD>
<TD rowSpan=2>Bidirectional Iterator<BR>-&gt; Bidirectional Traversal
Iterator and Swappable Iterator </TD></TR>
<TR>
<TD>partition</TD></TR>
<TR>
<TD>copy_backwards</TD>
<TD>Bidirectional Iterator<BR>-&gt; Bidirectional Traversal Iterator and
Readable Iterator<BR>Bidirectional Iterator<BR>-&gt; Bidirectional
Traversal Iterator and Writable Iterator </TD></TR>
<TR>
<TD>next_permutation</TD>
<TD rowSpan=2>Bidirectional Iterator<BR>-&gt; Bidirectional Traversal
Iterator and <BR>Swappable Iterator and Readable Iterator </TD>
<TR>
<TD>prev_permutation</TD></TR>
<TR>
<TD>stable_partition</TD>
<TD rowSpan=2>Bidirectional Iterator<BR>-&gt; Bidirectional Traversal
Iterator and <BR>Readable Iterator and Writable Iterator </TD>
<TR>
<TD>inplace_merge</TD></TR>
<TR>
<TD>reverse_copy</TD>
<TD>Bidirectional Iterator<BR>-&gt; Bidirectional Traversal Iterator and
Readable Iterator </TD></TR>
<TR>
<TD>random_shuffle</TD>
<TD rowSpan=9>Random Access Iterator<BR>-&gt; Random Access Traversal
Iterator and Swappable Iterator </TD></TR>
<TR>
<TD>sort</TD></TR>
<TR>
<TD>stable_sort</TD></TR>
<TR>
<TD>partial_sort</TD></TR>
<TR>
<TD>nth_element</TD></TR>
<TR>
<TD>push_heap</TD></TR>
<TR>
<TD>pop_heap</TD></TR>
<TR>
<TD>make_heap</TD></TR>
<TR>
<TD>sort_heap</TD></TR><A name=table:2>
<CAPTION><B>Table 2.</B> Requirement changes for standard
algorithms.</CAPTION></A></TABLE></CENTER>
<H2>The New Iterator Requirements</H2>
<H3>Notation</H3>
<TABLE>
<TBODY>
<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>, i.e.,
<TT>std::iterator_traits&lt;X&gt;::value_type</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></TBODY></TABLE>
<P>
<HR>
<!--------------------------------------------------------------------------->
<H3><A name=concept:ReadableIterator></A>Readable Iterator </H3>A Readable
Iterator is an iterator that dereferences to produce an rvalue that is
convertible to the <TT>value_type</TT> of the iterator.
<H3>Associated Types</H3>
<TABLE border=1>
<TBODY>
<TR>
<TD>Value type</TD>
<TD><TT>std::iterator_traits&lt;X&gt;::value_type</TT></TD>
<TD>The type of the objects pointed to by the iterator.</TD></TR>
<TR>
<TD>Reference type</TD>
<TD><TT>std::iterator_traits&lt;X&gt;::reference</TT></TD>
<TD>The return type of dereferencing the iterator. This type must be
convertible to <TT>T</TT>. </TD></TR>
<TR>
<TD>Return Category</TD>
<TD><TT>std::return_category&lt;X&gt;::type</TT></TD>
<TD>A type convertible to <TT>std::readable_iterator_tag</TT>
</TD></TR></TBODY></TABLE>
<H3>Refinement of</H3><A
href="http://www.boost.org/libs/utility/CopyConstructible.html">Copy
Constructible</A>
<H3>Valid expressions</H3>
<TABLE border=1>
<TBODY>
<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>std::iterator_traits&lt;X&gt;::reference</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>If <TT>m</TT> is a data member, the type of <TT>m</TT>. If <TT>m</TT>
is a member function, the return type of <TT>m</TT>. </TD></TR></TBODY></TABLE>
<P>
<HR>
<!--------------------------------------------------------------------------->
<H3><A name=concept:WritableIterator></A>Writable Iterator </H3>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=1>
<TBODY>
<TR>
<TD>Return Category</TD>
<TD><TT>std::return_category&lt;X&gt;::type</TT></TD>
<TD>A type convertible to <TT>std::writable_iterator_tag</TT>
</TD></TR></TBODY></TABLE>
<H3>Refinement of</H3><A
href="http://www.boost.org/libs/utility/CopyConstructible.html">Copy
Constructible</A>
<H3>Valid expressions</H3>
<TABLE border=1>
<TBODY>
<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></TBODY></TABLE>
<P>
<HR>
<!--------------------------------------------------------------------------->
<H3><A name=concept:SwappableIterator></A>Swappable Iterator </H3>A Swappable
Iterator is an iterator whose dereferenced values can be swapped.
<P>Note: the requirements for Swappable Iterator are dependent on the issues
surrounding <TT>std::swap()</TT> being resolved. Here we assume that the issue
will be resolved by allowing the overload of <TT>std::swap()</TT> for
user-defined types.
<P>Note: Readable Iterator and Writable Iterator combined implies Swappable
Iterator because of the fully templated <TT>std::swap()</TT>. However, Swappable
Iterator does not imply Readable Iterator nor Writable Iterator.
<H3>Associated Types</H3>
<TABLE border=1>
<TBODY>
<TR>
<TD>Return Category</TD>
<TD><TT>std::return_category&lt;X&gt;::type</TT></TD>
<TD>A type convertible to <TT>std::swappable_iterator_tag</TT>
</TD></TR></TBODY></TABLE>
<H3>Valid expressions</H3>Of the two valid expressions listed below, only one
<B>OR</B> the other is required. If <TT>std::iter_swap()</TT> is overloaded for
<TT>X</TT> then <TT>std::swap()</TT> is not required. If
<TT>std::iter_swap()</TT> is not overloaded for <TT>X</TT> then the default
(fully templated) version is used, which will call <TT>std::swap()</TT> (this
means changing the current requirements for <TT>std::iter_swap()</TT>).
<P>
<TABLE border=1>
<TBODY>
<TR>
<TH>Name</TH>
<TH>Expression</TH>
<TH>Return type</TH></TR>
<TR>
<TD>Iterator Swap</TD>
<TD><TT>std::iter_swap(x, y)</TT></TD>
<TD>void</TD></TR>
<TR>
<TD>Dereference and Swap</TD>
<TD><TT>std::swap(*x, *y)</TT></TD>
<TD>void</TD></TR></TBODY></TABLE>
<P>
<HR>
<!--------------------------------------------------------------------------->
<H3><A name=concept:ConstantLvalueIterator></A>Constant Lvalue Iterator </H3>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="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:ReadableIterator">Readable
Iterator</A>
<H3>Associated Types</H3>
<TABLE border=1>
<TBODY>
<TR>
<TD>Reference type</TD>
<TD><TT>std::iterator_traits&lt;X&gt;::reference</TT></TD>
<TD>The return type of dereferencing the iterator, which must be <TT>const
T&amp;</TT>. </TD></TR><!-- I don't think this is needed
<tr>
<td>Pointer type</td>
<td><tt>std::iterator_traits&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>std::return_category&lt;X&gt;::type</TT></TD>
<TD>A type convertible to <TT>std::constant_lvalue_iterator_tag</TT>
</TD></TR></TBODY></TABLE><!-- these are not necessary now that we use reference as operator* return type
<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>std::iterator_traits&lt;X&gt;::reference</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>
<!--------------------------------------------------------------------------->
<H3><A name=concept:MutableLvalueIterator></A>Mutable Lvalue Iterator </H3>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="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:ReadableIterator">Readable
Iterator</A>, <A
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:WritableIterator">Writable
Iterator</A>, and <A
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:SwappableIterator">Swappable
Iterator</A>.
<H3>Associated Types</H3>
<TABLE border=1>
<TBODY>
<TR>
<TD>Reference type</TD>
<TD><TT>std::iterator_traits&lt;X&gt;::reference</TT></TD>
<TD>The return type of dereferencing the iterator, which must be
<TT>T&amp;</TT>.</TD></TR><!-- I don't think this is necessary
<tr>
<td>Pointer type</td>
<td><tt>std::iterator_traits&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>std::return_category&lt;X&gt;::type</TT></TD>
<TD>A type convertible to <TT>std::mutable_lvalue_iterator_tag</TT>
</TD></TR></TBODY></TABLE><!-- no longer needed since the return type is specified as reference in the readable iterator
<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>std::iterator_traits&lt;X&gt;::reference</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>
<!--------------------------------------------------------------------------->
<H3><A name=concept:ForwardTraversalIterator></A>Forward Traversal Iterator
</H3>The Forward Iterator is an iterator that can be incremented. Also, it is
permissible to make multiple passes through the iterator's range.
<H3>Refinement of</H3><A
href="http://www.boost.org/libs/utility/CopyConstructible.html">Copy
Constructible</A>, <A
href="http://www.boost.org/libs/utility/Assignable.html">Assignable</A>, <A
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default
Constructible</A>, and <A
href="http://www.sgi.com/tech/stl/EqualityComparable.html">Equality
Comparable</A>
<H3>Associated types</H3>
<TABLE border=1>
<TBODY>
<TR>
<TD>Difference Type</TD>
<TD><TT>std::iterator_traits&lt;X&gt;::difference_type</TT></TD>
<TD>A signed integral type used for representing distances between
iterators that point into the same range. </TD></TR>
<TR>
<TD>Traversal Category</TD>
<TD><TT>std::traversal_category&lt;X&gt;::type</TT></TD>
<TD>A type convertible to <TT>std::forward_traversal_tag</TT>
</TD></TR></TBODY></TABLE>
<H3>Valid expressions</H3>
<TABLE border=1>
<TBODY>
<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>i++</TT></TD>
<TD>&nbsp;</TD>
<TD>convertible to <TT>const X&amp;</TT></TD></TR></TBODY></TABLE>
<P>
<HR>
<!--------------------------------------------------------------------------->
<H3><A name=concept:BidirectionalTraversalIterator></A>Bidirectional Traversal
Iterator </H3>An iterator that can be incremented and decremented.
<H3>Refinement of</H3><A
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:ForwardTraversalIterator">Forward
Traversal Iterator</A>
<H3>Associated types</H3>
<TABLE border=1>
<TBODY>
<TR>
<TD>Traversal Category</TD>
<TD><TT>std::traversal_category&lt;X&gt;::type</TT></TD>
<TD>A type convertible to <TT>std::bidirectional_traversal_tag</TT>
</TD></TR></TBODY></TABLE>
<H3>Valid expressions</H3>
<TABLE border=1>
<TBODY>
<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>convertible to <TT>const X&amp;</TT></TD></TR></TBODY></TABLE>
<P>
<HR>
<!--------------------------------------------------------------------------->
<H3><A name=concept:RandomAccessTraversalIterator></A>Random Access Traversal
Iterator </H3>An iterator that provides constant-time methods for moving forward
and backward in arbitrary-sized steps.
<H3>Refinement of</H3><A
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:BidirectionalTraversalIterator">Bidirectional
Traversal Iterator</A> and <A
href="http://www.sgi.com/tech/stl/LessThanComparable.html">Less Than
Comparable</A> where <TT>&lt;</TT> is a total ordering
<H3>Associated types</H3>
<TABLE border=1>
<TBODY>
<TR>
<TD>Traversal Category</TD>
<TD><TT>std::traversal_category&lt;X&gt;::type</TT></TD>
<TD>A type convertible to <TT>std::random_access_traversal_tag</TT>
</TD></TR></TBODY></TABLE>
<H3>Valid expressions</H3>
<TABLE border=1>
<TBODY>
<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>std::iterator_traits&lt;X&gt;::difference_type</TT></TD></TR>
<TR>
<TD>Element operator</TD>
<TD><TT>i[n]</TT></TD>
<TD><TT>X</TT> must also be a model of <A
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:ReadableIterator">Readable
Iterator</A>. </TD>
<TD><TT>std::iterator_traits&lt;X&gt;::reference</TT></TD></TR>
<TR>
<TD>Element assignment</TD>
<TD><TT>i[n] = t</TT></TD>
<TD><TT>X</TT> must also be a model of <A
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:WritableIterator">Writable
Iterator</A>.</TD>
<TD>unspecified</TD></TR></TBODY></TABLE>
<P>
<HR>
<!-- LocalWords: HTML BGCOLOR FFFFFF TR TD Siek HREF mailto jsiek
--><!-- LocalWords: lsc edu tt const href http anubis dkuug dk JTC SC WG docs lt
--><!-- LocalWords: lwg html bool gt Sutter's htm Lvalue namespace std struct
--><!-- LocalWords: lvalue typename OldTraits reusability min iter prev inplace
--><!-- LocalWords: rvalue templated Preincrement Postincrement Predecrement
--><!-- LocalWords: Postdecrement
--></BODY></HTML>
-731
View File
@@ -1,731 +0,0 @@
++++++++++++++++++++++
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<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``.
.. _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<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 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<X>::value_type`` | ``T`` | Any non-reference, non-cv-qualified type |
+--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+
| ``iterator_traits<X>::reference`` | Convertible to ``iterator_traits<X>::value_type`` | |
+--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+
| ``access_category<X>::type`` | Convertible to ``readable_iterator_tag`` | |
+--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+
| ``*a`` | ``iterator_traits<X>::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<X>::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<X>::reference`` | ``T&`` | ``T`` is *cv* ``iterator_traits<X>::value_type`` where |
| | | *cv* is an optional cv-qualification |
+------------------------------------+-------------------------------------------------+-----------------------------------------------------------+
| ``access_category<X>::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<X>::reference`` | ``iterator_traits<X>::value_type&`` | |
+--------------------------------------+--------------------------------------------------+------------------------------------------------------------+
| ``access_category<X>::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<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) |
+--------------------------------------+--------------------------------------------------+------------------------------------------------------------+
| Expression | Return Type | Assertion/Note/Precondition/Postcondition |
+======================================+==================================================+============================================================+
| ``++r`` | ``X&`` | ``&r == &++r`` |
+--------------------------------------+--------------------------------------------------+------------------------------------------------------------+
| ``r++`` | convertible to ``const X&`` | ``{ X tmp = r; ++r; return tmp; }`` |
+--------------------------------------+--------------------------------------------------+------------------------------------------------------------+
| ``traversal_category<X>::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<X>::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<X>::difference_type`` | | A signed integral type representing the distance between iterators |
+------------------------------------------+--------------+------------------------------------------------------------------------+
| ``traversal_category<X>::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<X>::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<X>::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<X>::type`` | | |Convertible 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;
};
..
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
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

-1
View File
@@ -1 +0,0 @@
unit-test ia1 : reverse_iterator.cpp : <sysinclude>../../.. <sysinclude>$(BOOST) ;
-16
View File
@@ -1,16 +0,0 @@
#include <boost/iterator/iterator_adaptors.hpp>
#include <boost/cstdlib.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
int x[] = { 1, 2, 3, 4 };
boost::reverse_iterator<int*, int, int&, int*,
boost::iterator_tag<boost::mutable_lvalue_iterator_tag, boost::random_access_traversal_tag>
, std::ptrdiff_t> first(x + 4), last(x);
std::copy(first, last, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}
+36 -19
View File
@@ -15,7 +15,12 @@
namespace boost {
template <class Incrementable, class Category, class Difference> 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<int>::value);
template <class Incrementable, class Category, class Difference>
template <class Incrementable, class CategoryOrTraversal, class Difference>
struct counting_iterator_base
{
typedef typename mpl::apply_if<
is_same<Category, use_default>
typedef typename detail::ia_dflt_help<
CategoryOrTraversal
, mpl::apply_if<
is_numeric<Incrementable>
, mpl::identity<std::random_access_iterator_tag>
, BOOST_ITERATOR_CATEGORY<Incrementable>
, mpl::identity<random_access_traversal_tag>
, iterator_traversal<Incrementable>
>
, mpl::identity<Category>
>::type category;
>::type traversal;
typedef typename mpl::apply_if<
is_same<Difference, use_default>
typedef typename detail::ia_dflt_help<
Difference
, mpl::apply_if<
is_numeric<Incrementable>
, numeric_difference<Incrementable>
, iterator_difference<Incrementable>
>
, mpl::identity<Difference>
>::type difference;
typedef iterator_adaptor<
counting_iterator<Incrementable, Category, Difference> // self
, Incrementable // Base
, Incrementable // value_type
, category
, Incrementable const& // reference
counting_iterator<Incrementable, CategoryOrTraversal, Difference> // 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 <class Incrementable, class Category = use_default, class Difference = use_default>
template <
class Incrementable
, class CategoryOrTraversal = use_default
, class Difference = use_default
>
class counting_iterator
: public detail::counting_iterator_base<Incrementable, Category, Difference>::type
: public detail::counting_iterator_base<
Incrementable, CategoryOrTraversal, Difference
>::type
{
typedef typename detail::counting_iterator_base<Incrementable, Category, Difference>::type super_t;
typedef typename detail::counting_iterator_base<
Incrementable, CategoryOrTraversal, Difference
>::type super_t;
friend class iterator_core_access;
public:
+19
View File
@@ -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 detail {
// This type can be used in traits to "eat" up the one user-defined
// implicit conversion allowed.
struct any_conversion_eater
{
template <class T>
any_conversion_eater(T const&);
};
}} // namespace boost::detail
#endif // ANY_CONVERSION_EATER_DWA20031117_HPP
+1 -338
View File
@@ -1,338 +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 <boost/config.hpp>
# include <boost/iterator/detail/config_def.hpp>
# include <boost/detail/workaround.hpp>
# include <boost/type_traits/is_convertible.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/apply_if.hpp>
# include <boost/mpl/identity.hpp>
# include <boost/mpl/bool.hpp>
# include <boost/mpl/or.hpp>
# include <boost/mpl/and.hpp>
# include <iterator>
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 <class Tag, class T>
struct is_tag
: mpl::or_<
is_convertible<T, Tag>
// Because we can't actually get forward_iterator_tag to
// derive from input_output_iterator_tag, we need this
// case.
, mpl::and_<
is_convertible<T,std::forward_iterator_tag>
, is_convertible<detail::input_output_iterator_tag,Tag>
>
>
{};
# else
template <class Tag, class T>
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 <detail::null_category_tag, std::category> \
: 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<detail::input_output_iterator_tag,std::forward_iterator_tag>
: mpl::true_
{
};
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
struct is_tag<T,T> : 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 <class Tag, class T>
struct is_tag_impl : mpl::false_
{};
// The generalized template dispatches to is_tag_impl because
// is_tag<T,T> and is_tag<some_tag,T> are equally specialized.
// This technique simulates making is_tag<T,T> more-specialized.
template <class Tag, class T>
struct is_tag
: is_tag_impl<Tag, T>
{};
# define BOOST_ITERATOR_DERIVED_TAG1(base, derived) \
BOOST_ITERATOR_DERIVED_TAG1_AUX(base, _, derived)
# define BOOST_ITERATOR_DERIVED_TAG1_AUX(base, underscore, derived) \
template<class T> \
struct is_tag_impl<base##underscore##tag, T> \
: is_tag<derived##underscore##tag, T> \
{ \
};
// Old-style tag relations
template<class T>
struct is_tag_impl<detail::null_category_tag, T>
: mpl::or_<
is_tag<std::output_iterator_tag, T>
, is_tag<std::input_iterator_tag, T>
>
{
};
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<class T>
struct is_tag_impl<readable_iterator_tag, T>
: mpl::or_<
is_tag<readable_lvalue_iterator_tag, T>
, is_tag<readable_writable_iterator_tag, T>
>
{
};
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 <class Tag, class Known, class Else>
struct known_tag
: mpl::apply_if<is_tag<Known,Tag>, mpl::identity<Known>, Else>
{};
template <class Tag>
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 <class Tag>
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<Tag, swappable_iterator_tag>
, mpl::identity<null_category_tag>
, 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 <class T1, class T2>
struct minimum_category
: mpl::apply_if<
is_tag<T1,T2>
, mpl::identity<T1>
, mpl::if_<
is_tag<T2, T1>
, T2
, error_type
>
>
{};
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
// Deal with ETI
template <> struct minimum_category<int, int> { typedef minimum_category type; };
# endif
} // namespace detail
} // namespace boost
#include <boost/iterator/detail/config_undef.hpp>
#endif // BOOST_ITERATOR_DETAIL_CATEGORIES_HPP
#error obsolete
+60 -1
View File
@@ -18,7 +18,66 @@
#include <boost/config.hpp> // for prior
#include <boost/detail/workaround.hpp>
#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 <class T>
no foo(T const&, ...);
template <class T>
char foo(T&, int);
struct value_iterator
{
v operator*() const;
};
template <class T>
struct lvalue_deref_helper
{
static T& x;
enum { value = (sizeof(foo(*x,0)) == 1) };
};
int z2[(lvalue_deref_helper<v*>::value == 1) ? 1 : -1];
int z[(lvalue_deref_helper<value_iterator>::value) == 1 ? -1 : 1 ];
# endif
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
|| BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) \
@@ -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
+2 -2
View File
@@ -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
+214
View File
@@ -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 <boost/iterator/iterator_categories.hpp>
# include <boost/static_assert.hpp>
# include <boost/mpl/or.hpp> // used in iterator_tag inheritance logic
# include <boost/mpl/and.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/apply_if.hpp>
# include <boost/mpl/identity.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/type_traits/is_const.hpp>
# include <boost/type_traits/is_reference.hpp>
# include <boost/type_traits/is_convertible.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/iterator/detail/config_def.hpp> // try to keep this last
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
# include <boost/python/detail/indirect_traits.hpp>
# 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 <class ValueParam, class Reference>
struct iterator_writability_disabled
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic?
: mpl::or_<
is_const<Reference>
, python::detail::is_reference_to_const<Reference>
, is_const<ValueParam>
>
# else
: is_const<ValueParam>
# 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 <class Traversal, class ValueParam, class Reference>
struct iterator_facade_default_category
: mpl::apply_if<
mpl::and_<
is_reference<Reference>
, is_convertible<Traversal,forward_traversal_tag>
>
, mpl::apply_if<
is_convertible<Traversal,random_access_traversal_tag>
, mpl::identity<std::random_access_iterator_tag>
, mpl::if_<
is_convertible<Traversal,bidirectional_traversal_tag>
, std::bidirectional_iterator_tag
, std::forward_iterator_tag
>
>
, typename mpl::apply_if<
mpl::and_<
is_convertible<Traversal, single_pass_traversal_tag>
, mpl::or_< // check for readability
is_same<ValueParam,use_default>
, is_convertible<Reference, ValueParam>
>
>
, mpl::if_<
iterator_writability_disabled<ValueParam,Reference>
, std::input_iterator_tag
, input_output_iterator_tag
>
, mpl::identity<std::output_iterator_tag>
>
>
{
};
// True iff T is convertible to an old-style iterator category.
template <class T>
struct is_iterator_category
: mpl::or_<
is_convertible<T,std::input_iterator_tag>
, is_convertible<T,std::output_iterator_tag>
>
{
};
template <class T>
struct is_iterator_traversal
: is_convertible<T,incrementable_traversal_tag>
{};
//
// 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 <class Category, class Traversal>
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<Category>::type
, Traversal
>::value));
BOOST_STATIC_ASSERT(is_iterator_category<Category>::value);
BOOST_STATIC_ASSERT(!is_iterator_category<Traversal>::value);
BOOST_STATIC_ASSERT(!is_iterator_traversal<Category>::value);
BOOST_STATIC_ASSERT(is_iterator_traversal<Traversal>::value);
# endif
};
// Computes an iterator_category tag whose traversal is Traversal and
// which is appropriate for an iterator
template <class Traversal, class ValueParam, class Reference>
struct facade_iterator_category_impl
{
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
BOOST_STATIC_ASSERT(!is_iterator_category<Traversal>::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<category>::type
>
, category
, iterator_category_with_traversal<category,Traversal>
>::type type;
};
//
// Compute an iterator_category for iterator_facade
//
template <class CategoryOrTraversal, class ValueParam, class Reference>
struct facade_iterator_category
: mpl::apply_if<
is_iterator_category<CategoryOrTraversal>
, mpl::identity<CategoryOrTraversal> // old-style categories are fine as-is
, facade_iterator_category_impl<CategoryOrTraversal,ValueParam,Reference>
>
{
};
}} // namespace boost::detail
# include <boost/iterator/detail/config_undef.hpp>
#endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
+98
View File
@@ -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 <boost/type_traits/is_convertible.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/mpl/aux_/lambda_support.hpp>
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 <bool GreaterEqual, bool LessEqual>
struct minimum_category_impl;
template <class T1, class T2>
struct error_not_related_by_convertibility;
template <>
struct minimum_category_impl<true,false>
{
template <class T1, class T2> struct apply
{
typedef T2 type;
};
};
template <>
struct minimum_category_impl<false,true>
{
template <class T1, class T2> struct apply
{
typedef T1 type;
};
};
template <>
struct minimum_category_impl<true,true>
{
template <class T1, class T2> struct apply
{
BOOST_STATIC_ASSERT((is_same<T1,T2>::value));
typedef T1 type;
};
};
template <>
struct minimum_category_impl<false,false>
{
template <class T1, class T2> struct apply
: error_not_related_by_convertibility<T1,T2>
{
};
};
template <class T1 = mpl::_1, class T2 = mpl::_2>
struct minimum_category
{
typedef minimum_category_impl<
::boost::is_convertible<T1,T2>::value
, ::boost::is_convertible<T2,T1>::value
> outer;
typedef typename outer::template apply<T1,T2> inner;
typedef typename inner::type type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2))
};
template <>
struct minimum_category<mpl::_1,mpl::_2>
{
template <class T1, class T2>
struct apply : minimum_category<T1,T2>
{};
};
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
template <>
struct minimum_category<int,int>
{
typedef int type;
};
# endif
}} // namespace boost::detail
#endif // MINIMUM_CATEGORY_DWA20031119_HPP
+51 -23
View File
@@ -13,37 +13,42 @@
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/static_assert.hpp>
namespace boost
{
template <class Predicate, class Iterator>
class filter_iterator;
namespace detail
{
template <class Iterator>
struct filter_iterator_category
template <class Predicate, class Iterator>
struct filter_iterator_base
{
typedef iterator_tag<
typename access_category<Iterator>::type
, typename minimum_category<
bidirectional_traversal_tag
, typename traversal_category<Iterator>::type
>::type
> type;
typedef iterator_adaptor<
filter_iterator<Predicate, Iterator>
, Iterator
, use_default
, typename mpl::if_<
is_convertible<
typename iterator_traversal<Iterator>::type
, bidirectional_traversal_tag
>
, forward_traversal_tag
, use_default
>::type
> type;
};
} // namespace detail
}
template <class Predicate, class Iterator>
class filter_iterator
: public iterator_adaptor<
filter_iterator<Predicate, Iterator>, Iterator
, use_default
, typename detail::filter_iterator_category<Iterator>::type
>
: public detail::filter_iterator_base<Predicate, Iterator>::type
{
typedef iterator_adaptor<
filter_iterator<Predicate, Iterator>, Iterator
, use_default
, typename detail::filter_iterator_category<Iterator>::type
> super_t;
typedef typename detail::filter_iterator_base<
Predicate, Iterator
>::type super_t;
friend class iterator_core_access;
@@ -57,8 +62,15 @@ namespace boost
}
filter_iterator(Iterator x, Iterator end = Iterator())
: super_t(x), m_predicate(), m_end(end)
: 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<Predicate>::value);
#endif
satisfy_predicate();
}
@@ -104,6 +116,22 @@ namespace boost
return filter_iterator<Predicate,Iterator>(f,x,end);
}
template <class Predicate, class Iterator>
filter_iterator<Predicate,Iterator>
make_filter_iterator(
typename iterators::enable_if<
is_class<Predicate>
, Iterator
>::type x
, Iterator end = Iterator()
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
, Predicate* = 0
#endif
)
{
return filter_iterator<Predicate,Iterator>(x,end);
}
} // namespace boost
#endif // BOOST_FILTER_ITERATOR_23022003THW_HPP
+57 -26
View File
@@ -14,11 +14,16 @@
#include <boost/iterator/iterator_traits.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/python/detail/indirect_traits.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/apply_if.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/aux_/has_xxx.hpp>
#ifdef BOOST_NO_MPL_AUX_HAS_XXX
#ifdef BOOST_MPL_NO_AUX_HAS_XXX
# include <boost/shared_ptr.hpp>
# include <boost/scoped_ptr.hpp>
# include <boost/mpl/bool.hpp>
@@ -30,8 +35,11 @@
namespace boost
{
template <class Iter, class Value, class Category, class Reference, class Difference>
struct indirect_iterator;
class indirect_iterator;
template <class T>
struct referent;
namespace detail
{
struct unspecified {};
@@ -44,7 +52,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)
@@ -79,9 +87,10 @@ namespace boost
: mpl::true_ {};
# endif
// Metafunction returning the nested element_type typedef
// Metafunction accessing the nested ::element_type
template <class T>
struct smart_pointer_value : remove_const<typename T::element_type>
struct element_type
: mpl::identity<typename T::element_type>
{};
template <class T>
@@ -110,37 +119,45 @@ namespace boost
struct not_int
: not_int_impl<T>::template apply<U> {};
template <class Dereferenceable>
struct class_has_element_type
: mpl::and_<
is_class<Dereferenceable>
, has_element_type<Dereferenceable>
>
{};
// If the Value parameter is unspecified, we use this metafunction
// to deduce the default types
template <class Iter, class Value, class Category, class Reference, class Difference>
struct indirect_base
template <class Dereferenceable>
struct default_indirect_value
{
typedef typename iterator_value<Iter>::type dereferenceable;
typedef mpl::and_<
is_class<dereferenceable>
, has_element_type<dereferenceable>
> is_smart_ptr;
typedef typename mpl::apply_if<
is_smart_ptr
, smart_pointer_value<dereferenceable>
, iterator_value<dereferenceable>
>::type value_type;
typedef typename remove_cv<
typename referent<Dereferenceable>::type
>::type referent_t;
typedef typename mpl::if_<
mpl::or_<
is_smart_ptr
, iterator_is_mutable<dereferenceable>
class_has_element_type<Dereferenceable>
, iterator_is_mutable<Dereferenceable>
>
, value_type
, value_type const
>::type cv_value_type;
, referent_t
, referent_t const
>::type type;
};
template <class Iter, class Value, class Category, class Reference, class Difference>
struct indirect_base
{
typedef typename iterator_traits<Iter>::value_type dereferenceable;
typedef iterator_adaptor<
indirect_iterator<Iter, Value, Category, Reference, Difference>
, Iter
, cv_value_type
, typename ia_dflt_help<
Value, default_indirect_value<dereferenceable>
>::type
, Category
, Reference
, Difference
@@ -151,6 +168,20 @@ namespace boost
struct indirect_base<int, int, int, int, int> {};
} // 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<Dereferenceable>::value_type otherwise.
template <class Dereferenceable>
struct referent
: mpl::apply_if<
detail::class_has_element_type<Dereferenceable>
, detail::element_type<Dereferenceable>
, iterator_value<Dereferenceable>
>
{};
template <
class Iterator
, class Value = use_default
+150
View File
@@ -0,0 +1,150 @@
// 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_LVALUE_ITERATOR_DWA2003112_HPP
# define IS_LVALUE_ITERATOR_DWA2003112_HPP
#include <boost/iterator.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/iterator/detail/any_conversion_eater.hpp>
// should be the last #includes
#include <boost/type_traits/detail/bool_trait_def.hpp>
#include <boost/iterator/detail/config_def.hpp>
#ifndef BOOST_NO_IS_CONVERTIBLE
namespace boost {
namespace detail
{
#ifndef BOOST_NO_LVALUE_RETURN_DETECTION
// Calling lvalue_preserver( <expression>, 0 ) returns a reference
// to the expression's result if <expression> is an lvalue, or
// not_an_lvalue() otherwise.
struct not_an_lvalue {};
template <class T>
T& lvalue_preserver(T&, int);
template <class U>
not_an_lvalue lvalue_preserver(U const&, ...);
# define BOOST_LVALUE_PRESERVER(expr) lvalue_preserver(expr,0)
#else
# define BOOST_LVALUE_PRESERVER(expr) expr
#endif
// Guts of is_lvalue_iterator. Value is the iterator's value_type
// and the result is computed in the nested rebind template.
template <class Value>
struct is_lvalue_iterator_impl
{
// Eat implicit conversions so we don't report true for things
// convertible to Value const&
struct conversion_eater
{
conversion_eater(Value&);
};
static char tester(conversion_eater, int);
static char (& tester(any_conversion_eater, ...) )[2];
template <class It>
struct rebind
{
static It& x;
BOOST_STATIC_CONSTANT(
bool
, value = (
sizeof(
is_lvalue_iterator_impl<Value>::tester(
BOOST_LVALUE_PRESERVER(*x), 0
)
) == 1
)
);
};
};
#undef BOOST_LVALUE_PRESERVER
//
// void specializations to handle std input and output iterators
//
template <>
struct is_lvalue_iterator_impl<void>
{
template <class It>
struct rebind : boost::mpl::false_
{};
};
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
template <>
struct is_lvalue_iterator_impl<const void>
{
template <class It>
struct rebind : boost::mpl::false_
{};
};
template <>
struct is_lvalue_iterator_impl<volatile void>
{
template <class It>
struct rebind : boost::mpl::false_
{};
};
template <>
struct is_lvalue_iterator_impl<const volatile void>
{
template <class It>
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 <class It>
struct is_readable_lvalue_iterator_impl
: is_lvalue_iterator_impl<
BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<It>::value_type const
>::template rebind<It>
{};
template <class It>
struct is_non_const_lvalue_iterator_impl
: is_lvalue_iterator_impl<
BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<It>::value_type
>::template rebind<It>
{};
} // namespace detail
// Define the trait with full mpl lambda capability and various broken
// compiler workarounds
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
is_lvalue_iterator,T,::boost::detail::is_readable_lvalue_iterator_impl<T>::value)
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
is_non_const_lvalue_iterator,T,::boost::detail::is_non_const_lvalue_iterator_impl<T>::value)
} // namespace boost
#endif
#include <boost/iterator/detail/config_undef.hpp>
#include <boost/type_traits/detail/bool_trait_undef.hpp>
#endif // IS_LVALUE_ITERATOR_DWA2003112_HPP
+108
View File
@@ -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 <boost/mpl/bool.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/type_traits/detail/bool_trait_def.hpp>
#include <boost/iterator/detail/any_conversion_eater.hpp>
// should be the last #include
#include <boost/iterator/detail/config_def.hpp>
#ifndef BOOST_NO_IS_CONVERTIBLE
namespace boost {
namespace detail
{
// Guts of is_readable_iterator. Value is the iterator's value_type
// and the result is computed in the nested rebind template.
template <class Value>
struct is_readable_iterator_impl
{
static char tester(Value&, int);
static char (& tester(any_conversion_eater, ...) )[2];
template <class It>
struct rebind
{
static It& x;
BOOST_STATIC_CONSTANT(
bool
, value = (
sizeof(
is_readable_iterator_impl<Value>::tester(*x, 1)
) == 1
)
);
};
};
#undef BOOST_READABLE_PRESERVER
//
// void specializations to handle std input and output iterators
//
template <>
struct is_readable_iterator_impl<void>
{
template <class It>
struct rebind : boost::mpl::false_
{};
};
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
template <>
struct is_readable_iterator_impl<const void>
{
template <class It>
struct rebind : boost::mpl::false_
{};
};
template <>
struct is_readable_iterator_impl<volatile void>
{
template <class It>
struct rebind : boost::mpl::false_
{};
};
template <>
struct is_readable_iterator_impl<const volatile void>
{
template <class It>
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 <class It>
struct is_readable_iterator_impl2
: is_readable_iterator_impl<
BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<It>::value_type const
>::template rebind<It>
{};
} // 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<T>::value)
} // namespace boost
#endif
#include <boost/iterator/detail/config_undef.hpp>
#endif // IS_READABLE_ITERATOR_DWA2003112_HPP
+71 -51
View File
@@ -26,12 +26,32 @@
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>
#ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
# include <boost/type_traits/remove_reference.hpp>
#else
# include <boost/type_traits/add_reference.hpp>
#endif
#include <boost/iterator/detail/config_def.hpp>
#include <boost/iterator/iterator_traits.hpp>
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<class To>
struct is_convertible<use_default,To>
: mpl::false_ {};
# endif
namespace detail
{
@@ -98,7 +118,7 @@ namespace boost
// of is_convertible in a few cases.
template<typename From, typename To>
struct enable_if_convertible
: detail::enable_if<
: iterators::enable_if<
mpl::or_<
is_same<From,To>
, is_convertible<From, To>
@@ -111,7 +131,7 @@ namespace boost
template<typename From, typename To>
struct enable_if_convertible
: detail::enable_if<
: iterators::enable_if<
is_convertible<From, To>
, detail::enable_type
>
@@ -142,46 +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 detail::ia_dflt_help<
Category, BOOST_ITERATOR_CATEGORY<Base>
>::type category;
typedef typename detail::ia_dflt_help<
Reference
, mpl::apply_if<
is_same<Value, use_default>
, iterator_reference<Base>
, mpl::identity<Value&>
>
>::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<Reference,use_default>
, iterator_value<Base>
, remove_reference<Reference>
>
>::type
# else
, typename detail::ia_dflt_help<
Value, iterator_value<Base>
>::type
, typename access_category_tag<category, reference>::type
, typename traversal_category_tag<category>::type
, reference
# endif
, typename detail::ia_dflt_help<
Traversal
, iterator_traversal<Base>
>::type
, typename detail::ia_dflt_help<
Reference
, mpl::apply_if<
is_same<Value,use_default>
, iterator_reference<Base>
, add_reference<Value>
>
>::type
, typename detail::ia_dflt_help<
Difference, iterator_difference<Base>
>::type
>
type;
};
template <class T> int static_assert_convertible_to(T);
}
//
@@ -198,8 +223,8 @@ namespace boost
// const. If const, a conforming compiler strips constness for the
// value_type. If not supplied, iterator_traits<Base>::value_type is used
//
// Category - the iterator_category of the resulting iterator. If not
// supplied, iterator_traits<Base>::iterator_category is used.
// Category - the traversal category of the resulting iterator. If not
// supplied, iterator_traversal<Base>::type is used.
//
// Reference - the reference type of the resulting iterator, and in
// particular, the result type of operator*(). If not supplied but
@@ -213,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:
@@ -270,28 +295,26 @@ 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<cat>(my_traversal()))];
// BOOST_STATIC_ASSERT((is_convertible<my_traversal,cat>::value));
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)
);
BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
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)
);
{
BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag)
--m_iterator;
}
@@ -301,12 +324,7 @@ namespace boost
typename super_t::difference_type distance_to(
iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> 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<Derived,OtherDerived>::value)
@@ -314,6 +332,8 @@ namespace boost
return y.base() - m_iterator;
}
# undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL
private: // data members
Base m_iterator;
};
+382 -274
View File
@@ -8,341 +8,449 @@
#define BOOST_ITERATOR_ARCHETYPES_HPP
#include <boost/iterator/iterator_categories.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/operators.hpp>
#include <boost/static_assert.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/detail/facade_iterator_category.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/mpl/aux_/msvc_eti_base.hpp>
#include <boost/mpl/bitand.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/apply_if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/identity.hpp>
#include <cstddef>
namespace boost
namespace boost {
template <class Value, class AccessCategory>
struct access_archetype;
template <class Derived, class Value, class AccessCategory, class TraversalCategory>
struct traversal_archetype;
namespace iterator_archetypes
{
enum {
readable_iterator_bit = 1
, writable_iterator_bit = 2
, swappable_iterator_bit = 4
, lvalue_iterator_bit = 8
};
template <class Value, class AccessCategory>
struct access_archetype;
// Not quite tags, since dispatching wouldn't work.
typedef mpl::int_<readable_iterator_bit>::type readable_iterator_t;
typedef mpl::int_<writable_iterator_bit>::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_<swappable_iterator_bit>::type swappable_iterator_t;
typedef mpl::int_<lvalue_iterator_bit>::type lvalue_iterator_t;
template <class Derived, class Value, class AccessCategory, class TraversalCategory>
struct traversal_archetype;
template <class Derived, class Base>
struct has_access
: mpl::equal_to<
mpl::bitand_<Derived,Base>
, Base
>
{};
}
namespace detail {
template <class T>
struct assign_proxy
{
namespace detail
{
template <class T>
struct assign_proxy
{
assign_proxy& operator=(T);
};
};
template <class T>
struct read_write_proxy :
assign_proxy<T>
{
template <class T>
struct read_proxy
{
operator T();
};
};
template <class T>
struct arrow_proxy
{
template <class T>
struct read_write_proxy
: assign_proxy<T>
, read_proxy<T>
{
};
template <class T>
struct arrow_proxy
{
T const* operator->() const;
};
};
struct no_operator_brackets {};
struct no_operator_brackets {};
template <class ValueType>
struct readable_operator_brackets
{
ValueType operator[](std::ptrdiff_t n) const;
};
template <class ValueType>
struct readable_operator_brackets
{
read_proxy<ValueType> operator[](std::ptrdiff_t n) const;
};
template <class ValueType>
struct writable_operator_brackets
{
template <class ValueType>
struct writable_operator_brackets
{
read_write_proxy<ValueType> operator[](std::ptrdiff_t n) const;
};
};
template <class Value, class AccessCategory, class TraversalCategory>
struct operator_brackets :
mpl::if_< is_tag<random_access_traversal_tag, TraversalCategory>,
mpl::if_< is_tag<writable_iterator_tag, AccessCategory>,
writable_operator_brackets< Value >,
mpl::if_< is_tag<readable_iterator_tag, AccessCategory>,
readable_operator_brackets<Value>,
no_operator_brackets > >,
no_operator_brackets >::type
{
};
template <class Value, class AccessCategory, class TraversalCategory>
struct operator_brackets
: mpl::aux::msvc_eti_base<
typename mpl::apply_if<
is_convertible<TraversalCategory, random_access_traversal_tag>
, mpl::apply_if<
iterator_archetypes::has_access<
AccessCategory
, iterator_archetypes::writable_iterator_t
>
, mpl::identity<writable_operator_brackets<Value> >
, mpl::if_<
iterator_archetypes::has_access<
AccessCategory
, iterator_archetypes::readable_iterator_t
>
, readable_operator_brackets<Value>
, no_operator_brackets
>
>
, mpl::identity<no_operator_brackets>
>::type
>::type
{};
template <class TraversalCategory>
struct traversal_archetype_impl
{
template <class Derived,class Value> struct archetype;
};
template <class TraversalCategory>
struct traversal_archetype_impl
{
template <class Derived,class Value> struct archetype;
};
template <class Derived, class Value, class TraversalCategory>
struct traversal_archetype_
: mpl::aux::msvc_eti_base<
typename traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value>
>::type
{};
template <class Derived, class Value, class TraversalCategory>
struct traversal_archetype_
: mpl::aux::msvc_eti_base<
typename traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value>
>::type
{};
template <>
struct traversal_archetype_impl<incrementable_traversal_tag>
{
template<class Derived, class Value>
struct archetype
{
typedef void difference_type;
template <>
struct traversal_archetype_impl<incrementable_traversal_tag>
{
template<class Derived, class Value>
struct archetype
{
typedef void difference_type;
Derived& operator++();
Derived operator++(int) const;
};
};
Derived& operator++();
Derived operator++(int) const;
};
};
template <>
struct traversal_archetype_impl<single_pass_traversal_tag>
{
template<class Derived, class Value>
struct archetype
: public equality_comparable< traversal_archetype_<Derived, Value, single_pass_traversal_tag> >,
public traversal_archetype_<Derived, Value, incrementable_traversal_tag>
{
};
};
template <>
struct traversal_archetype_impl<single_pass_traversal_tag>
{
template<class Derived, class Value>
struct archetype
: public equality_comparable< traversal_archetype_<Derived, Value, single_pass_traversal_tag> >,
public traversal_archetype_<Derived, Value, incrementable_traversal_tag>
{
};
};
template <class Derived, class Value>
bool operator==(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&);
template <class Derived, class Value>
bool operator==(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&);
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
// doesn't seem to pick up != from equality_comparable
template <class Derived, class Value>
bool operator!=(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&);
template <class Derived, class Value>
bool operator!=(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&);
#endif
template <>
struct traversal_archetype_impl<forward_traversal_tag>
{
template<class Derived, class Value>
struct archetype
: public traversal_archetype_<Derived, Value, single_pass_traversal_tag>
{
typedef std::ptrdiff_t difference_type;
};
};
template <>
struct traversal_archetype_impl<forward_traversal_tag>
{
template<class Derived, class Value>
struct archetype
: public traversal_archetype_<Derived, Value, single_pass_traversal_tag>
{
typedef std::ptrdiff_t difference_type;
};
};
template <>
struct traversal_archetype_impl<bidirectional_traversal_tag>
{
template<class Derived, class Value>
struct archetype
: public traversal_archetype_<Derived, Value, forward_traversal_tag>
{
Derived& operator--();
Derived operator--(int) const;
};
};
template <>
struct traversal_archetype_impl<bidirectional_traversal_tag>
{
template<class Derived, class Value>
struct archetype
: public traversal_archetype_<Derived, Value, forward_traversal_tag>
{
Derived& operator--();
Derived operator--(int) const;
};
};
template <>
struct traversal_archetype_impl<random_access_traversal_tag>
{
template<class Derived, class Value>
struct archetype
: public partially_ordered<traversal_archetype_<Derived, Value, random_access_traversal_tag> >,
public traversal_archetype_<Derived, Value, bidirectional_traversal_tag>
{
Derived& operator+=(std::ptrdiff_t);
Derived& operator-=(std::ptrdiff_t);
};
};
template <>
struct traversal_archetype_impl<random_access_traversal_tag>
{
template<class Derived, class Value>
struct archetype
: public partially_ordered<traversal_archetype_<Derived, Value, random_access_traversal_tag> >,
public traversal_archetype_<Derived, Value, bidirectional_traversal_tag>
{
Derived& operator+=(std::ptrdiff_t);
Derived& operator-=(std::ptrdiff_t);
};
};
template <class Derived, class Value>
Derived& operator+(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
std::ptrdiff_t);
template <class Derived, class Value>
Derived& operator+(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
std::ptrdiff_t);
template <class Derived, class Value>
Derived& operator+(std::ptrdiff_t,
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
template <class Derived, class Value>
Derived& operator+(std::ptrdiff_t,
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
template <class Derived, class Value>
Derived& operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
std::ptrdiff_t);
template <class Derived, class Value>
Derived& operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
std::ptrdiff_t);
template <class Derived, class Value>
std::ptrdiff_t operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
template <class Derived, class Value>
std::ptrdiff_t operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
template <class Derived, class Value>
bool operator<(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
template <class Derived, class Value>
bool operator<(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
struct bogus_type;
struct bogus_type;
template <class Value>
struct convertible_type
: mpl::if_< is_const<Value>,
typename remove_const<Value>::type,
bogus_type >
{};
} // namespace detail
template <class> struct undefined;
template <class AccessCategory>
struct iterator_access_archetype_impl
{
template <class Value> struct archetype;
};
template <class Value, class AccessCategory>
struct iterator_access_archetype
: mpl::aux::msvc_eti_base<
typename iterator_access_archetype_impl<
AccessCategory
>::template archetype<Value>
>::type
{
};
template <>
struct iterator_access_archetype_impl<
iterator_archetypes::readable_iterator_t
>
{
template <class Value>
struct convertible_type
: mpl::if_< is_const<Value>,
typename remove_const<Value>::type,
bogus_type >
{};
struct archetype
{
typedef typename remove_cv<Value>::type value_type;
typedef Value reference;
typedef Value* pointer;
} // namespace detail
value_type operator*() const;
detail::arrow_proxy<Value> operator->() const;
};
};
template <class> struct undefined;
template <class AccessCategory>
struct access_archetype_impl
{
template <class Value> struct archetype;
};
template <class Value, class AccessCategory>
struct access_archetype
: mpl::aux::msvc_eti_base<
typename access_archetype_impl<AccessCategory>::template archetype<Value>
>::type
{
};
template <>
struct access_archetype_impl<readable_iterator_tag>
{
template <class Value>
struct archetype
{
typedef typename remove_cv<Value>::type value_type;
typedef Value reference;
typedef Value* pointer;
value_type operator*() const;
detail::arrow_proxy<Value> operator->() const;
};
};
template <>
struct access_archetype_impl<writable_iterator_tag>
{
template <class Value>
struct archetype
{
template <>
struct iterator_access_archetype_impl<
iterator_archetypes::writable_iterator_t
>
{
template <class Value>
struct archetype
{
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
BOOST_STATIC_ASSERT(!is_const<Value>::value);
BOOST_STATIC_ASSERT(!is_const<Value>::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<Value> operator*() const;
};
};
detail::assign_proxy<Value> operator*() const;
};
};
template <>
struct access_archetype_impl<readable_writable_iterator_tag>
{
template <class Value>
struct archetype
: public virtual access_archetype<Value, readable_iterator_tag>
{
typedef detail::read_write_proxy<Value> reference;
detail::read_write_proxy<Value> operator*() const;
};
};
template <>
struct access_archetype_impl<readable_lvalue_iterator_tag>
{
template <class Value>
struct archetype
: public virtual access_archetype<Value, readable_iterator_tag>
{
typedef Value& reference;
Value& operator*() const;
Value* operator->() const;
};
};
template <>
struct access_archetype_impl<writable_lvalue_iterator_tag>
{
template <class Value>
struct archetype
: public virtual access_archetype<Value, readable_lvalue_iterator_tag>
{
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
BOOST_STATIC_ASSERT((!is_const<Value>::value));
# endif
};
};
template <class Value, class AccessCategory, class TraversalCategory>
struct iterator_archetype;
template <class Value, class AccessCategory, class TraversalCategory>
struct traversal_archetype_base
: detail::operator_brackets<
typename remove_cv<Value>::type
, AccessCategory
, TraversalCategory
>
, detail::traversal_archetype_<
iterator_archetype<Value, AccessCategory, TraversalCategory>
, Value
, TraversalCategory
template <>
struct iterator_access_archetype_impl<
iterator_archetypes::readable_writable_iterator_t
>
{
template <class Value>
struct archetype
: public virtual iterator_access_archetype<
Value, iterator_archetypes::readable_iterator_t
>
{
};
{
typedef detail::read_write_proxy<Value> reference;
template <class Value, class AccessCategory, class TraversalCategory>
struct iterator_archetype
: public traversal_archetype_base<Value, AccessCategory, TraversalCategory>
, public access_archetype<Value, AccessCategory>
detail::read_write_proxy<Value> 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<AccessCategory,TraversalCategory>
, typename access_archetype<Value, AccessCategory>::value_type
, typename traversal_archetype_base<
Value, AccessCategory, TraversalCategory
>::difference_type
>
template <>
struct iterator_access_archetype_impl<iterator_archetypes::readable_lvalue_iterator_t>
{
template <class Value>
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<iterator_archetypes::writable_lvalue_iterator_t>
{
template <class Value>
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>::value));
# endif
};
};
template <class Value, class AccessCategory, class TraversalCategory>
struct iterator_archetype;
template <class Value, class AccessCategory, class TraversalCategory>
struct traversal_archetype_base
: detail::operator_brackets<
typename remove_cv<Value>::type
, AccessCategory
, TraversalCategory
>
, detail::traversal_archetype_<
iterator_archetype<Value, AccessCategory, TraversalCategory>
, Value
, TraversalCategory
>
{
};
namespace detail
{
template <class Value, class AccessCategory, class TraversalCategory>
struct iterator_archetype_base
: iterator_access_archetype<Value, AccessCategory>
, traversal_archetype_base<Value, AccessCategory, TraversalCategory>
{
// Derivation from std::iterator above caused ambiguity, so now
// we have to declare all the types here.
typedef iterator_access_archetype<Value, AccessCategory> access;
typedef typename detail::facade_iterator_category<
TraversalCategory
, typename mpl::apply_if<
iterator_archetypes::has_access<
AccessCategory, iterator_archetypes::writable_iterator_t
>
, remove_const<Value>
, add_const<Value>
>::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 <class Value, class AccessCategory, class TraversalCategory>
struct iterator_archetype
: public detail::iterator_archetype_base<Value, AccessCategory, TraversalCategory>
// 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, AccessCategory>::value_type value_type;
typedef typename access_archetype<Value, AccessCategory>::pointer pointer;
typedef typename access_archetype<Value, AccessCategory>::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<AccessCategory, TraversalCategory> 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<typename detail::convertible_type<Value>::type, AccessCategory, TraversalCategory> const&);
};
// Optional conversion from mutable
// iterator_archetype(iterator_archetype<typename detail::convertible_type<Value>::type, AccessCategory, TraversalCategory> const&);
};
} // namespace boost
+127 -367
View File
@@ -4,399 +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 <boost/config.hpp>
#include <boost/iterator/detail/categories.hpp>
# include <boost/config.hpp>
# include <boost/detail/iterator.hpp>
# include <boost/iterator/detail/config_def.hpp>
#include <boost/type_traits/conversion_traits.hpp>
#include <boost/type_traits/cv_traits.hpp>
# include <boost/detail/workaround.hpp>
#include <boost/python/detail/indirect_traits.hpp>
# include <boost/mpl/apply_if.hpp>
# include <boost/mpl/identity.hpp>
# include <boost/mpl/placeholders.hpp>
# include <boost/mpl/aux_/lambda_support.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/detail/workaround.hpp>
# include <boost/type_traits/is_convertible.hpp>
#include <boost/mpl/apply_if.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/aux_/has_xxx.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/aux_/msvc_eti_base.hpp>
#include <iterator>
#include <boost/iterator/detail/config_def.hpp> // must be last #include
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
# define BOOST_NO_IS_CONVERTIBLE // "Convertible does not provide enough/is not working"
#endif
# include <boost/static_assert.hpp>
namespace boost {
namespace detail
{
// Helper metafunction for std_category below
template <class Cat, class Tag, class Next>
struct match_tag
: mpl::apply_if<is_tag<Tag, Cat>, mpl::identity<Tag>, Next>
{
};
// Converts a possibly user-defined category tag to the
// most-derived standard tag which is a base of that tag.
template <class Category>
struct std_category
: match_tag<
Category, std::random_access_iterator_tag
, match_tag<Category, std::bidirectional_iterator_tag
, match_tag<Category, std::forward_iterator_tag
, match_tag<Category, std::input_iterator_tag
, match_tag<Category, std::output_iterator_tag
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
, mpl::identity<void>
# 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 <class Category> struct std_to_new_tags
# if BOOST_WORKAROUND(BOOST_MSVC, == 1300) // handle ETI
{
typedef void type;
template <class T> struct apply { typedef void type; };
}
# endif
;
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // handle ETI
template <> struct std_to_new_tags<int> {};
# endif
//
// Specializations for specific standard tags
//
template <>
struct std_to_new_tags<std::input_iterator_tag>
{
typedef single_pass_traversal_tag type;
template <class Reference>
struct apply
: mpl::identity<readable_iterator_tag> {};
};
template <>
struct std_to_new_tags<std::output_iterator_tag>
{
typedef incrementable_traversal_tag type;
template <class Reference>
struct apply
: mpl::identity<writable_iterator_tag> {};
};
template <>
struct std_to_new_tags<std::forward_iterator_tag>
{
typedef forward_traversal_tag type;
template <class Reference>
struct apply
: mpl::if_<
python::detail::is_reference_to_const<Reference>
, boost::readable_lvalue_iterator_tag
, boost::writable_lvalue_iterator_tag
>
{};
};
template <>
struct std_to_new_tags<std::bidirectional_iterator_tag>
: std_to_new_tags<std::forward_iterator_tag>
{
typedef bidirectional_traversal_tag type;
};
template <>
struct std_to_new_tags<std::random_access_iterator_tag>
: std_to_new_tags<std::bidirectional_iterator_tag>
{
typedef random_access_traversal_tag type;
};
template <class Category>
struct old_tag_converter
: std_to_new_tags<
typename std_category<Category>::type
>
{
};
template <typename Category>
struct iter_category_to_traversal
: std_to_new_tags<
typename std_category<Category>::type
>
{};
template <typename Category, typename Reference>
struct iter_category_to_access
: mpl::apply1<
iter_category_to_traversal<Category>
, Reference
>
{};
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
// Deal with ETI
template <> struct iter_category_to_access<int, int> {};
template <> struct iter_category_to_traversal<int> {};
# endif
// A metafunction returning true iff T is boost::iterator_tag<R,U>
template <class T>
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 <class Tag>
struct is_new_iterator_tag
: mpl::not_<
mpl::or_<
is_tag<std::input_iterator_tag, Tag>
, is_tag<std::output_iterator_tag, Tag>
>
>
{};
#elif BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
template <class Tag>
struct is_new_iterator_tag
: is_boost_iterator_tag<Tag>
{
};
#else
BOOST_MPL_HAS_XXX_TRAIT_DEF(traversal)
template <class Tag>
struct is_new_iterator_tag
: mpl::if_<
is_class<Tag>
, has_traversal<Tag>
, mpl::false_
>::type
{
};
#endif
} // namespace detail
//
// Traversal Categories
//
struct incrementable_traversal_tag {};
namespace detail {
template <class NewCategoryTag>
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 <class AccessTag>
struct remove_access_writability
: mpl::apply_if<
is_tag<writable_lvalue_iterator_tag, AccessTag>
, mpl::identity<readable_lvalue_iterator_tag>
, mpl::apply_if<
is_tag<readable_writable_iterator_tag, AccessTag>
, mpl::identity<readable_iterator_tag>
, mpl::if_<
is_tag<writable_iterator_tag, AccessTag>
// 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 <class NewCategoryTag, class Reference>
struct new_category_to_access
: mpl::apply_if<
python::detail::is_reference_to_const<Reference>
, remove_access_writability<typename NewCategoryTag::access>
, mpl::identity<typename NewCategoryTag::access>
>
{};
struct forward_traversal_tag
: single_pass_traversal_tag {};
struct bidirectional_traversal_tag
: forward_traversal_tag {};
struct random_access_traversal_tag
: bidirectional_traversal_tag {};
template <class CategoryTag, class Reference>
struct access_category_tag
: mpl::apply_if<
is_new_iterator_tag<CategoryTag>
, new_category_to_access<CategoryTag, Reference>
, iter_category_to_access<CategoryTag, Reference>
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 <class Cat>
struct old_category_to_traversal
: mpl::apply_if<
is_convertible<Cat,std::random_access_iterator_tag>
, mpl::identity<random_access_traversal_tag>
, mpl::apply_if<
is_convertible<Cat,std::bidirectional_iterator_tag>
, mpl::identity<bidirectional_traversal_tag>
, mpl::apply_if<
is_convertible<Cat,std::forward_iterator_tag>
, mpl::identity<forward_traversal_tag>
, mpl::apply_if<
is_convertible<Cat,std::input_iterator_tag>
, mpl::identity<single_pass_traversal_tag>
, mpl::apply_if<
is_convertible<Cat,std::output_iterator_tag>
, mpl::identity<incrementable_traversal_tag>
, void
>
>
>
>
{
};
template <class CategoryTag>
struct traversal_category_tag
: mpl::apply_if<
is_new_iterator_tag<CategoryTag>
, get_traversal_category<CategoryTag>
, iter_category_to_traversal<CategoryTag>
>
{
};
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
// Deal with ETI
template <> struct access_category_tag<int, int> { typedef void type; };
template <> struct traversal_category_tag<int> { 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 <class KnownAccessTag, class KnownTraversalTag>
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<int,int>
: 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 <class Iterator>
struct access_category
: detail::access_category_tag<
typename detail::iterator_traits<Iterator>::iterator_category
, typename detail::iterator_traits<Iterator>::reference>
>
{};
template <class Iterator>
struct traversal_category
: detail::traversal_category_tag<
typename detail::iterator_traits<Iterator>::iterator_category
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
template <>
struct old_category_to_traversal<int>
{
typedef int type;
};
# endif
template <class Traversal>
struct pure_traversal_tag
: mpl::apply_if<
is_convertible<Traversal,random_access_traversal_tag>
, mpl::identity<random_access_traversal_tag>
, mpl::apply_if<
is_convertible<Traversal,bidirectional_traversal_tag>
, mpl::identity<bidirectional_traversal_tag>
, mpl::apply_if<
is_convertible<Traversal,forward_traversal_tag>
, mpl::identity<forward_traversal_tag>
, mpl::apply_if<
is_convertible<Traversal,single_pass_traversal_tag>
, mpl::identity<single_pass_traversal_tag>
, mpl::apply_if<
is_convertible<Traversal,incrementable_traversal_tag>
, mpl::identity<incrementable_traversal_tag>
, void
>
>
>
>
>
{
};
# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <typename T>
struct access_category<T*>
: mpl::if_<
is_const<T>
, readable_lvalue_iterator_tag
, writable_lvalue_iterator_tag>
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
template <>
struct pure_traversal_tag<int>
{
typedef int type;
};
template <typename T>
struct traversal_category<T*>
{
typedef random_access_traversal_tag type;
};
# endif
template <class AccessTag, class TraversalTag>
struct iterator_tag
: detail::iterator_tag_base<
typename detail::max_known_access_tag<AccessTag>::type
, typename detail::max_known_traversal_tag<TraversalTag>::type
>::type
{
typedef AccessTag access;
typedef TraversalTag traversal;
};
} // namespace detail
namespace detail
{
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
struct is_boost_iterator_tag
: mpl::false_ {};
template <class R, class T>
struct is_boost_iterator_tag<iterator_tag<R,T> >
: mpl::true_ {};
# else
//
// Convert an iterator category into a traversal tag
//
template <class Cat>
struct iterator_category_to_traversal
: mpl::apply_if< // if already convertible to a traversal tag, we're done.
is_convertible<Cat,incrementable_traversal_tag>
, mpl::identity<Cat>
, detail::old_category_to_traversal<Cat>
>
{};
// Trait to get an iterator's traversal category
template <class Iterator = mpl::_1>
struct iterator_traversal
: iterator_category_to_traversal<
typename boost::detail::iterator_traits<Iterator>::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.
template <>
struct iterator_traversal<mpl::_1>
{
template <class T>
struct is_boost_iterator_tag
{
typedef char (&yes)[1];
typedef char (&no)[2];
template <class R, class U>
static yes test(mpl::identity<iterator_tag<R,U> >*);
static no test(...);
static mpl::identity<T>* inst;
BOOST_STATIC_CONSTANT(bool, value = sizeof(test(inst)) == sizeof(yes));
typedef mpl::bool_<value> type;
};
struct apply : iterator_traversal<T>
{};
};
template <>
struct iterator_traversal<mpl::_>
: iterator_traversal<mpl::_1>
{};
# endif
}
} // namespace boost
+68 -47
View File
@@ -15,16 +15,20 @@
#include <boost/concept_check.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/static_assert.hpp>
// Use boost::detail::iterator_traits to work around some MSVC/Dinkumware problems.
#include <boost/detail/iterator.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/or.hpp>
#include <boost/static_assert.hpp>
// Use boost/limits to work around missing limits headers on some compilers
#include <boost/limits.hpp>
@@ -56,7 +60,6 @@ namespace boost_concepts {
public:
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits<Iterator>::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits<Iterator>::reference reference;
typedef BOOST_DEDUCED_TYPENAME ::boost::access_category<Iterator>::type access_category;
void constraints() {
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
@@ -64,8 +67,6 @@ namespace boost_concepts {
boost::function_requires<
boost::DefaultConstructibleConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::readable_iterator_tag, access_category>::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 <typename Iterator, typename ValueType>
template <
typename Iterator
, typename ValueType = typename boost::detail::iterator_traits<Iterator>::value_type
>
class WritableIteratorConcept {
public:
typedef typename boost::access_category<Iterator>::type access_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::detail::is_tag<boost::writable_iterator_tag, access_category>::value));
*i = v; // a good alternative could be something like write(x, v)
}
ValueType v;
@@ -95,11 +96,8 @@ namespace boost_concepts {
template <typename Iterator>
class SwappableIteratorConcept {
public:
typedef typename boost::access_category<Iterator>::type access_category;
void constraints() {
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::swappable_iterator_tag, access_category>::value));
std::iter_swap(i1, i2);
}
Iterator i1;
@@ -107,25 +105,25 @@ namespace boost_concepts {
};
template <typename Iterator>
class ReadableLvalueIteratorConcept {
public:
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
typedef typename boost::access_category<Iterator>::type access_category;
class ReadableLvalueIteratorConcept
{
public:
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
void constraints() {
boost::function_requires< ReadableIteratorConcept<Iterator> >();
void constraints()
{
boost::function_requires< ReadableIteratorConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::readable_lvalue_iterator_tag, access_category>::value));
typedef boost::mpl::or_<
boost::is_same<reference, value_type&>,
boost::is_same<reference, value_type const&> > correct_reference;
typedef boost::mpl::or_<
boost::is_same<reference, value_type&>
, boost::is_same<reference, value_type const&>
> 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<Iterator>::value_type value_type;
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
typedef typename boost::access_category<Iterator>::type access_category;
void constraints() {
boost::function_requires<
@@ -145,7 +142,6 @@ namespace boost_concepts {
boost::function_requires<
SwappableIteratorConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::writable_lvalue_iterator_tag, access_category>::value));
BOOST_STATIC_ASSERT((boost::is_same<reference, value_type&>::value));
}
@@ -157,14 +153,19 @@ namespace boost_concepts {
template <typename Iterator>
class IncrementableIteratorConcept {
public:
typedef typename boost::traversal_category<Iterator>::type traversal_category;
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
void constraints() {
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
boost::function_requires<
boost::DefaultConstructibleConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::incrementable_traversal_tag, traversal_category>::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 <typename Iterator>
class SinglePassIteratorConcept {
public:
typedef typename boost::traversal_category<Iterator>::type traversal_category;
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
typedef typename boost::detail::iterator_traits<Iterator>::difference_type difference_type;
void constraints() {
boost::function_requires< IncrementableIteratorConcept<Iterator> >();
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::single_pass_traversal_tag, traversal_category>::value));
BOOST_STATIC_ASSERT(
(boost::is_convertible<
traversal_category
, boost::single_pass_traversal_tag
>::value
));
}
};
template <typename Iterator>
class ForwardTraversalConcept {
public:
typedef typename boost::traversal_category<Iterator>::type traversal_category;
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
typedef typename boost::detail::iterator_traits<Iterator>::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<boost::forward_traversal_tag, traversal_category>::value));
BOOST_STATIC_ASSERT(
(boost::is_convertible<
traversal_category
, boost::forward_traversal_tag
>::value
));
}
};
template <typename Iterator>
class BidirectionalTraversalConcept {
public:
typedef typename boost::traversal_category<Iterator>::type traversal_category;
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
void constraints() {
boost::function_requires< ForwardTraversalConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::bidirectional_traversal_tag, traversal_category>::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 <typename Iterator>
class RandomAccessTraversalConcept {
public:
typedef typename boost::traversal_category<Iterator>::type traversal_category;
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
typedef typename boost::detail::iterator_traits<Iterator>::difference_type
difference_type;
void constraints() {
boost::function_requires< BidirectionalTraversalConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::random_access_traversal_tag, traversal_category>::value));
BOOST_STATIC_ASSERT(
(boost::is_convertible<
traversal_category
, boost::random_access_traversal_tag
>::value
));
i += n;
i = i + n;
@@ -269,7 +290,7 @@ namespace detail
template <typename Iterator1, typename Iterator2>
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
{
Operations<boost::incrementable_traversal_tag>(i1, i2);
Operations<boost::incrementable_traversal_tag>::constraints(i1, i2);
i1 == i2;
i1 != i2;
@@ -326,11 +347,11 @@ namespace detail
class InteroperableConcept
{
public:
typedef typename boost::traversal_category<Iterator>::type traversal_category;
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
typedef typename boost::detail::iterator_traits<Iterator>::difference_type
difference_type;
typedef typename boost::traversal_category<ConstIterator>::type
typedef typename boost::iterator_traversal<ConstIterator>::type
const_traversal_category;
typedef typename boost::detail::iterator_traits<ConstIterator>::difference_type
const_difference_type;
+76 -112
View File
@@ -12,15 +12,17 @@
#include <boost/static_assert.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/iterator/interoperable.hpp>
#include <boost/iterator/detail/facade_iterator_category.hpp>
#include <boost/iterator/detail/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/mpl/apply_if.hpp>
#include <boost/mpl/or.hpp>
@@ -28,12 +30,12 @@
namespace boost
{
// This forward declaration is required for the friend declaration
// in iterator_core_access
template <class I, class V, class TC, class R, class D> class iterator_facade;
struct use_default;
namespace detail
{
//
// enable if for use in operator implementation.
//
@@ -47,7 +49,7 @@ namespace boost
>
struct enable_if_interoperable
#ifndef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
: ::boost::detail::enable_if<
: ::boost::iterators::enable_if<
mpl::or_<
is_convertible<Facade1, Facade2>
, is_convertible<Facade2, Facade1>
@@ -61,59 +63,30 @@ namespace boost
#endif
};
//
// Add const qualification for iterators which are not writable
//
template<class Value, class AccessCategory>
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<class Value, class AccessCategory>
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<AccessCategory, TraversalCategory> iterator_category;
typedef typename facade_iterator_category<
CategoryOrTraversal, ValueParam, Reference
>::type iterator_category;
typedef typename remove_cv<Value>::type value_type;
typedef typename remove_const<ValueParam>::type value_type;
typedef Difference difference_type;
typedef typename const_qualified_ptr<Value, AccessCategory>::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<Reference, use_default>
, typename const_qualified_ref<Value, AccessCategory>::type
, Reference
>::type reference;
typedef typename mpl::apply_if<
detail::iterator_writability_disabled<ValueParam,Reference>
, add_pointer<typename add_const<value_type>::type>
, add_pointer<value_type>
>::type pointer;
# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
&& (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \
|| BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \
@@ -127,7 +100,7 @@ namespace boost
# define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1
typedef
iterator<iterator_category, value_type, difference_type, pointer, reference>
iterator<iterator_category, value_type, Difference, pointer, Reference>
base;
# endif
};
@@ -152,17 +125,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 <class Value, class Category, class Reference, class Pointer>
template <class Value, class Reference, class Pointer>
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<Category,Reference>::type
>
is_reference<Reference>
, Pointer
, operator_arrow_proxy<Value>
>::type type;
@@ -176,16 +146,15 @@ namespace boost
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
// Deal with ETI
template<>
struct operator_arrow_result<int, int, int, int>
struct operator_arrow_result<int, int, int>
{
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 Iterator>
class operator_brackets_proxy
@@ -195,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;
}
@@ -213,28 +182,24 @@ namespace boost
Iterator m_iter;
};
template <class Iterator, class ValueType, class Category, class Reference>
template <class Iterator, class Value, class Reference>
struct operator_brackets_result
{
typedef typename access_category_tag<Category,Reference>::type access_category;
typedef is_tag<writable_iterator_tag, access_category> use_proxy;
typedef typename mpl::if_<
use_proxy
typedef typename mpl::if_<
iterator_writability_disabled<Value,Reference>
, Value
, operator_brackets_proxy<Iterator>
, ValueType
>::type type;
};
template <class Iterator>
operator_brackets_proxy<Iterator> make_operator_brackets_result(Iterator const& iter, mpl::true_)
operator_brackets_proxy<Iterator> make_operator_brackets_result(Iterator const& iter, mpl::false_)
{
return operator_brackets_proxy<Iterator>(iter);
}
template <class Iterator>
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;
}
@@ -243,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<Derived1, V1, AC1, TC1, R1, D1> const& lhs \
, iterator_facade<Derived2, V2, AC2, TC2, R2, D2> 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<Derived1, V1, TC1, R1, D1> const& lhs \
, iterator_facade<Derived2, V2, TC2, R2, D2> const& rhs)
# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \
template <class Derived, class V, class AC, class TC, class R, class D> \
# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \
template <class Derived, class V, class TC, class R, class D> \
prefix Derived operator+ args
//
@@ -277,7 +242,7 @@ namespace boost
public:
# else
template <class I, class V, class AC, class TC, class R, class D> friend class iterator_facade;
template <class I, class V, class TC, class R, class D> friend class iterator_facade;
# define BOOST_ITERATOR_FACADE_RELATION(op) \
BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, bool);
@@ -297,7 +262,7 @@ namespace boost
BOOST_ITERATOR_FACADE_PLUS_HEAD(
friend
, (iterator_facade<Derived, V, AC, TC, R, D> const&
, (iterator_facade<Derived, V, TC, R, D> const&
, typename Derived::difference_type)
)
;
@@ -305,7 +270,7 @@ namespace boost
BOOST_ITERATOR_FACADE_PLUS_HEAD(
friend
, (typename Derived::difference_type
, iterator_facade<Derived, V, AC, TC, R, D> const&)
, iterator_facade<Derived, V, TC, R, D> const&)
)
;
@@ -360,26 +325,21 @@ namespace boost
template <
class Derived // The derived iterator type being constructed
, class Value
, class AccessCategory
, class TraversalCategory
, class Reference = typename detail::const_qualified_ref<Value, AccessCategory>::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<Value, AccessCategory, TraversalCategory, Reference, Difference>
types;
//
// Curiously Recursive Template interface.
// Curiously Recurring Template interface.
//
typedef Derived derived_t;
@@ -393,13 +353,17 @@ namespace boost
return static_cast<Derived const&>(*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
{
@@ -408,7 +372,6 @@ namespace boost
typename detail::operator_arrow_result<
value_type
, iterator_category
, reference
, pointer
>::type
@@ -416,20 +379,21 @@ namespace boost
{
return detail::operator_arrow_result<
value_type
, iterator_category
, reference
, pointer
>::make(*this->derived());
}
typename detail::operator_brackets_result<Derived,value_type,iterator_category,reference>::type
typename detail::operator_brackets_result<Derived,Value,Reference>::type
operator[](difference_type n) const
{
typedef typename
detail::operator_brackets_result<Derived,value_type,iterator_category,reference>::use_proxy
use_proxy;
typedef detail::iterator_writability_disabled<Value,Reference>
not_writable;
return detail::make_operator_brackets_result<Derived>(this->derived() + n, use_proxy());
return detail::make_operator_brackets_result<Derived>(
this->derived() + n
, not_writable()
);
}
Derived& operator++()
@@ -607,13 +571,13 @@ namespace boost
}
BOOST_ITERATOR_FACADE_PLUS((
iterator_facade<Derived, V, AC, TC, R, D> const& i
iterator_facade<Derived, V, TC, R, D> const& i
, typename Derived::difference_type n
))
BOOST_ITERATOR_FACADE_PLUS((
typename Derived::difference_type n
, iterator_facade<Derived, V, AC, TC, R, D> const& i
, iterator_facade<Derived, V, TC, R, D> const& i
))
# undef BOOST_ITERATOR_FACADE_PLUS
# undef BOOST_ITERATOR_FACADE_PLUS_HEAD
View File
+33 -23
View File
@@ -24,15 +24,13 @@
# include <boost/concept_archetype.hpp> // for detail::dummy_constructor
# include <boost/detail/iterator.hpp>
# include <boost/pending/iterator_tests.hpp>
# include <boost/iterator/is_readable_iterator.hpp>
# include <boost/iterator/is_lvalue_iterator.hpp>
# include <boost/iterator/detail/config_def.hpp>
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 <class Iterator, class T>
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<Iterator>::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<Iterator>::value);
# endif
}
template <class Iterator, class T>
@@ -54,7 +56,6 @@ void writable_iterator_test(Iterator i, T v)
{
Iterator i2(i); // Copy Constructible
*i2 = v;
is_writable(typename access_category<Iterator>::type());
}
template <class Iterator>
@@ -65,8 +66,6 @@ void swappable_iterator_test(Iterator i, Iterator j)
iter_swap(i2, j2);
typename detail::iterator_traits<Iterator>::value_type ai = *i, aj = *j;
assert(bi == aj && bj == ai);
typedef typename access_category<Iterator>::type result_category;
is_swappable(result_category());
}
template <class Iterator, class T>
@@ -78,12 +77,14 @@ void constant_lvalue_iterator_test(Iterator i, T v1)
BOOST_STATIC_ASSERT((is_same<const value_type&, reference>::value));
const T& v2 = *i2;
assert(v1 == v2);
typedef typename access_category<Iterator>::type result_category;
is_constant_lvalue(result_category());
# ifndef BOOST_NO_LVALUE_RETURN_DETECTION
BOOST_STATIC_ASSERT(is_lvalue_iterator<Iterator>::value);
BOOST_STATIC_ASSERT(!is_non_const_lvalue_iterator<Iterator>::value);
# endif
}
template <class Iterator, class T>
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<Iterator>::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_type&, reference>::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<Iterator>::type result_category;
is_mutable_lvalue(result_category());
# ifndef BOOST_NO_LVALUE_RETURN_DETECTION
BOOST_STATIC_ASSERT(is_lvalue_iterator<Iterator>::value);
BOOST_STATIC_ASSERT(is_non_const_lvalue_iterator<Iterator>::value);
# endif
}
template <class Iterator, class T>
@@ -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 <class Iterator, class TrueVals>
@@ -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<Iterator>::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<Iterator>::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 <boost/iterator/detail/config_undef.hpp>
#endif // BOOST_NEW_ITERATOR_TESTS_HPP
+67 -51
View File
@@ -14,15 +14,18 @@
#include <boost/iterator/detail/enable_if.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/function_traits.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/type_traits/is_function.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/iterator/detail/config_def.hpp>
namespace boost
{
template <class UnaryFunction, class Iterator, class Reference = use_default, class Value = use_default>
@@ -45,58 +48,39 @@ 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 <class UnaryFunction, class Iterator, class Reference, class Value>
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<UnaryFunction>
>::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<Iterator>::type >::value));
#endif
typedef typename mpl::apply_if<
is_same< Reference, use_default >
, function_object_result<UnaryFunction>
, mpl::identity<Reference>
>::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<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<Iterator>::type
>::type access_category;
public:
typedef iterator_adaptor<
transform_iterator<UnaryFunction, Iterator, Reference, Value>
, Iterator
, cv_value_type
, iterator_tag<
access_category
, typename traversal_category<Iterator>::type
>
, result_type
> type;
public:
typedef iterator_adaptor<
transform_iterator<UnaryFunction, Iterator, Reference, Value>
, Iterator
, cv_value_type
, use_default // Leave the traversal category alone
, reference
> type;
};
}
template <class UnaryFunction, class Iterator, class Reference, class Value>
@@ -115,10 +99,22 @@ namespace boost
transform_iterator(Iterator const& x, UnaryFunction f)
: super_t(x), m_f(f) { }
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<UnaryFunction>::value);
#endif
}
template<class OtherIterator>
transform_iterator(
transform_iterator<UnaryFunction, OtherIterator, Reference, Value> const& t
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
transform_iterator<UnaryFunction, OtherIterator, Reference, Value> const& t
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
)
: super_t(t.base()), m_f(t.functor()) {}
@@ -135,9 +131,27 @@ namespace boost
};
template <class UnaryFunction, class Iterator>
transform_iterator<UnaryFunction, Iterator> make_transform_iterator(Iterator it, UnaryFunction fun)
transform_iterator<UnaryFunction, Iterator>
make_transform_iterator(Iterator it, UnaryFunction fun)
{
return transform_iterator<UnaryFunction, Iterator>(it, fun);
return transform_iterator<UnaryFunction, 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 <class UnaryFunction, class Iterator>
typename iterators::enable_if<
is_class<UnaryFunction> // We should probably find a cheaper test than is_class<>
, transform_iterator<UnaryFunction, Iterator>
>::type
make_transform_iterator(Iterator it)
{
return transform_iterator<UnaryFunction, Iterator>(it, UnaryFunction());
}
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
@@ -151,4 +165,6 @@ namespace boost
} // namespace boost
#include <boost/iterator/detail/config_undef.hpp>
#endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP
+611
View File
@@ -0,0 +1,611 @@
// (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 <stddef.h>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_adaptor.hpp> // for enable_if_convertible
#include <boost/iterator/iterator_categories.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/iterator/detail/minimum_category.hpp>
#include <boost/tuple/tuple.hpp>
#if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
# include <boost/type_traits/remove_cv.hpp>
#endif
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/apply_if.hpp>
#include <boost/mpl/lambda.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
namespace boost {
// Zip iterator forward declaration for zip_iterator_base
template<typename IteratorTuple>
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.
namespace detail
{
// Functors to be used with tuple algorithms
//
template<typename DiffType>
class advance_iterator
{
public:
advance_iterator(DiffType step) : m_step(step) {}
template<typename Iterator>
void operator()(Iterator& it) const
{ it += m_step; }
private:
DiffType m_step;
};
//
struct increment_iterator
{
template<typename Iterator>
void operator()(Iterator& it)
{ ++it; }
};
//
struct decrement_iterator
{
template<typename Iterator>
void operator()(Iterator& it)
{ --it; }
};
//
struct dereference_iterator
{
template<typename Iterator>
struct apply
{
#if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
typedef typename
iterator_traits<
typename boost::remove_cv<Iterator>::type
>::reference
type;
#else
typedef typename
iterator_traits<Iterator>::reference
type;
#endif
};
template<typename Iterator>
typename apply<Iterator>::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<typename Tuple, class UnaryMetaFun>
struct tuple_meta_transform;
template<typename Tuple, class UnaryMetaFun>
struct tuple_meta_transform_impl
{
typedef tuples::cons<
typename mpl::apply1<
typename mpl::lambda<UnaryMetaFun>::type
, typename Tuple::head_type
>::type
, typename tuple_meta_transform<
typename Tuple::tail_type
, UnaryMetaFun
>::type
> type;
};
template<typename Tuple, class UnaryMetaFun>
struct tuple_meta_transform
: mpl::apply_if<
boost::is_same<Tuple, tuples::null_type>
, mpl::identity<tuples::null_type>
, tuple_meta_transform_impl<Tuple, UnaryMetaFun>
>
{
};
// Meta-accumulate algorithm for tuples. Note: The template
// parameter StartType corresponds to the initial value in
// ordinary accumulation.
//
template<class Tuple, class BinaryMetaFun, class StartType>
struct tuple_meta_accumulate;
template<
typename Tuple
, class BinaryMetaFun
, typename StartType
>
struct tuple_meta_accumulate_impl
{
typedef typename mpl::apply2<
typename mpl::lambda<BinaryMetaFun>::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<Tuple, tuples::null_type>
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
, boost::is_same<Tuple,int>
>
#endif
, mpl::identity<StartType>
, 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 <class Arg>
// struct apply
// {
// typedef Arg* type;
// }
//
// template <class Arg>
// Arg* operator()(Arg x);
// };
template<typename Fun>
tuples::null_type BOOST_TUPLE_ALGO(tuple_transform)
(tuples::null_type const&, Fun BOOST_TUPLE_ALGO_TERMINATOR)
{ return tuples::null_type(); }
template<typename Tuple, typename Fun>
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<
BOOST_DEDUCED_TYPENAME Tuple::tail_type
, Fun
>::type transformed_tail_type;
return tuples::cons<
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)
);
}
#ifdef BOOST_TUPLE_ALGO_DISPATCH
template<typename Tuple, typename Fun>
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<typename Fun>
Fun BOOST_TUPLE_ALGO(tuple_for_each)(
tuples::null_type
, Fun f BOOST_TUPLE_ALGO_TERMINATOR
)
{ return f; }
template<typename Tuple, typename Fun>
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<typename Tuple, typename Fun>
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<typename Tuple1, typename Tuple2>
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<typename Iterator>
struct iterator_reference
{
typedef typename iterator_traits<Iterator>::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<mpl::_1>
{
template <class T>
struct apply : iterator_reference<T> {};
};
#endif
// Metafunction to obtain the type of the tuple whose element types
// are the reference types of an iterator tuple.
//
template<typename IteratorTuple>
struct tuple_of_references
: tuple_impl_specific::tuple_meta_transform<
IteratorTuple,
iterator_reference<mpl::_1>
>
{
};
// Metafunction to obtain the minimal traversal tag in a tuple
// of iterators.
//
template<typename IteratorTuple>
struct minimum_traversal_category_in_iterator_tuple
{
typedef typename tuple_impl_specific::tuple_meta_transform<
IteratorTuple
, iterator_traversal<>
>::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<int>
{
typedef int type;
};
#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<typename Arg1, typename Arg2>
struct and_with_two_args
: mpl::and_<Arg1, Arg2>
{
};
# 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<mpl::_1,mpl::_2>
{
template <class A1, class A2>
struct apply : mpl::and_<A1,A2>
{};
};
# endif
///////////////////////////////////////////////////////////////////
//
// Class zip_iterator_base
//
// Builds and exposes the iterator facade type from which the zip
// iterator will be derived.
//
template<typename IteratorTuple>
struct zip_iterator_base
{
private:
// Reference type is the type of the tuple obtained from the
// iterators' reference types.
typedef typename
detail::tuple_of_references<IteratorTuple>::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;
public:
// The iterator facade type from which the zip iterator will
// be derived.
typedef iterator_facade<
zip_iterator<IteratorTuple>,
value_type,
traversal_category,
reference,
difference_type
> type;
};
template <>
struct zip_iterator_base<int>
{
typedef int type;
};
}
/////////////////////////////////////////////////////////////////////
//
// zip_iterator class definition
//
template<typename IteratorTuple>
class zip_iterator :
public detail::zip_iterator_base<IteratorTuple>::type
{
// Typedef super_t as our base class.
typedef typename
detail::zip_iterator_base<IteratorTuple>::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<typename OtherIteratorTuple>
zip_iterator(
const zip_iterator<OtherIteratorTuple>& 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<typename OtherIteratorTuple>
bool equal(const zip_iterator<OtherIteratorTuple>& 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<BOOST_DEDUCED_TYPENAME super_t::difference_type>(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 OtherIteratorTuple>
typename super_t::difference_type distance_to(
const zip_iterator<OtherIteratorTuple>& 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<typename IteratorTuple>
zip_iterator<IteratorTuple>
make_zip_iterator(IteratorTuple t)
{ return zip_iterator<IteratorTuple>(t); }
}
#endif
-13
View File
@@ -1,13 +0,0 @@
// 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_13062003HK_HPP
#define BOOST_ITERATOR_ADAPTOR_13062003HK_HPP
#define BOOST_ITERATOR_ADAPTORS_VERSION 0x0200
#include <boost/iterator/iterator_adaptor.hpp>
#endif // BOOST_ITERATOR_ADAPTOR_13062003HK_HPP
+50 -14
View File
@@ -1,14 +1,50 @@
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 ;
# 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.
subproject libs/iterator/test ;
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 ]
[ run zip_iterator_test.cpp ]
# 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 ]
[ 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 : : : # <stlport-iostream>on
]
[ 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 ]
;
+44
View File
@@ -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 : : : # <stlport-iostream>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 ]
;
+11 -102
View File
@@ -5,15 +5,16 @@
// to its suitability for any purpose.
#include <boost/iterator/iterator_concepts.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/operators.hpp>
#include <boost/static_assert.hpp> // remove
#include <boost/detail/workaround.hpp>
#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,104 +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<tag, std::output_iterator_tag>::value
));
BOOST_STATIC_ASSERT((
boost::is_convertible<tag, std::input_iterator_tag>::value
));
BOOST_STATIC_ASSERT((
!boost::is_convertible<tag, std::forward_iterator_tag>::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<tag, std::output_iterator_tag>::value
));
BOOST_STATIC_ASSERT((
boost::is_convertible<tag, std::input_iterator_tag>::value
));
BOOST_STATIC_ASSERT((
!boost::is_convertible<tag, std::forward_iterator_tag>::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<tag, std::input_iterator_tag>::value
));
BOOST_STATIC_ASSERT((
!boost::is_convertible<tag, std::output_iterator_tag>::value
));
BOOST_STATIC_ASSERT((
!boost::is_convertible<tag, std::forward_iterator_tag>::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<tag>::value));
int test = static_assert_same<tag::access, boost::writable_lvalue_iterator_tag>::value;
test = static_assert_same<tag::traversal, boost::random_access_traversal_tag>::value;
// BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator<new_iterator::iterator_category>::value));
test = static_assert_same<new_iterator::iterator_category::access, boost::writable_lvalue_iterator_tag>::value;
test = static_assert_same<new_iterator::iterator_category::traversal, boost::random_access_traversal_tag>::value;
typedef boost::traversal_category<new_iterator>::type traversal_category;
// BOOST_STATIC_ASSERT(boost::detail::has_traversal<new_iterator::iterator_category>::value);
BOOST_STATIC_ASSERT(boost::detail::is_new_iterator_tag<new_iterator::iterator_category>::value);
test = static_assert_same<traversal_category, boost::random_access_traversal_tag>::value;
(void)test;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
boost::iterator_traversal<new_iterator>::type tc;
boost::random_access_traversal_tag derived = tc;
(void)derived;
boost::function_requires<
boost_concepts::WritableLvalueIteratorConcept<int*> >();
boost::function_requires<
@@ -159,7 +69,6 @@ main()
boost_concepts::ReadableLvalueIteratorConcept<const int*> >();
boost::function_requires<
boost_concepts::RandomAccessTraversalConcept<const int*> >();
#endif
boost::function_requires<
boost_concepts::WritableLvalueIteratorConcept<new_iterator> >();
Executable → Regular
+1 -1
View File
@@ -286,7 +286,7 @@ int main()
# ifndef BOOST_NO_SLIST
test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
# 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));
+8 -15
View File
@@ -7,12 +7,13 @@
#include <boost/iterator/filter_iterator.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/iterator/new_iterator_tests.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <deque>
#include <iostream>
using boost::dummyT;
struct one_or_four
{
bool operator()(dummyT x) const
@@ -21,14 +22,6 @@ struct one_or_four
}
};
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
namespace boost { namespace detail
{
template<> struct iterator_traits<dummyT*>
: ptr_iter_traits<dummyT> {};
}}
#endif
template <class T> struct undefined;
// Test filter iterator
@@ -44,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<filter_iter>::type
>::value
));
BOOST_STATIC_ASSERT(
(!boost::is_convertible<
boost::iterator_traversal<filter_iter>::type
, boost::random_access_traversal_tag
>::value
));
//# endif
+7 -51
View File
@@ -26,6 +26,8 @@
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
#include <boost/type_traits/broken_compiler_spec.hpp>
#include <vector>
#include <stdlib.h>
#include <set>
@@ -36,35 +38,18 @@
// 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 <deque>
# ifdef NO_MUTABLE_CONST_STD_DEQUE_ITERATOR_INTEROPERABILITY
# define NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY
# endif
#else
# define RA_CONTAINER std::vector
# include <vector>
#endif
struct my_iterator_tag : public std::random_access_iterator_tag { };
using boost::dummyT;
typedef RA_CONTAINER<int> storage;
typedef RA_CONTAINER<int*> pointer_ra_container;
BOOST_TT_BROKEN_COMPILER_SPEC(boost::shared_ptr<dummyT>)
typedef std::vector<int> storage;
typedef std::vector<int*> pointer_ra_container;
typedef std::set<storage::iterator> iterator_set;
template <class Container>
@@ -78,36 +63,8 @@ struct indirect_iterator_pair_generator
> const_iterator;
};
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
namespace boost { namespace detail
{
template<> struct iterator_traits<int*>
: ptr_iter_traits<int> {};
template<> struct iterator_traits<dummyT*>
: ptr_iter_traits<dummyT> {};
template<> struct iterator_traits<dummyT*const>
: ptr_iter_traits<dummyT> {};
template<> struct iterator_traits<dummyT const*>
: ptr_iter_traits<dummyT, dummyT const> {};
template<> struct iterator_traits<dummyT**>
: ptr_iter_traits<dummyT*> {};
template<> struct iterator_traits<dummyT*const*>
: ptr_iter_traits<dummyT*const> {};
template<> struct iterator_traits<dummyT const*const*>
: ptr_iter_traits<dummyT const*, dummyT const*const> {};
}}
#endif
void more_indirect_iterator_tests()
{
# if 0
storage store(1000);
std::generate(store.begin(), store.end(), rand);
@@ -177,7 +134,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 +143,7 @@ main()
dummyT(3), dummyT(4), dummyT(5) };
const int N = sizeof(array)/sizeof(dummyT);
typedef RA_CONTAINER<boost::shared_ptr<dummyT> > shared_t;
typedef std::vector<boost::shared_ptr<dummyT> > shared_t;
shared_t shared;
// Concept checks
+145
View File
@@ -0,0 +1,145 @@
// 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 <deque>
#include <iterator>
#include <iostream>
#include <boost/static_assert.hpp>
#include <boost/noncopyable.hpp>
#include <boost/type_traits/broken_compiler_spec.hpp>
#include <boost/iterator/is_lvalue_iterator.hpp>
#include <boost/iterator.hpp>
// Last, for BOOST_NO_LVALUE_RETURN_DETECTION
#include <boost/iterator/detail/config_def.hpp>
struct v
{
v();
~v();
};
BOOST_TT_BROKEN_COMPILER_SPEC(v)
struct value_iterator : boost::iterator<std::input_iterator_tag,v>
{
v operator*() const;
};
struct noncopyable_iterator : boost::iterator<std::forward_iterator_tag,boost::noncopyable>
{
boost::noncopyable const& operator*() const;
};
template <class T>
struct proxy_iterator
: boost::iterator<std::output_iterator_tag,T>
{
typedef T value_type;
#if BOOST_WORKAROUND(__GNUC__, == 2)
typedef boost::iterator<std::input_iterator_tag,value_type> base;
typedef base::iterator_category iterator_category;
typedef base::difference_type difference_type;
typedef base::pointer pointer;
typedef base::reference reference;
#endif
struct proxy
{
operator value_type&() const;
proxy& operator=(value_type) const;
};
proxy operator*() const;
};
template <class T>
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 <class T>
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<v>::proxy)
BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator<int>::proxy)
int main()
{
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<v*>::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<v const*>::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<std::deque<v>::iterator>::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<std::deque<v>::const_iterator>::value);
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<std::back_insert_iterator<std::deque<v> > >::value);
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<std::ostream_iterator<v> >::value);
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<proxy_iterator<v> >::value);
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<proxy_iterator<int> >::value);
#ifndef BOOST_NO_LVALUE_RETURN_DETECTION
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<value_iterator>::value);
#endif
// Make sure inaccessible copy constructor doesn't prevent
// reference binding
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<noncopyable_iterator>::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<v> >::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<int> >::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<char*> >::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<float> >::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<v> >::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<int> >::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<char*> >::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<float> >::value);
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<v*>::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<v const*>::value);
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<std::deque<v>::iterator>::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<std::deque<v>::const_iterator>::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<std::back_insert_iterator<std::deque<v> > >::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<std::ostream_iterator<v> >::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<proxy_iterator<v> >::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<proxy_iterator<int> >::value);
#ifndef BOOST_NO_LVALUE_RETURN_DETECTION
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<value_iterator>::value);
#endif
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<noncopyable_iterator>::value);
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<v> >::value);
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<int> >::value);
#endif
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<char*> >::value);
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<float> >::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<v> >::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<int> >::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<char*> >::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<float> >::value);
return 0;
}
+93
View File
@@ -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 <deque>
#include <iterator>
#include <iostream>
#include <boost/static_assert.hpp>
#include <boost/noncopyable.hpp>
#include <boost/type_traits/broken_compiler_spec.hpp>
#include <boost/iterator/is_readable_iterator.hpp>
#include <boost/iterator.hpp>
// Last, for BOOST_NO_LVALUE_RETURN_DETECTION
#include <boost/iterator/detail/config_def.hpp>
struct v
{
v();
~v();
};
BOOST_TT_BROKEN_COMPILER_SPEC(v)
struct value_iterator : boost::iterator<std::input_iterator_tag,v>
{
v operator*() const;
};
struct noncopyable_iterator : boost::iterator<std::forward_iterator_tag,boost::noncopyable>
{
boost::noncopyable const& operator*() const;
};
struct proxy_iterator : boost::iterator<std::output_iterator_tag,v>
{
#if BOOST_WORKAROUND(__GNUC__, == 2)
typedef boost::iterator<std::input_iterator_tag,v> 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<std::output_iterator_tag,v>
{
#if BOOST_WORKAROUND(__GNUC__, == 2)
typedef boost::iterator<std::input_iterator_tag,v> 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<v*>::value);
BOOST_STATIC_ASSERT(boost::is_readable_iterator<v const*>::value);
BOOST_STATIC_ASSERT(boost::is_readable_iterator<std::deque<v>::iterator>::value);
BOOST_STATIC_ASSERT(boost::is_readable_iterator<std::deque<v>::const_iterator>::value);
BOOST_STATIC_ASSERT(!boost::is_readable_iterator<std::back_insert_iterator<std::deque<v> > >::value);
BOOST_STATIC_ASSERT(!boost::is_readable_iterator<std::ostream_iterator<v> >::value);
BOOST_STATIC_ASSERT(boost::is_readable_iterator<proxy_iterator>::value);
BOOST_STATIC_ASSERT(!boost::is_readable_iterator<proxy_iterator2>::value);
BOOST_STATIC_ASSERT(boost::is_readable_iterator<value_iterator>::value);
// Make sure inaccessible copy constructor doesn't prevent
// readability
BOOST_STATIC_ASSERT(boost::is_readable_iterator<noncopyable_iterator>::value);
return 0;
}
-11
View File
@@ -4,17 +4,6 @@
#include <boost/cstdlib.hpp>
#include <list>
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
namespace boost { namespace detail
{
template<> struct iterator_traits<int*>
: ptr_iter_traits<int> {};
template<> struct iterator_traits<int const*>
: ptr_iter_traits<int, int const> {};
}}
#endif
int main()
{
{
+69 -7
View File
@@ -14,8 +14,14 @@
#include <numeric>
#include <boost/iterator/iterator_adaptor.hpp>
#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
# include <boost/iterator/is_readable_iterator.hpp>
# include <boost/iterator/is_lvalue_iterator.hpp>
#endif
#include <boost/pending/iterator_tests.hpp>
# include <boost/type_traits/broken_compiler_spec.hpp>
#include <stdlib.h>
#include <vector>
#include <deque>
@@ -24,11 +30,10 @@
#include "static_assert_same.hpp"
struct my_iterator_tag : public std::random_access_iterator_tag { };
#include <boost/iterator/detail/config_def.hpp>
using boost::dummyT;
struct mult_functor {
typedef int result_type;
typedef int argument_type;
@@ -82,7 +87,7 @@ struct ptr_iterator
ptr_iterator<V>
, V*
, V
, std::random_access_iterator_tag
, boost::random_access_traversal_tag
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
, V&
#endif
@@ -93,7 +98,7 @@ private:
ptr_iterator<V>
, V*
, V
, std::random_access_iterator_tag
, boost::random_access_traversal_tag
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
, V&
#endif
@@ -112,6 +117,17 @@ public:
{}
};
// Non-functional iterator for category modification checking
template <class Iter, class Traversal>
struct modify_traversal
: boost::iterator_adaptor<
modify_traversal<Iter, Traversal>
, Iter
, boost::use_default
, Traversal
>
{};
template <class T>
struct fwd_iterator
: boost::iterator_adaptor<
@@ -167,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 <class Cat>
struct traversal3
{
static typename boost::iterator_category_to_traversal<Cat>::type x;
BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(traversal2(x)));
typedef char (&type)[value];
};
template <class Cat>
typename traversal3<Cat>::type traversal(Cat);
template <class Iter, class Trav>
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<Trav,t2>::value;
}
int
main()
{
@@ -207,7 +250,17 @@ main()
typedef ptr_iterator<int const> Iter1;
test = static_assert_same<Iter1::value_type, int>::value;
test = static_assert_same<Iter1::reference, const int&>::value;
test = static_assert_same<Iter1::iterator_category::access, boost::readable_lvalue_iterator_tag>::value; test = static_assert_same<Iter1::pointer, const int*>::value;
#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
BOOST_STATIC_ASSERT(boost::is_readable_iterator<Iter1>::value);
# ifndef BOOST_NO_LVALUE_RETURN_DETECTION
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<Iter1>::value);
# endif
#endif
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness
test = static_assert_same<Iter1::pointer, int const*>::value;
#endif
}
{
@@ -217,10 +270,19 @@ main()
test = static_assert_same<Iter::value_type, int>::value;
test = static_assert_same<Iter::reference, int const&>::value;
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness
test = static_assert_same<Iter::pointer, int const*>::value;
#endif
test = static_assert_same<BaseIter::iterator_category::access, boost::writable_lvalue_iterator_tag>::value;
test = static_assert_same<Iter::iterator_category::access, boost::readable_lvalue_iterator_tag>::value;
#ifndef BOOST_NO_LVALUE_RETURN_DETECTION
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<BaseIter>::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<Iter>::value);
#endif
typedef modify_traversal<BaseIter, boost::incrementable_traversal_tag> IncrementableIter;
static_assert_traversal<BaseIter,boost::random_access_traversal_tag>();
static_assert_traversal<IncrementableIter,boost::incrementable_traversal_tag>();
}
// Test the iterator_adaptor
+7 -6
View File
@@ -12,14 +12,15 @@
int main()
{
{
typedef boost::iterator_archetype<int,
boost::writable_lvalue_iterator_tag,
boost::random_access_traversal_tag> 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<iter> >();
boost::function_requires< boost_concepts::RandomAccessTraversalConcept<iter> >();
}
return 0; // keep msvc happy
return 0; // keep msvc happy
}
+16 -33
View File
@@ -9,6 +9,7 @@
#include <boost/test/minimal.hpp>
#include <boost/iterator/permutation_iterator.hpp>
#include <boost/static_assert.hpp>
#include <vector>
#include <list>
@@ -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;
}
Executable → Regular
+1 -13
View File
@@ -11,19 +11,6 @@
using boost::dummyT;
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
namespace boost
{
namespace detail
{
template<> struct iterator_traits<dummyT*>
: ptr_iter_traits<dummyT> {};
template<> struct iterator_traits<dummyT const*>
: ptr_iter_traits<dummyT const> {};
}
}
#endif
// Test reverse iterator
int main()
{
@@ -87,6 +74,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);
Executable → Regular
+6 -2
View File
@@ -10,13 +10,17 @@
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T, class U>
struct static_assert_same;
struct static_assert_same_base;
template <class T>
struct static_assert_same<T,T>
struct static_assert_same_base<T,T>
{
enum { value = 1 };
};
template <class T, class U>
struct static_assert_same : static_assert_same_base<T,U> {};
#else
# include <boost/mpl/if.hpp>
# include <boost/mpl/bool.hpp>
+33 -35
View File
@@ -27,18 +27,10 @@
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
namespace boost { namespace detail
{
template<> struct iterator_traits<int*>
: ptr_iter_traits<int> {};
template<> struct iterator_traits<std::pair<int, int>*>
: ptr_iter_traits<std::pair<int, int> > {};
template<> struct iterator_traits<int const*>
: ptr_iter_traits<int, int const> {};
template<> struct iterator_traits<std::pair<int, int> const*>
: ptr_iter_traits<std::pair<int, int>, std::pair<int, int> const> {};
template<> struct function_object_result<int (*)(int)>
{
typedef int type;
};
}}
#endif
@@ -192,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);
}
@@ -221,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);
}
Executable → Regular
+29 -21
View File
@@ -5,16 +5,16 @@
// to its suitability for any purpose.
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/static_assert.hpp>
#include "static_assert_same.hpp"
#include <boost/type_traits/broken_compiler_spec.hpp>
#include <boost/iterator/detail/minimum_category.hpp>
struct X { int a; };
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
namespace boost { namespace detail {
template<> struct iterator_traits<X*>
: ptr_iter_traits<X> {};
}}
#endif
BOOST_TT_BROKEN_COMPILER_SPEC(X)
struct Xiter : boost::iterator_adaptor<Xiter,X*>
{
@@ -43,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
@@ -75,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
@@ -87,9 +92,12 @@ 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
(void)test;
}
+910
View File
@@ -0,0 +1,910 @@
// (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 <boost/iterator/zip_iterator.hpp>
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <boost/tuple/tuple.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/is_readable_iterator.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/detail/workaround.hpp>
#include <stddef.h>
template <class It>
struct pure_traversal
: boost::detail::pure_traversal_tag<
typename boost::iterator_traversal<It>::type
>
{};
/////////////////////////////////////////////////////////////////////////////
//
// 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<int, double> mytuple;
mytuple t1;
boost::tuples::get<0>(t1) = 42;
boost::tuples::get<1>(t1) = 42.1;
if( 2 == boost::tuples::length<mytuple>::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<int> s;
s.insert(42);
s.insert(43);
s.insert(44);
typedef boost::transform_iterator<
std::binder1st<std::plus<int> >,
std::set<int>::iterator
>
add_seven_iterator;
typedef boost::transform_iterator<
std::binder1st<std::plus<int> >,
std::set<int>::const_iterator
>
const_add_seven_iterator;
add_seven_iterator set_run(s.begin(), std::bind1st(std::plus<int>(), 7));
add_seven_iterator set_end(s.end(), std::bind1st(std::plus<int>(), 7));
const_add_seven_iterator const_set_run(s.begin(), std::bind1st(std::plus<int>(), 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<double> vect1(3);
vect1[0] = 42.;
vect1[1] = 43.;
vect1[2] = 44.;
std::set<int> intset;
intset.insert(52);
intset.insert(53);
intset.insert(54);
//
boost::zip_iterator<
boost::tuples::tuple<
std::set<int>::iterator
, std::vector<double>::iterator
>
>
zip_it_mixed(
boost::make_tuple(
intset.begin()
, vect1.begin()
)
);
boost::tuples::tuple<int, double> val_tuple(
*zip_it_mixed);
boost::tuples::tuple<const int&, double&> 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<int> li1;
li1.push_back(1);
std::set<int> se1;
se1.insert(2);
std::vector<int> ve1;
ve1.push_back(3);
//
std::list<int> li2;
li2.push_back(4);
std::set<int> se2;
se2.insert(5);
std::vector<int> ve2;
ve2.push_back(6);
//
std::list<int> li3;
li3.push_back(7);
std::set<int> se3;
se3.insert(8);
std::vector<int> ve3;
ve3.push_back(9);
//
std::list<int> li4;
li4.push_back(10);
std::set<int> se4;
se4.insert(11);
std::vector<int> ve4;
ve4.push_back(12);
// typedefs for cons lists of iterators.
typedef boost::tuples::cons<
std::set<int>::iterator,
boost::tuples::tuple<
std::vector<int>::iterator,
std::list<int>::iterator,
std::set<int>::iterator,
std::vector<int>::iterator,
std::list<int>::iterator,
std::set<int>::iterator,
std::vector<int>::iterator,
std::list<int>::iterator,
std::set<int>::iterator,
std::vector<int>::const_iterator
>::inherited
> cons_11_its_type;
//
typedef boost::tuples::cons<
std::list<int>::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<cons_12_its_type> 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<double> vect2(3);
vect2[0] = 2.2;
vect2[1] = 3.3;
vect2[2] = 4.4;
boost::zip_iterator<
boost::tuples::tuple<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_begin(
boost::make_tuple(
vect1.begin(),
vect2.begin()
)
);
boost::zip_iterator<
boost::tuples::tuple<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_run(
boost::make_tuple(
vect1.begin(),
vect2.begin()
)
);
boost::zip_iterator<
boost::tuples::tuple<
std::vector<double>::const_iterator,
std::vector<double>::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<double>::const_iterator,
std::vector<double>::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<boost::tuples::tuple<double, double> >
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<int>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_const(
boost::make_tuple(
intset.begin(),
vect2.begin()
)
);
//
boost::zip_iterator<
boost::tuples::tuple<
std::set<int>::iterator,
std::vector<double>::const_iterator
>
>
zip_it_half_const(
boost::make_tuple(
intset.begin(),
vect2.begin()
)
);
//
boost::zip_iterator<
boost::tuples::tuple<
std::set<int>::iterator,
std::vector<double>::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_convertible<
boost::iterator_traversal<zip_it_12_type>::type
, boost::bidirectional_traversal_tag
>::value;
bool bBigItIsRandomAccessIterator = boost::is_convertible<
boost::iterator_traversal<zip_it_12_type>::type
, boost::random_access_traversal_tag
>::value;
// A combining iterator with all vector iterators must have random access
// traversal.
//
typedef boost::zip_iterator<
boost::tuples::tuple<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
> all_vects_type;
bool bAllVectsIsRandomAccessIterator = boost::is_convertible<
boost::iterator_traversal<all_vects_type>::type
, boost::random_access_traversal_tag
>::value;
// The big test.
if( bBigItIsBidirectionalIterator &&
! bBigItIsRandomAccessIterator &&
bAllVectsIsRandomAccessIterator
)
{
++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<unsigned int>(num_successful_tests)
<< "\nNumber of failed tests: " << static_cast<unsigned int>(num_failed_tests)
<< std::endl;
return num_failed_tests;
}