Compare commits

...

165 Commits

Author SHA1 Message Date
nobody
df4b43a1bf This commit was manufactured by cvs2svn to create tag
'Version_1_30_2'.

[SVN r19685]
2003-08-18 18:40:31 +00:00
Dave Abrahams
985d2ff669 merged from trunk
[SVN r19631]
2003-08-16 02:09:27 +00:00
nobody
dc294f7225 This commit was manufactured by cvs2svn to create branch 'RC_1_30_0'.
[SVN r19146]
2003-07-16 10:53:07 +00:00
nobody
3dffb91af6 This commit was manufactured by cvs2svn to create branch 'RC_1_30_0'.
[SVN r17693]
2003-03-01 19:43:06 +00:00
Daniel Frey
56acf9c325 Fixed shift-operators to respect BOOST_FORCE_SYMMETRIC_OPERATORS
[SVN r17664]
2003-02-26 21:26:57 +00:00
Aleksey Gurtovoy
c6e3957efc MPL names/directory structure refactoring
[SVN r17651]
2003-02-25 23:11:41 +00:00
Peter Dimov
25e8284950 Qualified checked_delete calls to prevent ADL (reported by Daniel Frey)
[SVN r17636]
2003-02-25 13:00:22 +00:00
Dave Abrahams
37a6537a5b fix metafunctions for MPL
[SVN r17621]
2003-02-25 00:57:33 +00:00
Aleksey Gurtovoy
80df1d8f12 split utility.hpp header
[SVN r17472]
2003-02-17 06:20:57 +00:00
Peter Dimov
75afed7f17 Made operator()s const.
[SVN r17411]
2003-02-14 16:20:01 +00:00
Peter Dimov
1d7066aee1 __func__ is a predefined identifier, not a macro.
[SVN r17308]
2003-02-10 16:25:41 +00:00
Fernando Cacciola
12272a38d4 Initial Commit (was left out when the Optional Library was commited)
[SVN r17204]
2003-02-04 15:29:12 +00:00
Jeremy Siek
04f901e52e fixed some typos
[SVN r17052]
2003-01-27 19:14:18 +00:00
Beman Dawes
fabfb31bf6 add value_init
[SVN r16826]
2003-01-09 13:26:13 +00:00
Beman Dawes
683701cd07 fix invalid bookmarks
[SVN r16823]
2003-01-09 13:03:37 +00:00
Dave Abrahams
119c64be0b Workaround VC7 bug which strips const from nested classes
[SVN r16797]
2003-01-08 17:21:10 +00:00
Beman Dawes
d429c9a7d8 minor cleanup
[SVN r16709]
2002-12-27 16:58:27 +00:00
Beman Dawes
1e8216431b add or update See www.boost.org comments
[SVN r16708]
2002-12-27 16:51:53 +00:00
Peter Dimov
e45b2e2136 Doc link updated.
[SVN r16699]
2002-12-24 12:34:42 +00:00
Beman Dawes
9e6951009b Add /libs/lib-name to comment
[SVN r16685]
2002-12-23 02:43:12 +00:00
Dave Abrahams
a009a209f1 Use BOOST_WORKAROUND
[SVN r16668]
2002-12-20 00:03:04 +00:00
Peter Dimov
97605056ed Added a note that throw_exception must not return (Beman Dawes)
[SVN r16471]
2002-12-02 12:12:42 +00:00
Peter Dimov
8fcfa33d33 Fix: Comeau with bcc32 as backend defines __BORLANDC__ as 1.
[SVN r16455]
2002-11-28 13:32:44 +00:00
Toon Knapen
aa65e3da3b sort_by_value(std::list<std::string>& l) is not declared inline anymore to make it compile with vacpp
[SVN r16407]
2002-11-25 15:54:37 +00:00
Peter Dimov
b4cfadb4d5 Metrowerks support (Bertolt Mildner)
[SVN r16263]
2002-11-15 19:44:18 +00:00
Peter Dimov
45a6249668 New BOOST_ASSERT, including documentation.
[SVN r16240]
2002-11-14 16:09:29 +00:00
Peter Dimov
1d601aef4d boost::throw_exception documentation added.
[SVN r16239]
2002-11-14 15:13:59 +00:00
Peter Dimov
32fb45eba9 checked_delete.hpp documentation added.
[SVN r16238]
2002-11-14 14:53:32 +00:00
Peter Dimov
2b7d10aceb BOOST_CURRENT_FUNCTION documentation added.
[SVN r16236]
2002-11-14 14:41:25 +00:00
Dave Abrahams
5dc62711e1 Fix from Yitzhak Sapir <yitzhaks@actimize.com>
[SVN r16198]
2002-11-11 19:50:05 +00:00
Dave Abrahams
252c02aca0 Works with MSVC and Intel5 now. Thanks, Aleksey!!
[SVN r16165]
2002-11-08 17:08:17 +00:00
Dave Abrahams
9655beb7ba Cleanups on boost::iterator_traits<>
Broke MSVC though :(


[SVN r16157]
2002-11-08 06:57:31 +00:00
Dave Abrahams
f0ea53e77e rip out illegal semicolons
[SVN r16134]
2002-11-06 18:20:38 +00:00
Dave Abrahams
4755b42909 Daniel Frey's NRVO patches
[SVN r16084]
2002-11-04 01:59:32 +00:00
Peter Dimov
ef9af03c6c Changed typename to class; some libraries helpfully #define typename
[SVN r15970]
2002-10-23 13:55:18 +00:00
Björn Karlsson
7439073cbf Merged from branch to trunk
[SVN r15572]
2002-09-30 16:54:26 +00:00
Ralf W. Grosse-Kunstleve
aff985a563 explicit "private" inheritance to avoid compiler warnings (MIPSpro)
[SVN r15422]
2002-09-17 21:06:32 +00:00
Dave Abrahams
db425222d5 mpl_v2 branch checkin
[SVN r15258]
2002-09-11 05:35:41 +00:00
Ronald Garcia
e20af510f7 Initial Revision
[SVN r15254]
2002-09-10 16:13:08 +00:00
Ronald Garcia
d8230c6a73 Added Shared Container Iterator adaptor to iterator adaptor library.
[SVN r15169]
2002-09-05 14:05:29 +00:00
Beman Dawes
f5690787bf Distinguish between VC++ versions
[SVN r15127]
2002-09-01 14:57:40 +00:00
John Maddock
a4fd7b32dd Misc Kylix fixes
[SVN r15086]
2002-08-25 11:57:37 +00:00
Ronald Garcia
f4336ec693 fixed typo.
[SVN r14798]
2002-08-12 20:47:54 +00:00
Beman Dawes
03d906976b Reduced probes from 10,000 to 1,000 to speed regression tests
[SVN r14789]
2002-08-12 15:05:23 +00:00
Beman Dawes
4ba6a96822 fix test_main signature
[SVN r14783]
2002-08-12 13:22:40 +00:00
John Maddock
1ea4140d56 Added tests for BOOST_NO_STD_ITERATOR_TRAITS
[SVN r14654]
2002-07-31 11:25:25 +00:00
Douglas Gregor
351d4ecb15 Document policies() member of iterator_adaptor
[SVN r14613]
2002-07-26 00:03:24 +00:00
Beman Dawes
7fbf84dcc6 BaseType -> Base in one more place
[SVN r14605]
2002-07-25 19:10:05 +00:00
Dave Abrahams
3ff49b272d fixup
[SVN r14598]
2002-07-25 14:16:54 +00:00
Dave Abrahams
5b52e3d418 Fix doc based on Beman's feedback
[SVN r14596]
2002-07-25 13:52:48 +00:00
Dave Abrahams
8c0eb498d3 Fix unversioned VC++ checks
[SVN r14436]
2002-07-13 12:26:19 +00:00
Dave Abrahams
48a81ef7ea VC++ fixes
[SVN r14435]
2002-07-13 12:22:51 +00:00
Dave Abrahams
f7610c9b26 fix link
[SVN r14318]
2002-07-05 23:51:20 +00:00
Dave Abrahams
1755eaf019 Merged from RC_1_28_0
[SVN r13944]
2002-05-16 00:56:42 +00:00
John Maddock
6b8b218efb Removed tabs, fixed end of files.
[SVN r13803]
2002-05-10 11:35:38 +00:00
Beman Dawes
333d79b345 Add index.html so automatic tools work correctly
[SVN r13725]
2002-05-07 19:23:05 +00:00
John Maddock
f0fa436fe4 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
John Maddock
13e6d78fa8 Fixes for Borland C++ Builder 6
[SVN r13662]
2002-05-04 11:03:42 +00:00
John Maddock
7126ea2685 Borland C++ Builder 6 fixes
[SVN r13659]
2002-05-04 10:55:15 +00:00
John Maddock
a37518cb4a Fixed broken links.
[SVN r13574]
2002-04-27 11:05:49 +00:00
Jens Maurer
64b3e8c3bd add missing #include <iterator>
[SVN r13554]
2002-04-23 19:52:11 +00:00
Peter Dimov
339937380e MSVC fixes.
[SVN r13476]
2002-04-13 13:19:57 +00:00
Dave Abrahams
6156f0d302 Roll addressof() patch back in!
[SVN r13433]
2002-04-10 17:01:35 +00:00
Douglas Gregor
00560e8e17 addressof.hpp:
- Peter Dimov suggested a fix to deal with those evil cv-qualifiers


[SVN r13431]
2002-04-10 14:47:32 +00:00
Dave Abrahams
029ff9828f Roll back addressof() patch temporarily
[SVN r13428]
2002-04-10 09:48:30 +00:00
Douglas Gregor
ec188c7c3e Make local classes nonlocal to silence annoying warnings from Borland C++
[SVN r13418]
2002-04-10 04:00:22 +00:00
Douglas Gregor
0a0296a5d0 ref.hpp:
- Use addressof() instead of & operator


[SVN r13416]
2002-04-10 03:36:17 +00:00
Douglas Gregor
6e26a5bbe7 boost/utility.hpp:
- Include boost/utility/addressof.hpp

boost/utility/addressof.hpp:
  - addressof() implementation

libs/utility/utility.htm:
  - Document addressof

libs/utility/addressof_test.cpp:
  - Test addressof()


[SVN r13414]
2002-04-10 03:31:18 +00:00
Douglas Gregor
dc1b6246a0 boost/ref.hpp:
- Added get_pointer method to return a pointer (instead of a reference)

libs/bind/ref.html:
  - Document get_pointer


[SVN r13322]
2002-03-31 00:24:00 +00:00
John Maddock
15f69eaf14 Fixed new problem with Borland compile -
code clashes with some new type traits workarounds for some reason.


[SVN r13226]
2002-03-19 11:33:00 +00:00
Dave Abrahams
4774a0d325 Added Copyright
[SVN r13145]
2002-03-09 20:34:06 +00:00
Jens Maurer
be78ab72c9 update expected failures for Sun CC
[SVN r13101]
2002-03-05 20:41:37 +00:00
Dave Abrahams
0bc4a1b20d Warning suppressioni from Craig Rodrigues
[SVN r13098]
2002-03-05 18:55:49 +00:00
Darin Adler
c8b674d105 Add missing paren.
[SVN r12997]
2002-03-01 17:43:00 +00:00
John Maddock
b421d4725a Fixed expected failures for gcc 3.1
[SVN r12994]
2002-03-01 12:27:01 +00:00
Dave Abrahams
1662bb5713 use of "small" changed to "small_" to suppress confusion on some compilers
[SVN r12916]
2002-02-24 02:35:19 +00:00
Toon Knapen
ad79a21abd added portability note about using std::vector's as Base with VC++
[SVN r12875]
2002-02-21 12:09:46 +00:00
Peter Dimov
19645a52e6 Added a default constructor to shared_count and shared_ptr for incomplete types (void).
[SVN r12815]
2002-02-15 13:31:58 +00:00
John Maddock
74c3077c9a Added test cases for incomplete and abstract base class types.
[SVN r12803]
2002-02-14 12:57:32 +00:00
John Maddock
1f29191329 Modified call_traits to work with incomplete types.
[SVN r12800]
2002-02-14 12:54:57 +00:00
Darin Adler
4b636a7680 Always say "private noncopyable" to avoid warnings.
[SVN r12762]
2002-02-08 20:08:15 +00:00
Jeremy Siek
e6fc2555f3 removed tabs
[SVN r12707]
2002-02-04 20:29:35 +00:00
Darin Adler
e27d0fcf2a New smart pointer documentation. Related clean-up of the smart pointer
library. Changing includes to include the new individual smart pointer
headers. Replacing old smart pointer library with an include of the new
smart pointer headers. Simplify ifdefs that involve the member templates
macros now that BOOST_MSVC6_MEMBER_TEMPLATES is also guaranteed to bet
set for platforms that have full member templates.


[SVN r12647]
2002-02-02 18:36:12 +00:00
Dave Abrahams
2643c33b20 Doc fixes from Thomas Witt
[SVN r12621]
2002-02-01 13:03:21 +00:00
Aleksey Gurtovoy
71af1e77c8 compile-time ref.hpp header test, initial checkin
[SVN r12525]
2002-01-27 13:39:06 +00:00
Aleksey Gurtovoy
99e7406bd9 ref_ct_test.cpp
[SVN r12524]
2002-01-27 13:32:37 +00:00
Aleksey Gurtovoy
413265f497 compile-time ref.hpp header test, initial checkin
[SVN r12522]
2002-01-27 13:07:20 +00:00
Aleksey Gurtovoy
fe44cdf09b made 'reference_wrapper' Assignable
[SVN r12520]
2002-01-27 13:02:27 +00:00
Peter Dimov
e413428d71 Added tests for the new smart pointers.
[SVN r12500]
2002-01-25 13:54:30 +00:00
Darin Adler
88b9822db7 Mark inline to avoid warning with "require prototypes" on.
[SVN r12490]
2002-01-24 19:15:30 +00:00
Peter Dimov
24045c0cd7 #included <boost/checked_delete.hpp>, removed unnecessary #includes.
[SVN r12488]
2002-01-24 17:47:08 +00:00
Dave Abrahams
d2aa9f4a84 added missing #include of boost/config.hpp
[SVN r12483]
2002-01-24 16:55:41 +00:00
Dave Abrahams
d2a5fd169f initial checkin
[SVN r12481]
2002-01-24 16:52:06 +00:00
Peter Dimov
4e350d9934 Modified is_reference_wrapper<> to work for reference types.
[SVN r12475]
2002-01-24 13:28:08 +00:00
Dave Abrahams
f3f697bbc8 added is_reference_wrapper<>, unwrap_reference<>
[SVN r12470]
2002-01-23 21:19:14 +00:00
Darin Adler
c7c09696db Tweak comments. Include <assert.h> and <boost/current_function.hpp> only
when needed.


[SVN r12446]
2002-01-22 18:28:33 +00:00
Peter Dimov
dbcc58d984 Smart pointer enhancements, initial commit
[SVN r12439]
2002-01-22 13:38:52 +00:00
Dave Abrahams
8231310c4d initial checkin
[SVN r12390]
2002-01-21 01:29:06 +00:00
Beman Dawes
2988140430 tabs
[SVN r12360]
2002-01-19 16:07:28 +00:00
John Maddock
7387966005 Stripped tabs from source
[SVN r12351]
2002-01-19 12:38:14 +00:00
Jeremy Siek
e0a5a61375 removed eroneous "detail::" prefix
[SVN r12326]
2002-01-15 19:14:53 +00:00
Jeremy Siek
66ecd70689 removed std:: prefix from slist
[SVN r12310]
2002-01-14 14:57:20 +00:00
Dave Abrahams
67f4f45653 Fixed violation of 'explicit' constructor
[SVN r12256]
2002-01-09 13:15:54 +00:00
Dave Abrahams
1bf28b3de2 Fixes for Borland
[SVN r12254]
2002-01-09 12:11:37 +00:00
John Maddock
eb3c3435d7 Updated expected results
[SVN r12250]
2002-01-08 13:01:15 +00:00
Dave Abrahams
8a81d8b16c Workarounds for MSVC
[SVN r12246]
2002-01-07 19:24:45 +00:00
Toon Knapen
bc9d8b13d0 converted some of the old terminology (OrderIterator) to the current
terminology (IndexIterator)


[SVN r12164]
2001-12-28 15:49:45 +00:00
Dave Abrahams
4768b167ab Removed obsolete mentions of "less"; Added formalized Policies Concept description
[SVN r12056]
2001-12-14 12:54:21 +00:00
Dave Abrahams
591ff70ed1 many fixes
[SVN r12054]
2001-12-13 19:43:35 +00:00
Dave Abrahams
7bf2ad0b22 VC6 patch
[SVN r12045]
2001-12-13 18:24:29 +00:00
Jens Maurer
409c79b2e4 fix example (thanks to Michael Stevens)
[SVN r11979]
2001-12-08 08:39:27 +00:00
Toon Knapen
d0410691a1 removed calls to non-standard std::iota (SGI extension)
[SVN r11904]
2001-12-04 08:02:36 +00:00
Dave Abrahams
64e5115138 Fixed spelling error ing gcc-3.0 bug workaround
[SVN r11888]
2001-12-03 21:48:54 +00:00
Dave Abrahams
7ae912d83c Rolled in Helmut's fixes for random_access_iterable; rolled back
workarounds for that problem.


[SVN r11887]
2001-12-03 21:47:58 +00:00
Toon Knapen
2937f5876c changed std::iota call (SGI extension) to a manual loop
in permutation_iterator test


[SVN r11869]
2001-12-03 08:35:08 +00:00
Beman Dawes
8619c9b5c3 fix gcc looping (from Dave Abrahams)
[SVN r11839]
2001-11-30 17:55:39 +00:00
Toon Knapen
e4d5684f6b added test for permutation_iterator
[SVN r11825]
2001-11-30 11:10:07 +00:00
Toon Knapen
3d69cf95da added documentation for the permutation_iterator_adaptor
and linked to it from the iterator_adaptors documentation.


[SVN r11824]
2001-11-30 10:40:03 +00:00
Dave Abrahams
18944572b7 committing Daryle and Helmut's changes
[SVN r11813]
2001-11-29 21:22:52 +00:00
Jens Maurer
3e9d0f80c2 add generator iterator adaptor
[SVN r11736]
2001-11-19 22:11:51 +00:00
Jens Maurer
a2c4d1990a add boost::generator_iterator_policies and convenience classes
[SVN r11725]
2001-11-18 17:56:43 +00:00
Jens Maurer
404261c6ee add definition for integral constants initialized in-class
[SVN r11723]
2001-11-18 17:32:19 +00:00
Peter Dimov
87abc59612 #undef BOOST_REF_CONST added
[SVN r11674]
2001-11-14 14:40:29 +00:00
Peter Dimov
cb98ddf7db Fixed a bug w/ adaptable function objects + nested binds, made ref<> return const
[SVN r11670]
2001-11-13 13:56:05 +00:00
Peter Dimov
7d2e6c9025 __stdcall support added.
[SVN r11649]
2001-11-10 19:18:58 +00:00
Dave Abrahams
75eaa14a18 Removed defunct boost::tied (thanks, Daryle Walker)
[SVN r11622]
2001-11-07 10:35:12 +00:00
Jeremy Siek
082d6e3b32 *** empty log message ***
[SVN r11614]
2001-11-06 16:09:14 +00:00
Jeremy Siek
35b3770b6f *** empty log message ***
[SVN r11613]
2001-11-06 16:05:25 +00:00
Jeremy Siek
5b9d20c7e2 *** empty log message ***
[SVN r11611]
2001-11-06 15:52:56 +00:00
Jeremy Siek
5bbed2372e *** empty log message ***
[SVN r11602]
2001-11-05 21:03:59 +00:00
Jens Maurer
a9d407d239 update SunCC to 6.u2 (C++ 5.3)
[SVN r11601]
2001-11-05 21:00:53 +00:00
Jeremy Siek
3ca4a33a65 updated for named parameters
[SVN r11566]
2001-11-04 16:21:51 +00:00
Jeremy Siek
95197f427c remoeved #if 0
[SVN r11565]
2001-11-04 16:18:10 +00:00
Jeremy Siek
84cdfb032c commit these changes
[SVN r11563]
2001-11-04 04:37:14 +00:00
Dave Abrahams
ec2ceb9c96 no message
[SVN r11508]
2001-11-01 17:22:39 +00:00
John Maddock
6286c893fd Minor regression fixes for Borland and Sunpro tests.
[SVN r11470]
2001-10-30 11:41:35 +00:00
Jeremy Siek
354aef0e8c changed named parameters doc to match new stuff
[SVN r11417]
2001-10-22 17:04:23 +00:00
John Maddock
139e33c36d Updated preprocessor logic to use BOOST_HAS_LONG_LONG
[SVN r11399]
2001-10-18 11:33:52 +00:00
Dave Abrahams
e01de59cdd Made these actually compile
[SVN r11378]
2001-10-12 22:22:42 +00:00
Darin Adler
686f822dea Fix spelling error: "occurances" -> "occurrences".
[SVN r11376]
2001-10-11 17:26:04 +00:00
John Maddock
9961d5c9af Last fix had broken preprocessor logic, now fixed.
[SVN r11373]
2001-10-11 12:04:00 +00:00
John Maddock
628be0d125 Fixes for Sunpro C++ 5.3 (code now works!)
[SVN r11368]
2001-10-09 11:24:56 +00:00
John Maddock
633e45f61a Fixed test to work with sunpro 5.3 (omits array specialisation tests)
[SVN r11359]
2001-10-08 11:35:05 +00:00
John Maddock
2f357c3805 Partial fixes for sunpro 5.3 - doesn't actually work yet though
[SVN r11355]
2001-10-08 11:31:29 +00:00
John Maddock
cda0894d0d Fix for sunpro 5.3 (array specialisations don't work)
[SVN r11354]
2001-10-08 11:30:53 +00:00
Beman Dawes
117720a8bc 1.25.0 Final runup
[SVN r11315]
2001-10-01 15:54:23 +00:00
Beman Dawes
a6f6c3613a Change comments to make it clear why forward declaration header is required.
[SVN r11314]
2001-10-01 14:15:44 +00:00
Darin Adler
7914f5b931 Fixed unused variables that show up as warnings when doing regression
tests.


[SVN r11241]
2001-09-24 23:21:16 +00:00
John Maddock
a1add0a6f6 Intel C++ fixes: Added class copy constructor.
[SVN r11200]
2001-09-22 11:52:56 +00:00
Beman Dawes
c032b337c4 Fix broken links and other HTML changes related to new config system
[SVN r11142]
2001-09-18 21:24:51 +00:00
Jens Maurer
ec363261ae remove "explicit" on two- and three-argument constructors to avoid
error on HP aCC


[SVN r11097]
2001-09-11 18:42:25 +00:00
Beman Dawes
97cde2183d Initial base_from_member commit
[SVN r11086]
2001-09-10 14:04:28 +00:00
Dave Abrahams
7f43c682db Fixed the pair_generator documentation. Order of parameters was wrong; reordered
the table to match the corrected order.


[SVN r11035]
2001-09-05 16:29:29 +00:00
Jeremy Siek
0c9eee3c6b changed note about the move to the tuples library
[SVN r10972]
2001-08-30 19:45:19 +00:00
John Maddock
3b1afa3ba6 changed "empty-member" to "empty base-class"
[SVN r10966]
2001-08-30 10:58:19 +00:00
Jeremy Siek
93e6a75125 changed #include for tie() to tuple.hpp
[SVN r10951]
2001-08-28 19:09:33 +00:00
Jeremy Siek
52f8a7c0ca changed #include for tie()
[SVN r10950]
2001-08-28 19:07:51 +00:00
Jeremy Siek
55bfeb646f removed tie() and class tied
[SVN r10938]
2001-08-26 19:55:49 +00:00
Jeremy Siek
75c9dd3be1 added not about constness of operator* and operator[]
[SVN r10931]
2001-08-24 15:28:20 +00:00
Dave Abrahams
6392e2788f Removed incorrect statics, added const
[SVN r10930]
2001-08-24 12:09:34 +00:00
Peter Dimov
6a97f3f9ba Tabs converted to spaces.
[SVN r10916]
2001-08-23 19:05:21 +00:00
Peter Dimov
6e5f52e279 initial commit
[SVN r10914]
2001-08-23 18:42:16 +00:00
Darin Adler
7f92bed902 Fix some broken links. Fix order of constructor initializers.
[SVN r10913]
2001-08-23 17:42:07 +00:00
Beman Dawes
d68a11cc42 Misc; mostly fix links to hard disk locations
[SVN r10902]
2001-08-20 13:04:43 +00:00
Beman Dawes
328a81e194 Fix broken hyperlink
[SVN r10896]
2001-08-19 15:08:33 +00:00
77 changed files with 7899 additions and 1782 deletions

648
Collection.html Normal file
View File

@@ -0,0 +1,648 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. Silicon Graphics makes no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Collection</Title>
</HEAD>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<h1>
<img src="../../c++boost.gif" alt="boost logo"
width="277" align="middle" height="86">
<br>Collection
</h1>
<h3>Description</h3>
A Collection is a <i>concept</i> similar to the STL <a
href="http://www.sgi.com/tech/stl/Container.html">Container</a>
concept. A Collection provides iterators for accessing a range of
elements and provides information about the number of elements in the
Collection. However, a Collection has fewer requirements than a
Container. The motivation for the Collection concept is that there are
many useful Container-like types that do not meet the full
requirements of Container, and many algorithms that can be written
with this reduced set of requirements. To summarize the reduction
in requirements:
<UL>
<LI>It is not required to &quot;own&quot; its elements: the lifetime
of an element in a Collection does not have to match the lifetime of
the Collection object, though the lifetime of the element should cover
the lifetime of the Collection object.
<LI>The semantics of copying a Collection object is not defined (it
could be a deep or shallow copy or not even support copying).
<LI>The associated reference type of a Collection does
not have to be a real C++ reference.
</UL>
Because of the reduced requirements, some care must be taken when
writing code that is meant to be generic for all Collection types.
In particular, a Collection object should be passed by-reference
since assumptions can not be made about the behaviour of the
copy constructor.
<p>
<h3>Associated types</h3>
<Table border>
<TR>
<TD VAlign=top>
Value type
</TD>
<TD VAlign=top>
<tt>X::value_type</tt>
</TD>
<TD VAlign=top>
The type of the object stored in a Collection.
If the Collection is <i>mutable</i> then
the value type must be <A
href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</A>.
Otherwise the value type must be <a href="./CopyConstructible.html">CopyConstructible</a>.
</TD>
</TR>
<TR>
<TD VAlign=top>
Iterator type
</TD>
<TD VAlign=top>
<tt>X::iterator</tt>
</TD>
<TD VAlign=top>
The type of iterator used to iterate through a Collection's
elements. The iterator's value type is expected to be the
Collection's value type. A conversion
from the iterator type to the const iterator type must exist.
The iterator type must be an <A href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</A>.
</TD>
</TR>
<TR>
<TD VAlign=top>
Const iterator type
</TD>
<TD VAlign=top>
<tt>X::const_iterator</tt>
</TD>
<TD VAlign=top>
A type of iterator that may be used to examine, but not to modify,
a Collection's elements.
</TD>
</TR>
<TR>
<TD VAlign=top>
Reference type
</TD>
<TD VAlign=top>
<tt>X::reference</tt>
</TD>
<TD VAlign=top>
A type that behaves like a reference to the Collection's value type.
<a href="#1">[1]</a>
</TD>
</TR>
<TR>
<TD VAlign=top>
Const reference type
</TD>
<TD VAlign=top>
<tt>X::const_reference</tt>
</TD>
<TD VAlign=top>
A type that behaves like a const reference to the Collection's value type.
</TD>
</TR>
<TR>
<TD VAlign=top>
Pointer type
</TD>
<TD VAlign=top>
<tt>X::pointer</tt>
</TD>
<TD VAlign=top>
A type that behaves as a pointer to the Collection's value type.
</TD>
</TR>
<TR>
<TD VAlign=top>
Distance type
</TD>
<TD VAlign=top>
<tt>X::difference_type</tt>
</TD>
<TD VAlign=top>
A signed integral type used to represent the distance between two
of the Collection's iterators. This type must be the same as
the iterator's distance type.
</TD>
</TR>
<TR>
<TD VAlign=top>
Size type
</TD>
<TD VAlign=top>
<tt>X::size_type</tt>
</TD>
<TD VAlign=top>
An unsigned integral type that can represent any nonnegative value
of the Collection's distance type.
</TD>
</tr>
</table>
<h3>Notation</h3>
<Table>
<TR>
<TD VAlign=top>
<tt>X</tt>
</TD>
<TD VAlign=top>
A type that is a model of Collection.
</TD>
</TR>
<TR>
<TD VAlign=top>
<tt>a</tt>, <tt>b</tt>
</TD>
<TD VAlign=top>
Object of type <tt>X</tt>.
</TD>
</TR>
<TR>
<TD VAlign=top>
<tt>T</tt>
</TD>
<TD VAlign=top>
The value type of <tt>X</tt>.
</TD>
</tr>
</table>
<h3>Valid expressions</h3>
The following expressions must be valid.
<p>
<Table border>
<TR>
<TH>
Name
</TH>
<TH>
Expression
</TH>
<TH>
Return type
</TH>
</TR>
<TR>
<TD VAlign=top>
Beginning of range
</TD>
<TD VAlign=top>
<tt>a.begin()</tt>
</TD>
<TD VAlign=top>
<tt>iterator</tt> if <tt>a</tt> is mutable, <tt>const_iterator</tt> otherwise
</TD>
</TR>
<TR>
<TD VAlign=top>
End of range
</TD>
<TD VAlign=top>
<tt>a.end()</tt>
</TD>
<TD VAlign=top>
<tt>iterator</tt> if <tt>a</tt> is mutable, <tt>const_iterator</tt> otherwise
</TD>
</TR>
<TR>
<TD VAlign=top>
Size
</TD>
<TD VAlign=top>
<tt>a.size()</tt>
</TD>
<TD VAlign=top>
<tt>size_type</tt>
</TD>
</TR>
<!--
<TR>
<TD VAlign=top>
Maximum size
</TD>
<TD VAlign=top>
<tt>a.max_size()</tt>
</TD>
<TD VAlign=top>
<tt>size_type</tt>
</TD>
</TR>
<TR>
-->
<TD VAlign=top>
Empty Collection
</TD>
<TD VAlign=top>
<tt>a.empty()</tt>
</TD>
<TD VAlign=top>
Convertible to <tt>bool</tt>
</TD>
</TR>
<TR>
<TD VAlign=top>
Swap
</TD>
<TD VAlign=top>
<tt>a.swap(b)</tt>
</TD>
<TD VAlign=top>
<tt>void</tt>
</TD>
</tr>
</table>
<h3>Expression semantics</h3>
<Table border>
<TR>
<TH>
Name
</TH>
<TH>
Expression
</TH>
<TH>
Semantics
</TH>
<TH>
Postcondition
</TH>
</TR>
<TD VAlign=top>
<TR>
<TD VAlign=top>
Beginning of range
</TD>
<TD VAlign=top>
<tt>a.begin()</tt>
</TD>
<TD VAlign=top>
Returns an iterator pointing to the first element in the Collection.
</TD>
<TD VAlign=top>
<tt>a.begin()</tt> is either dereferenceable or past-the-end. It is
past-the-end if and only if <tt>a.size() == 0</tt>.
</TD>
</TR>
<TR>
<TD VAlign=top>
End of range
</TD>
<TD VAlign=top>
<tt>a.end()</tt>
</TD>
<TD VAlign=top>
Returns an iterator pointing one past the last element in the
Collection.
</TD>
<TD VAlign=top>
<tt>a.end()</tt> is past-the-end.
</TD>
</TR>
<TR>
<TD VAlign=top>
Size
</TD>
<TD VAlign=top>
<tt>a.size()</tt>
</TD>
<TD VAlign=top>
Returns the size of the Collection, that is, its number of elements.
</TD>
<TD VAlign=top>
<tt>a.size() &gt;= 0
</TD>
</TR>
<!--
<TR>
<TD VAlign=top>
Maximum size
</TD>
<TD VAlign=top>
<tt>a.max_size()</tt>
</TD>
<TD VAlign=top>
&nbsp;
</TD>
<TD VAlign=top>
Returns the largest size that this Collection can ever have. <A href="#8">[8]</A>
</TD>
<TD VAlign=top>
<tt>a.max_size() &gt;= 0 &amp;&amp; a.max_size() &gt;= a.size()</tt>
</TD>
</TR>
-->
<TR>
<TD VAlign=top>
Empty Collection
</TD>
<TD VAlign=top>
<tt>a.empty()</tt>
</TD>
<TD VAlign=top>
Equivalent to <tt>a.size() == 0</tt>. (But possibly faster.)
</TD>
<TD VAlign=top>
&nbsp;
</TD>
</TR>
<TR>
<TD VAlign=top>
Swap
</TD>
<TD VAlign=top>
<tt>a.swap(b)</tt>
</TD>
<TD VAlign=top>
Equivalent to <tt>swap(a,b)</tt>
</TD>
<TD VAlign=top>
&nbsp;
</TD>
</tr>
</table>
<h3>Complexity guarantees</h3>
<tt>begin()</tt> and <tt>end()</tt> are amortized constant time.
<P>
<tt>size()</tt> is at most linear in the Collection's
size. <tt>empty()</tt> is amortized constant time.
<P>
<tt>swap()</tt> is at most linear in the size of the two collections.
<h3>Invariants</h3>
<Table border>
<TR>
<TD VAlign=top>
Valid range
</TD>
<TD VAlign=top>
For any Collection <tt>a</tt>, <tt>[a.begin(), a.end())</tt> is a valid
range.
</TD>
</TR>
<TR>
<TD VAlign=top>
Range size
</TD>
<TD VAlign=top>
<tt>a.size()</tt> is equal to the distance from <tt>a.begin()</tt> to <tt>a.end()</tt>.
</TD>
</TR>
<TR>
<TD VAlign=top>
Completeness
</TD>
<TD VAlign=top>
An algorithm that iterates through the range <tt>[a.begin(), a.end())</tt>
will pass through every element of <tt>a</tt>.
</TD>
</tr>
</table>
<h3>Models</h3>
<UL>
<LI> <tt>array</tt>
<LI> <tt>array_ptr</tt>
<LI> <tt>vector&lt;bool&gt;</tt>
</UL>
<h3>Collection Refinements</h3>
There are quite a few concepts that refine the Collection concept,
similar to the concepts that refine the Container concept. Here
is a brief overview of the refining concepts.
<h4>ForwardCollection</h4>
The elements are arranged in some order that
does not change spontaneously from one iteration to the next. As
a result, a ForwardCollection is
<A
href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</A>
and
<A
href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</A>.
In addition, the iterator type of a ForwardCollection is a
MultiPassInputIterator which is just an InputIterator with the added
requirements that the iterator can be used to make multiple passes
through a range, and that if <tt>it1 == it2</tt> and <tt>it1</tt> is
dereferenceable then <tt>++it1 == ++it2</tt>. The ForwardCollection
also has a <tt>front()</tt> method.
<p>
<Table border>
<TR>
<TH>
Name
</TH>
<TH>
Expression
</TH>
<TH>
Return type
</TH>
<TH>
Semantics
</TH>
</TR>
<TR>
<TD VAlign=top>
Front
</TD>
<TD VAlign=top>
<tt>a.front()</tt>
</TD>
<TD VAlign=top>
<tt>reference</tt> if <tt>a</tt> is mutable, <br> <tt>const_reference</tt>
otherwise.
</TD>
<TD VAlign=top>
Equivalent to <tt>*(a.begin())</tt>.
</TD>
</TR>
</table>
<h4>ReversibleCollection</h4>
The container provides access to iterators that traverse in both
directions (forward and reverse). The iterator type must meet all of
the requirements of
<a href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>
except that the reference type does not have to be a real C++
reference. The ReversibleCollection adds the following requirements
to those of ForwardCollection.
<p>
<Table border>
<TR>
<TH>
Name
</TH>
<TH>
Expression
</TH>
<TH>
Return type
</TH>
<TH>
Semantics
</TH>
</TR>
<TR>
<TD VAlign=top>
Beginning of range
</TD>
<TD VAlign=top>
<tt>a.rbegin()</tt>
</TD>
<TD VAlign=top>
<tt>reverse_iterator</tt> if <tt>a</tt> is mutable,
<tt>const_reverse_iterator</tt> otherwise.
</TD>
<TD VAlign=top>
Equivalent to <tt>X::reverse_iterator(a.end())</tt>.
</TD>
</TR>
<TR>
<TD VAlign=top>
End of range
</TD>
<TD VAlign=top>
<tt>a.rend()</tt>
</TD>
<TD VAlign=top>
<tt>reverse_iterator</tt> if <tt>a</tt> is mutable,
<tt>const_reverse_iterator</tt> otherwise.
</TD>
<TD VAlign=top>
Equivalent to <tt>X::reverse_iterator(a.begin())</tt>.
</TD>
</tr>
<TR>
<TD VAlign=top>
Back
</TD>
<TD VAlign=top>
<tt>a.back()</tt>
</TD>
<TD VAlign=top>
<tt>reference</tt> if <tt>a</tt> is mutable, <br> <tt>const_reference</tt>
otherwise.
</TD>
<TD VAlign=top>
Equivalent to <tt>*(--a.end())</tt>.
</TD>
</TR>
</table>
<h4>SequentialCollection</h4>
The elements are arranged in a strict linear order. No extra methods
are required.
<h4>RandomAccessCollection</h4>
The iterators of a RandomAccessCollection satisfy all of the
requirements of <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>
except that the reference type does not have to be a real C++
reference. In addition, a RandomAccessCollection provides
an element access operator.
<p>
<Table border>
<TR>
<TH>
Name
</TH>
<TH>
Expression
</TH>
<TH>
Return type
</TH>
<TH>
Semantics
</TH>
</TR>
<TR>
<TD VAlign=top>
Element Access
</TD>
<TD VAlign=top>
<tt>a[n]</tt>
</TD>
<TD VAlign=top>
<tt>reference</tt> if <tt>a</tt> is mutable,
<tt>const_reference</tt> otherwise.
</TD>
<TD VAlign=top>
Returns the nth element of the Collection.
<tt>n</tt> must be convertible to <tt>size_type</tt>.
Precondition: <tt>0 &lt;= n &lt; a.size()</tt>.
</TD>
</TR>
</table>
<h3>Notes</h3>
<P><A name="1">[1]</A>
The reference type does not have to be a real C++ reference. The
requirements of the reference type depend on the context within which
the Collection is being used. Specifically it depends on the
requirements the context places on the value type of the Collection.
The reference type of the Collection must meet the same requirements
as the value type. In addition, the reference objects must be
equivalent to the value type objects in the collection (which is
trivially true if they are the same object). Also, in a mutable
Collection, an assignment to the reference object must result in an
assignment to the object in the Collection (again, which is trivially
true if they are the same object, but non-trivial if the reference
type is a proxy class).
<h3>See also</h3>
<A href="http://www.sgi.com/tech/stl/Container.html">Container</A>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>, Univ.of Notre Dame and C++ Library & Compiler Group/SGI (<A HREF="mailto:jsiek@engr.sgi.com">jsiek@engr.sgi.com</A>)
</TD></TR></TABLE>
</BODY>
</HTML>

View File

@@ -85,7 +85,7 @@ Once that is done we can drop Multi-Pass Input Iterator.
<TABLE> <TABLE>
<TR valign=top> <TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD> <TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF=file:///c:/boost/site/people/jeremy_siek.htm>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>) <a HREF="../../people/jeremy_siek.htm">Jeremy Siek</a>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
</TD></TR></TABLE> </TD></TR></TABLE>
</BODY> </BODY>

130
OptionalPointee.html Normal file
View File

@@ -0,0 +1,130 @@
<HTML>
<Head>
<Title>OptionalPointee Concept</Title>
</HEAD>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<!--end header-->
<BR Clear>
<H1>Concept: OptionalPointee</H1>
<h3>Description</h3>
A type is a model of <i>OptionalPointee</i> if it points to (or refers to) a value
that may not exist. That is, if it has a <b>pointee</b> which might be <b>valid</b>
(existent) or <b>invalid</b> (inexistent); and it is possible to test whether the
pointee is valid or not.
This model does <u>not</u> imply pointer semantics: i.e., it does not imply shallow copy nor
aliasing.
<h3>Notation</h3>
<Table>
<TR>
<TD VAlign=top> <tt>T</tt> </TD>
<TD VAlign=top> is a type that is a model of OptionalPointee</TD>
</TR>
<TR>
<TD VAlign=top> <tt>t</tt> </TD>
<TD VAlign=top> is an object of type <tt>T</tt> or possibly <tt>const T</tt></TD>
</tr>
</table>
<h3>Definitions</h3>
<h3>Valid expressions</h3>
<Table border>
<TR>
<TH> Name </TH>
<TH> Expression </TH>
<TH> Return type </TH>
<TH> Semantics </TH>
</TR>
<TR>
<TD VAlign=top>Value Access</TD>
<TD VAlign=top>&nbsp;<tt>*t</tt></TD>
<TD VAlign=top>&nbsp;<tt>T&amp;</tt></TD>
<TD VAlign=top>If the pointee is valid returns a reference to
the pointee.<br>
If the pointee is invalid the result is <i>undefined</i>.</TD>
<TD VAlign=top> </TD>
</TR>
<TR>
<TD VAlign=top>Value Access</TD>
<TD VAlign=top>&nbsp;<tt>t-><i>xyz</i></tt></TD>
<TD VAlign=top>&nbsp;<tt>T*</tt></TD>
<TD VAlign=top>If the pointee is valid returns a builtin pointer to the pointee.<br>
If the pointee is invalid the result is <i>undefined</i> (It might not even return NULL).<br>
</TD>
<TD VAlign=top> </TD>
</TR>
<TR>
<TD VAlign=top>Validity Test</TD>
<TD VAlign=top>&nbsp;<tt>t</tt><br>
&nbsp;<tt>t != 0</tt><br>
&nbsp;<tt>!!t</tt>
</TD>
<TD VAlign=top>&nbsp;bool </TD>
<TD VAlign=top>If the pointee is valid returns true.<br>
If the pointee is invalid returns false.</TD>
<TD VAlign=top></TD>
</TR>
<TR>
<TD VAlign=top>Invalidity Test</TD>
<TD VAlign=top>&nbsp;<tt>t == 0</tt><br>
&nbsp;<tt>!t</tt>
</TD>
<TD VAlign=top>&nbsp;bool </TD>
<TD VAlign=top>If the pointee is valid returns false.<br>
If the pointee is invalid returns true.</TD>
<TD VAlign=top></TD>
</TR>
</table>
<h3>Models</h3>
<UL>
<LI><tt>pointers, both builtin and smart.</tt>
<LI><tt>boost::optional&lt;&gt;</tt>
</UL>
<HR>
<h3>OptionalPointee and relational operations</h3>
<p>This concept does not define any particular semantic for relational operations, therefore,
a type which models this concept might have either shallow or deep relational semantics.<br>
For instance, pointers, which are models of OptionalPointee, have shallow relational operators:
comparisons of pointers do not involve comparisons of pointees.
This makes sense for pointers because they have shallow copy semantics.<br>
But boost::optional&lt;T&gt;, on the other hand, which is also a model of OptionalPointee, has
deep-copy and deep-relational semantics.<br>
If generic code is written for this concept, it is important not to use relational
operators directly because the semantics might be different depending on the actual type.<br>
Still, the concept itsef can be used to define a <i>deep</i> equality-test that can
be used in generic code with any type which models OptionalPointee:</p>
<a name="equal"></a>
<pre>
template&lt;class OptionalPointee&gt;
inline
bool equal_pointees ( OptionalPointee const&amp; x, OptionalPointee const&amp; y )
{
return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ;
}
</pre>
<p>The preceding generic function has the following semantics:<br>
If both x and y have valid pointees, it compares pointee's values via (*x == *y).<br>
If only one has a valid pointee, returns false.<br>
If both have invalid pointees, returns true.</p>
<p><code>equal_pointees()</code> is implemented in <a href="../../boost/optional.hpp">optional.hpp</a></p>
<p>Notice that OptionalPointee does not imply aliasing (and optional&lt;&gt; for instance does not alias);
so direct usage of relational operators with the implied aliasing of shallow semantics
-as with pointers- should not be used with generic code written for this concept.</p>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2003</TD><TD>
<A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>,
based on the original concept developed by Augustus Saunders.
</TD></TR></TABLE>
</BODY>
</HTML>

46
addressof_test.cpp Normal file
View File

@@ -0,0 +1,46 @@
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
// Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <boost/utility.hpp>
struct useless_type {};
class nonaddressable {
public:
void dummy(); // Silence GCC warning: all member of class are private
private:
useless_type operator&() const;
};
int test_main(int, char*[])
{
nonaddressable* px = new nonaddressable();
nonaddressable& x = *px;
BOOST_TEST(boost::addressof(x) == px);
const nonaddressable& cx = *px;
BOOST_TEST(boost::addressof(cx) == static_cast<const nonaddressable*>(px));
volatile nonaddressable& vx = *px;
BOOST_TEST(boost::addressof(vx) == static_cast<volatile nonaddressable*>(px));
const volatile nonaddressable& cvx = *px;
BOOST_TEST(boost::addressof(cvx) == static_cast<const volatile nonaddressable*>(px));
return 0;
}

57
assert.html Normal file
View File

@@ -0,0 +1,57 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Boost: assert.hpp documentation</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
<table border="0" width="100%">
<tr>
<td width="277">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277" height="86">
</td>
<td align="middle">
<h1>assert.hpp</h1>
</td>
</tr>
<tr>
<td colspan="2" height="64">&nbsp;</td>
</tr>
</table>
<p>
The header <STRONG>&lt;boost/assert.hpp&gt;</STRONG> defines the macro <b>BOOST_ASSERT</b>,
which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG>&lt;cassert&gt;</STRONG>.
The macro is intended to be used in Boost libraries.
</p>
<P>By default, <tt>BOOST_ASSERT(expr)</tt> is equivalent to <tt>assert(expr)</tt>.</P>
<P>When the macro <STRONG>BOOST_DISABLE_ASSERTS</STRONG> is defined when <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
is included, <tt>BOOST_ASSERT(expr)</tt> is defined as <tt>((void)0)</tt>. This
allows users to selectively disable <STRONG>BOOST_ASSERT</STRONG> without
affecting the definition of the standard <STRONG>assert</STRONG>.</P>
<P>When the macro <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> is defined when <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
is included, <tt>BOOST_ASSERT(expr)</tt> evaluates <b>expr</b> and, if the
result is false, evaluates the expression</P>
<P><tt>::boost::assertion_failed(#expr, <a href="current_function.html">BOOST_CURRENT_FUNCTION</a>,
__FILE__, __LINE__)</tt></P>
<P><STRONG>assertion_failed</STRONG> is declared in <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
as</P>
<pre>
namespace boost
{
void assertion_failed(char const * expr, char const * function, char const * file, long line);
}
</pre>
<p>but it is never defined. The user is expected to supply an appropriate
definition.</p>
<P>As is the case with <STRONG>&lt;cassert&gt;</STRONG>, <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
can be included multiple times in a single translation unit. <STRONG>BOOST_ASSERT</STRONG>
will be redefined each time as specified above.</P>
<p><br>
<small>Copyright <20> 2002 by Peter Dimov. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears in
all copies. This document is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.</small></p>
</body>
</html>

105
assert_test.cpp Normal file
View File

@@ -0,0 +1,105 @@
//
// assert_test.cpp - a test for boost/assert.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/detail/lightweight_test.hpp>
#include <boost/assert.hpp>
void test_default()
{
int x = 1;
BOOST_ASSERT(1);
BOOST_ASSERT(x);
BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x);
}
#define BOOST_DISABLE_ASSERTS
#include <boost/assert.hpp>
void test_disabled()
{
int x = 1;
BOOST_ASSERT(1);
BOOST_ASSERT(x);
BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x);
BOOST_ASSERT(0);
BOOST_ASSERT(!x);
BOOST_ASSERT(x == 0);
void * p = 0;
BOOST_ASSERT(p);
// supress warnings
p = &x;
p = &p;
}
#undef BOOST_DISABLE_ASSERTS
#define BOOST_ENABLE_ASSERT_HANDLER
#include <boost/assert.hpp>
#include <cstdio>
int handler_invoked = 0;
void boost::assertion_failed(char const * expr, char const * function, char const * file, long line)
{
std::printf("Expression: %s\nFunction: %s\nFile: %s\nLine: %ld\n\n", expr, function, file, line);
++handler_invoked;
}
struct X
{
static void f()
{
BOOST_ASSERT(0);
}
};
void test_handler()
{
int x = 1;
BOOST_ASSERT(1);
BOOST_ASSERT(x);
BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x);
BOOST_ASSERT(0);
BOOST_ASSERT(!x);
BOOST_ASSERT(x == 0);
void * p = 0;
BOOST_ASSERT(p);
X::f();
BOOST_ASSERT(handler_invoked == 5);
BOOST_TEST(handler_invoked == 5);
}
#undef BOOST_ENABLE_ASSERT_HANDLER
int main()
{
test_default();
test_disabled();
test_handler();
return boost::report_errors();
}

341
base_from_member.html Normal file
View File

@@ -0,0 +1,341 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title>Boost: Base-from-Member Idiom Documentation</title>
</head>
<body bgcolor="white" link="blue" text="black" vlink="purple" alink="red">
<h1><img src="../../c++boost.gif" alt="C++ Boost" align="middle"
width="277" height="86">Base-from-Member Idiom</h1>
<p>The class template <code>boost::base_from_member</code> provides
a workaround for a class that needs to initialize a base class with a
member. The class template is in <cite><a
href="../../boost/utility/base_from_member.hpp">boost/utility/base_from_member.hpp</a></cite>
which is included in <i><a href="../../boost/utility.hpp">boost/utility.hpp</a></i>.
The class template is forward declared in <i><a href="../../boost/utility_fwd.hpp">boost/utility_fwd.hpp</a></i>.</p>
<p>There is test/example code in <cite><a
href="base_from_member_test.cpp">base_from_member_test.cpp</a></cite>.</p>
<h2><a name="contents">Contents</a></h2>
<ul>
<li><a href="#contents">Contents</a></li>
<li><a href="#rationale">Rationale</a></li>
<li><a href="#synopsis">Synopsis</a></li>
<li><a href="#usage">Usage</a></li>
<li><a href="#example">Example</a></li>
<li><a href="#credits">Credits</a>
<ul>
<li><a href="#contributors">Contributors</a></li>
</ul></li>
</ul>
<h2><a name="rationale">Rationale</a></h2>
<p>When developing a class, sometimes a base class needs to be
initialized with a member of the current class. As a na&iuml;ve
example:</p>
<blockquote><pre>
#include &lt;streambuf&gt; <i>// for std::streambuf</i>
#include &lt;ostream&gt; <i>// for std::ostream</i>
class fdoutbuf
: public std::streambuf
{
public:
explicit fdoutbuf( int fd );
//...
};
class fdostream
: public std::ostream
{
protected:
fdoutbuf buf;
public:
explicit fdostream( int fd )
: buf( fd ), std::ostream( &amp;buf )
{}
//...
};
</pre></blockquote>
<p>This is undefined because C++'s initialization order mandates that
the base class is initialized before the member it uses. Ron Klatchko
developed a way around this by using the initialization order in his
favor. Base classes are intialized in order of declaration, so moving
the desired member to another base class, that is initialized before the
desired base class, can ensure proper initialization.</p>
<p>A custom base class can be made for this idiom:</p>
<blockquote><pre>
#include &lt;streambuf&gt; <i>// for std::streambuf</i>
#include &lt;ostream&gt; <i>// for std::ostream</i>
class fdoutbuf
: public std::streambuf
{
public:
explicit fdoutbuf( int fd );
//...
};
struct fdostream_pbase
{
fdoutbuf sbuffer;
explicit fdostream_pbase( int fd )
: sbuffer( fd )
{}
};
class fdostream
: private fdostream_pbase
, public std::ostream
{
typedef fdostream_pbase pbase_type;
typedef std::ostream base_type;
public:
explicit fdostream( int fd )
: pbase_type( fd ), base_type( &amp;sbuffer )
{}
//...
};
</pre></blockquote>
<p>Other projects can use similar custom base classes. The technique is basic enough to make a template, with a sample template class in this library. The main template parameter is the type of the enclosed member. The template class has several (explicit) constructor member templates, which implicitly type the constructor arguments and pass them to the member. The template class uses implicit copy construction and assignment, cancelling them if the enclosed member is non-copyable.</p>
<p>Manually coding a base class may be better if the construction
and/or copying needs are too complex for the supplied template class,
or if the compiler is not advanced enough to use it.</p>
<p>Since base classes are unnamed, a class cannot have multiple (direct)
base classes of the same type. The supplied template class has an
extra template parameter, an integer, that exists solely to provide type
differentiation. This parameter has a default value so a single use of a
particular member type does not need to concern itself with the integer.</p>
<h2><a name="synopsis">Synopsis</a></h2>
<blockquote><pre>
template &lt; typename MemberType, int UniqueID = 0 &gt;
class boost::base_from_member
{
protected:
MemberType member;
explicit base_from_member();
template&lt; typename T1 &gt;
explicit base_from_member( T1 x1 );
//...
template&lt; typename T1, typename T2, typename T3 &gt;
explicit base_from_member( T1 x1, T2 x2, T3 x3 );
};
</pre></blockquote>
<p>The class template has a first template parameter
<var>MemberType</var> representing the type of the based-member.
It has a last template parameter <var>UniqueID</var>, that is an
<code>int</code>, to differentiate between multiple base classes that use
the same based-member type. The last template parameter has a default
value of zero if it is omitted. The class template has a protected
data member called <var>member</var> that the derived class can use
for later base classes (or itself).</p>
<p>There is a default constructor and several constructor member
templates. These constructor templates can take as many arguments
(currently up to three) as possible and pass them to a constructor of
the data member. Since C++ does not allow any way to explicitly state
the template parameters of a templated constructor, make sure that
the arguments are already close as possible to the actual type used in
the data member's desired constructor.</p>
<h2><a name="usage">Usage</a></h2>
<p>With the starting example, the <code>fdoutbuf</code> sub-object needs
to be encapsulated in a base class that is inheirited before
<code>std::ostream</code>.</p>
<blockquote><pre>
#include &lt;boost/utility/base_from_member.hpp&gt;
#include &lt;streambuf&gt; <i>// for std::streambuf</i>
#include &lt;ostream&gt; <i>// for std::ostream</i>
class fdoutbuf
: public std::streambuf
{
public:
explicit fdoutbuf( int fd );
//...
};
class fdostream
: private boost::base_from_member&lt;fdoutbuf&gt;
, public std::ostream
{
// Helper typedef's
typedef boost::base_from_member&lt;fdoutbuf&gt; pbase_type;
typedef std::ostream base_type;
public:
explicit fdostream( int fd )
: pbase_type( fd ), base_type( &amp;member )
{}
//...
};
</pre></blockquote>
<p>The base-from-member idiom is an implementation detail, so it
should not be visible to the clients (or any derived classes) of
<code>fdostream</code>. Due to the initialization order, the
<code>fdoutbuf</code> sub-object will get initialized before the
<code>std::ostream</code> sub-object does, making the former
sub-object safe to use in the latter sub-object's construction. Since the
<code>fdoutbuf</code> sub-object of the final type is the only sub-object
with the name &quot;member,&quot; that name can be used
unqualified within the final class.</p>
<h2><a name="example">Example</a></h2>
<p>The base-from-member class templates should commonly involve
only one base-from-member sub-object, usually for attaching a
stream-buffer to an I/O stream. The next example demonstrates how
to use multiple base-from-member sub-objects and the resulting
qualification issues.</p>
<blockquote><pre>
#include &lt;boost/utility/base_from_member.hpp&gt;
#include &lt;cstddef&gt; <i>// for NULL</i>
struct an_int
{
int y;
an_int( float yf );
};
class switcher
{
public:
switcher();
switcher( double, int * );
//...
};
class flow_regulator
{
public:
flow_regulator( switcher &amp;, switcher &amp; );
//...
};
template &lt; unsigned Size &gt;
class fan
{
public:
explicit fan( switcher );
//...
};
class system
: private boost::base_from_member&lt;an_int&gt;
, private boost::base_from_member&lt;switcher&gt;
, private boost::base_from_member&lt;switcher, 1&gt;
, private boost::base_from_member&lt;switcher, 2&gt;
, protected flow_regulator
, public fan&lt;6&gt;
{
// Helper typedef's
typedef boost::base_from_member&lt;an_int&gt; pbase0_type;
typedef boost::base_from_member&lt;switcher&gt; pbase1_type;
typedef boost::base_from_member&lt;switcher, 1&gt; pbase2_type;
typedef boost::base_from_member&lt;switcher, 2&gt; pbase3_type;
typedef flow_regulator base1_type;
typedef fan&lt;6&gt; base2_type;
public:
system( double x );
//...
};
system::system( double x )
: pbase0_type( 0.2 )
, pbase1_type()
, pbase2_type( -16, &amp;this-&gt;pbase0_type::member )
, pbase3_type( x, static_cast&lt;int *&gt;(NULL) )
, base1_type( pbase3_type::member, pbase1_type::member )
, base2_type( pbase2_type::member )
{
//...
}
</pre></blockquote>
<p>The final class has multiple sub-objects with the name
&quot;member,&quot; so any use of that name needs qualification by
a name of the appropriate base type. (Using <code>typedef</code>s
ease mentioning the base types.) However, the fix introduces a new
problem when a pointer is needed. Using the address operator with
a sub-object qualified with its class's name results in a pointer-to-member
(here, having a type of <code>an_int boost::base_from_member&lt;an_int,
0&gt; :: *</code>) instead of a pointer to the member (having a type of
<code>an_int *</code>). The new problem is fixed by qualifying the
sub-object with &quot;<code>this-&gt;</code>,&quot; and is needed just
for pointers, and not for references or values.</p>
<p>There are some argument conversions in the initialization. The
constructor argument for <code>pbase0_type</code> is converted from
<code>double</code> to <code>float</code>. The first constructor
argument for <code>pbase2_type</code> is converted from <code>int</code>
to <code>double</code>. The second constructor argument for
<code>pbase3_type</code> is a special case of necessary conversion; all
forms of the null-pointer literal in C++ also look like compile-time
integral expressions, so C++ always interprets such code as an integer
when it has overloads that can take either an integer or a pointer. The
last conversion is necessary for the compiler to call a constructor form
with the exact pointer type used in <code>switcher</code>'s constructor.</p>
<h2><a name="credits">Credits</a></h2>
<h3><a name="contributors">Contributors</a></h3>
<dl>
<dt><a href="../../people/ed_brey.htm">Ed Brey</a>
<dd>Suggested some interface changes.
<dt>Ron Klatchko (<a href="mailto:ron@crl.com">ron@crl.com</a>)
<dd>Invented the idiom of how to use a class member for initializing
a base class.
<dt><a href="../../people/dietmar_kuehl.htm">Dietmar Kuehl</a>
<dd>Popularized the base-from-member idiom in his
<a href="http://www.informatik.uni-konstanz.de/~kuehl/c++/iostream/">IOStream
example classes</a>.
<dt><a href="../../people/daryle_walker.html">Daryle Walker</a>
<dd>Started the library. Contributed the test file <cite><a
href="base_from_member_test.cpp">base_from_member_test.cpp</a></cite>.
</dl>
<hr>
<p>Revised: 22 August 2001</p>
<p>Copyright &copy; boost.org 2001. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &quot;as
is&quot; without express or implied warranty, and with no claim as to
its suitability for any purpose.</p>
</body>
</html>

597
base_from_member_test.cpp Normal file
View File

@@ -0,0 +1,597 @@
// Boost test program for base-from-member class templates -----------------//
// (C) Copyright Daryle Walker 2001. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 29 Aug 2001 Initial Version (Daryle Walker)
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp> // for BOOST_TEST, main
#include <boost/config.hpp> // for BOOST_NO_MEMBER_TEMPLATES
#include <boost/cstdlib.hpp> // for boost::exit_success
#include <boost/noncopyable.hpp> // for boost::noncopyable
#include <boost/utility/base_from_member.hpp> // for boost::base_from_member
#include <functional> // for std::binary_function, std::less
#include <iostream> // for std::cout (std::ostream, std::endl indirectly)
#include <set> // for std::set
#include <typeinfo> // for std::type_info
#include <utility> // for std::pair, std::make_pair
#include <vector> // for std::vector
// Control if extra information is printed
#ifndef CONTROL_EXTRA_PRINTING
#define CONTROL_EXTRA_PRINTING 1
#endif
// A (sub)object can be identified by its memory location and its type.
// Both are needed since an object can start at the same place as its
// first base class subobject and/or contained subobject.
typedef std::pair< void *, std::type_info const * > object_id;
// Object IDs need to be printed
std::ostream & operator <<( std::ostream &os, object_id const &oi );
// A way to generate an object ID
template < typename T >
object_id identify( T &obj );
// A custom comparison type is needed
struct object_id_compare
: std::binary_function<object_id, object_id, bool>
{
bool operator ()( object_id const &a, object_id const &b ) const;
}; // object_id_compare
// A singleton of this type coordinates the acknowledgements
// of objects being created and used.
class object_registrar
: private boost::noncopyable
{
public:
#ifndef BOOST_NO_MEMBER_TEMPLATES
template < typename T >
void register_object( T &obj )
{ this->register_object_imp( identify(obj) ); }
template < typename T, typename U >
void register_use( T &owner, U &owned )
{ this->register_use_imp( identify(owner), identify(owned) ); }
template < typename T, typename U >
void unregister_use( T &owner, U &owned )
{ this->unregister_use_imp( identify(owner), identify(owned) ); }
template < typename T >
void unregister_object( T &obj )
{ this->unregister_object_imp( identify(obj) ); }
#endif
void register_object_imp( object_id obj );
void register_use_imp( object_id owner, object_id owned );
void unregister_use_imp( object_id owner, object_id owned );
void unregister_object_imp( object_id obj );
typedef std::set<object_id, object_id_compare> set_type;
typedef std::vector<object_id> error_record_type;
typedef std::vector< std::pair<object_id, object_id> > error_pair_type;
set_type db_;
error_pair_type defrauders_in_, defrauders_out_;
error_record_type overeager_, overkilled_;
}; // object_registrar
// A sample type to be used by containing types
class base_or_member
{
public:
explicit base_or_member( int x = 1, double y = -0.25 );
~base_or_member();
}; // base_or_member
// A sample type that uses base_or_member, used
// as a base for the main demonstration classes
class base_class
{
public:
explicit base_class( base_or_member &x, base_or_member *y = 0,
base_or_member *z = 0 );
~base_class();
private:
base_or_member *x_, *y_, *z_;
}; // base_class
// This bad class demonstrates the direct method of a base class needing
// to be initialized by a member. This is improper since the member
// isn't initialized until after the base class.
class bad_class
: public base_class
{
public:
bad_class();
~bad_class();
private:
base_or_member x_;
}; // bad_class
// The first good class demonstrates the correct way to initialize a
// base class with a member. The member is changed to another base
// class, one that is initialized before the base that needs it.
class good_class_1
: private boost::base_from_member<base_or_member>
, public base_class
{
typedef boost::base_from_member<base_or_member> pbase_type;
typedef base_class base_type;
public:
good_class_1();
~good_class_1();
}; // good_class_1
// The second good class also demonstrates the correct way to initialize
// base classes with other subobjects. This class uses the other helpers
// in the library, and shows the technique of using two base subobjects
// of the "same" type.
class good_class_2
: private boost::base_from_member<base_or_member, 0>
, private boost::base_from_member<base_or_member, 1>
, private boost::base_from_member<base_or_member, 2>
, public base_class
{
typedef boost::base_from_member<base_or_member, 0> pbase_type0;
typedef boost::base_from_member<base_or_member, 1> pbase_type1;
typedef boost::base_from_member<base_or_member, 2> pbase_type2;
typedef base_class base_type;
public:
good_class_2();
~good_class_2();
}; // good_class_2
// Declare/define the single object registrar
object_registrar obj_reg;
// Main functionality
int
test_main( int , char * [] )
{
BOOST_TEST( obj_reg.db_.empty() );
BOOST_TEST( obj_reg.defrauders_in_.empty() );
BOOST_TEST( obj_reg.defrauders_out_.empty() );
BOOST_TEST( obj_reg.overeager_.empty() );
BOOST_TEST( obj_reg.overkilled_.empty() );
// Make a separate block to examine pre- and post-effects
{
using std::cout;
using std::endl;
bad_class bc;
BOOST_TEST( obj_reg.db_.size() == 3 );
BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
good_class_1 gc1;
BOOST_TEST( obj_reg.db_.size() == 6 );
BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
good_class_2 gc2;
BOOST_TEST( obj_reg.db_.size() == 11 );
BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
BOOST_TEST( obj_reg.defrauders_out_.empty() );
BOOST_TEST( obj_reg.overeager_.empty() );
BOOST_TEST( obj_reg.overkilled_.empty() );
// Getting the addresses of the objects ensure
// that they're used, and not optimized away.
cout << "Object 'bc' is at " << &bc << '.' << endl;
cout << "Object 'gc1' is at " << &gc1 << '.' << endl;
cout << "Object 'gc2' is at " << &gc2 << '.' << endl;
}
BOOST_TEST( obj_reg.db_.empty() );
BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
BOOST_TEST( obj_reg.defrauders_out_.size() == 1 );
BOOST_TEST( obj_reg.overeager_.empty() );
BOOST_TEST( obj_reg.overkilled_.empty() );
return boost::exit_success;
}
// Print an object's ID
std::ostream &
operator <<
(
std::ostream & os,
object_id const & oi
)
{
// I had an std::ostringstream to help, but I did not need it since
// the program never screws around with formatting. Worse, using
// std::ostringstream is an issue with some compilers.
return os << '[' << ( oi.second ? oi.second->name() : "NOTHING" )
<< " at " << oi.first << ']';
}
// Get an object ID given an object
template < typename T >
inline
object_id
identify
(
T & obj
)
{
return std::make_pair( static_cast<void *>(&obj), &(typeid( obj )) );
}
// Compare two object IDs
bool
object_id_compare::operator ()
(
object_id const & a,
object_id const & b
) const
{
std::less<void *> vp_cmp;
if ( vp_cmp(a.first, b.first) )
{
return true;
}
else if ( vp_cmp(b.first, a.first) )
{
return false;
}
else
{
// object pointers are equal, compare the types
if ( a.second == b.second )
{
return false;
}
else if ( !a.second )
{
return true; // NULL preceeds anything else
}
else if ( !b.second )
{
return false; // NULL preceeds anything else
}
else
{
return a.second->before( *b.second );
}
}
}
// Let an object register its existence
void
object_registrar::register_object_imp
(
object_id obj
)
{
if ( db_.count(obj) <= 0 )
{
db_.insert( obj );
#if CONTROL_EXTRA_PRINTING
std::cout << "Registered " << obj << '.' << std::endl;
#endif
}
else
{
overeager_.push_back( obj );
#if CONTROL_EXTRA_PRINTING
std::cout << "Attempted to register a non-existant " << obj
<< '.' << std::endl;
#endif
}
}
// Let an object register its use of another object
void
object_registrar::register_use_imp
(
object_id owner,
object_id owned
)
{
if ( db_.count(owned) > 0 )
{
// We don't care to record usage registrations
}
else
{
defrauders_in_.push_back( std::make_pair(owner, owned) );
#if CONTROL_EXTRA_PRINTING
std::cout << "Attempted to own a non-existant " << owned
<< " by " << owner << '.' << std::endl;
#endif
}
}
// Let an object un-register its use of another object
void
object_registrar::unregister_use_imp
(
object_id owner,
object_id owned
)
{
if ( db_.count(owned) > 0 )
{
// We don't care to record usage un-registrations
}
else
{
defrauders_out_.push_back( std::make_pair(owner, owned) );
#if CONTROL_EXTRA_PRINTING
std::cout << "Attempted to disown a non-existant " << owned
<< " by " << owner << '.' << std::endl;
#endif
}
}
// Let an object un-register its existence
void
object_registrar::unregister_object_imp
(
object_id obj
)
{
set_type::iterator const i = db_.find( obj );
if ( i != db_.end() )
{
db_.erase( i );
#if CONTROL_EXTRA_PRINTING
std::cout << "Unregistered " << obj << '.' << std::endl;
#endif
}
else
{
overkilled_.push_back( obj );
#if CONTROL_EXTRA_PRINTING
std::cout << "Attempted to unregister a non-existant " << obj
<< '.' << std::endl;
#endif
}
}
// Macros to abstract the registration of objects
#ifndef BOOST_NO_MEMBER_TEMPLATES
#define PRIVATE_REGISTER_BIRTH(o) obj_reg.register_object( (o) )
#define PRIVATE_REGISTER_DEATH(o) obj_reg.unregister_object( (o) )
#define PRIVATE_REGISTER_USE(o, w) obj_reg.register_use( (o), (w) )
#define PRIVATE_UNREGISTER_USE(o, w) obj_reg.unregister_use( (o), (w) )
#else
#define PRIVATE_REGISTER_BIRTH(o) obj_reg.register_object_imp( \
identify((o)) )
#define PRIVATE_REGISTER_DEATH(o) obj_reg.unregister_object_imp( \
identify((o)) )
#define PRIVATE_REGISTER_USE(o, w) obj_reg.register_use_imp( identify((o)), \
identify((w)) )
#define PRIVATE_UNREGISTER_USE(o, w) obj_reg.unregister_use_imp( \
identify((o)), identify((w)) )
#endif
// Create a base_or_member, with arguments to simulate member initializations
base_or_member::base_or_member
(
int x, // = 1
double y // = -0.25
)
{
PRIVATE_REGISTER_BIRTH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy x-factor is " << x << " and my y-factor is " << y
<< '.' << std::endl;
#endif
}
// Destroy a base_or_member
inline
base_or_member::~base_or_member
(
)
{
PRIVATE_REGISTER_DEATH( *this );
}
// Create a base_class, registering any objects used
base_class::base_class
(
base_or_member & x,
base_or_member * y, // = 0
base_or_member * z // = 0
)
: x_( &x ), y_( y ), z_( z )
{
PRIVATE_REGISTER_BIRTH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy x-factor is " << x_;
#endif
PRIVATE_REGISTER_USE( *this, *x_ );
if ( y_ )
{
#if CONTROL_EXTRA_PRINTING
std::cout << ", my y-factor is " << y_;
#endif
PRIVATE_REGISTER_USE( *this, *y_ );
}
if ( z_ )
{
#if CONTROL_EXTRA_PRINTING
std::cout << ", my z-factor is " << z_;
#endif
PRIVATE_REGISTER_USE( *this, *z_ );
}
#if CONTROL_EXTRA_PRINTING
std::cout << '.' << std::endl;
#endif
}
// Destroy a base_class, unregistering the objects it uses
base_class::~base_class
(
)
{
PRIVATE_REGISTER_DEATH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy x-factor was " << x_;
#endif
PRIVATE_UNREGISTER_USE( *this, *x_ );
if ( y_ )
{
#if CONTROL_EXTRA_PRINTING
std::cout << ", my y-factor was " << y_;
#endif
PRIVATE_UNREGISTER_USE( *this, *y_ );
}
if ( z_ )
{
#if CONTROL_EXTRA_PRINTING
std::cout << ", my z-factor was " << z_;
#endif
PRIVATE_UNREGISTER_USE( *this, *z_ );
}
#if CONTROL_EXTRA_PRINTING
std::cout << '.' << std::endl;
#endif
}
// Create a bad_class, noting the improper construction order
bad_class::bad_class
(
)
: x_( -7, 16.75 ), base_class( x_ ) // this order doesn't matter
{
PRIVATE_REGISTER_BIRTH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy factor is at " << &x_
<< " and my base is at " << static_cast<base_class *>(this) << '.'
<< std::endl;
#endif
}
// Destroy a bad_class, noting the improper destruction order
bad_class::~bad_class
(
)
{
PRIVATE_REGISTER_DEATH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy factor was at " << &x_
<< " and my base was at " << static_cast<base_class *>(this)
<< '.' << std::endl;
#endif
}
// Create a good_class_1, noting the proper construction order
good_class_1::good_class_1
(
)
: pbase_type( 8 ), base_type( member )
{
PRIVATE_REGISTER_BIRTH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy factor is at " << &member
<< " and my base is at " << static_cast<base_class *>(this) << '.'
<< std::endl;
#endif
}
// Destroy a good_class_1, noting the proper destruction order
good_class_1::~good_class_1
(
)
{
PRIVATE_REGISTER_DEATH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy factor was at " << &member
<< " and my base was at " << static_cast<base_class *>(this)
<< '.' << std::endl;
#endif
}
// Create a good_class_2, noting the proper construction order
good_class_2::good_class_2
(
)
: pbase_type0(), pbase_type1(-16, 0.125), pbase_type2(2, -3)
, base_type( pbase_type1::member, &this->pbase_type0::member,
&this->pbase_type2::member )
{
PRIVATE_REGISTER_BIRTH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy factors are at " << &this->pbase_type0::member
<< ", " << &this->pbase_type1::member << ", "
<< &this->pbase_type2::member << ", and my base is at "
<< static_cast<base_class *>(this) << '.' << std::endl;
#endif
}
// Destroy a good_class_2, noting the proper destruction order
good_class_2::~good_class_2
(
)
{
PRIVATE_REGISTER_DEATH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy factors were at " << &this->pbase_type0::member
<< ", " << &this->pbase_type1::member << ", "
<< &this->pbase_type2::member << ", and my base was at "
<< static_cast<base_class *>(this) << '.' << std::endl;
#endif
}

249
binary_search_test.cpp Normal file
View File

@@ -0,0 +1,249 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <vector>
#include <string>
#include <memory>
#include <climits>
#include <iostream>
#include <cassert>
#include <stdlib.h> // for rand(). Would use cstdlib but VC6.4 doesn't put it in std::
#include <list>
#include <algorithm>
#include <boost/detail/binary_search.hpp>
#if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
# define USE_SSTREAM
#endif
#ifdef USE_SSTREAM
# include <sstream>
#else
# include <strstream>
#endif
namespace {
typedef std::vector<std::string> string_vector;
const std::size_t sequence_length = 1000;
unsigned random_number()
{
return static_cast<unsigned>(::rand()) % sequence_length;
}
# ifndef USE_SSTREAM
class unfreezer {
public:
unfreezer(std::ostrstream& s) : m_stream(s) {}
~unfreezer() { m_stream.freeze(false); }
private:
std::ostrstream& m_stream;
};
# endif
template <class T>
void push_back_random_number_string(T& seq)
{
unsigned value = random_number();
# if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
std::ostringstream s;
s << value;
seq.push_back(s.str());
# else
std::ostrstream s;
auto unfreezer unfreeze(s);
s << value << char(0);
seq.push_back(std::string(s.str()));
# endif
}
inline unsigned to_int(unsigned x) { return x; }
inline unsigned to_int(const std::string& x) { return atoi(x.c_str()); }
struct cmp
{
template <class A1, class A2>
inline bool operator()(const A1& a1, const A2& a2) const
{
return to_int(a1) < to_int(a2);
}
};
inline bool operator<(const std::string& x, const unsigned y)
{
return to_int(x) < y;
}
inline bool operator<(const unsigned y, const std::string& x)
{
return y < to_int(x);
}
template <class T> void sort_by_value(T&);
template <>
void sort_by_value(std::vector<std::string>& v)
{
std::sort(v.begin(), v.end(), cmp());
}
template <class T>
void random_sorted_sequence(T& seq)
{
seq.clear();
for (std::size_t i = 0; i < sequence_length; ++i)
{
push_back_random_number_string(seq);
}
sort_by_value(seq);
}
# if defined(BOOST_MSVC) && BOOST_MSVC < 1300 && !defined(__SGI_STL_PORT)
// VC6's standard lib doesn't have a template member function for list::sort()
template <>
void random_sorted_sequence(std::list<std::string>& result)
{
std::vector<std::string> seq;
seq.reserve(sequence_length);
for (std::size_t i = 0; i < sequence_length; ++i)
{
push_back_random_number_string(seq);
}
sort_by_value(seq);
result.resize(seq.size());
std::copy(seq.begin(), seq.end(), result.begin());
}
#else
template <>
void sort_by_value(std::list<std::string>& l)
{
l.sort(cmp());
}
# endif
// A way to select the comparisons with/without a Compare parameter for testing.
template <class Compare> struct searches
{
template <class Iterator, class Key>
static Iterator lower_bound(Iterator start, Iterator finish, Key key, Compare cmp)
{ return boost::detail::lower_bound(start, finish, key, cmp); }
template <class Iterator, class Key>
static Iterator upper_bound(Iterator start, Iterator finish, Key key, Compare cmp)
{ return boost::detail::upper_bound(start, finish, key, cmp); }
template <class Iterator, class Key>
static std::pair<Iterator, Iterator> equal_range(Iterator start, Iterator finish, Key key, Compare cmp)
{ return boost::detail::equal_range(start, finish, key, cmp); }
template <class Iterator, class Key>
static bool binary_search(Iterator start, Iterator finish, Key key, Compare cmp)
{ return boost::detail::binary_search(start, finish, key, cmp); }
};
struct no_compare {};
template <> struct searches<no_compare>
{
template <class Iterator, class Key>
static Iterator lower_bound(Iterator start, Iterator finish, Key key, no_compare)
{ return boost::detail::lower_bound(start, finish, key); }
template <class Iterator, class Key>
static Iterator upper_bound(Iterator start, Iterator finish, Key key, no_compare)
{ return boost::detail::upper_bound(start, finish, key); }
template <class Iterator, class Key>
static std::pair<Iterator, Iterator> equal_range(Iterator start, Iterator finish, Key key, no_compare)
{ return boost::detail::equal_range(start, finish, key); }
template <class Iterator, class Key>
static bool binary_search(Iterator start, Iterator finish, Key key, no_compare)
{ return boost::detail::binary_search(start, finish, key); }
};
template <class Sequence, class Compare>
void test_loop(Sequence& x, Compare cmp, unsigned long test_count)
{
typedef typename Sequence::const_iterator const_iterator;
for (unsigned long i = 0; i < test_count; ++i)
{
random_sorted_sequence(x);
const const_iterator start = x.begin();
const const_iterator finish = x.end();
unsigned key = random_number();
const const_iterator l = searches<Compare>::lower_bound(start, finish, key, cmp);
const const_iterator u = searches<Compare>::upper_bound(start, finish, key, cmp);
bool found_l = false;
bool found_u = false;
std::size_t index = 0;
std::size_t count = 0;
unsigned last_value = 0;
for (const_iterator p = start; p != finish; ++p)
{
if (p == l)
found_l = true;
if (p == u)
{
assert(found_l);
found_u = true;
}
unsigned value = to_int(*p);
assert(value >= last_value);
last_value = value;
if (!found_l)
{
++index;
assert(to_int(*p) < key);
}
else if (!found_u)
{
++count;
assert(to_int(*p) == key);
}
else
assert(to_int(*p) > key);
}
assert(found_l || l == finish);
assert(found_u || u == finish);
std::pair<const_iterator, const_iterator>
range = searches<Compare>::equal_range(start, finish, key, cmp);
assert(range.first == l);
assert(range.second == u);
bool found = searches<Compare>::binary_search(start, finish, key, cmp);
assert(found == (u != l));
std::cout << "found " << count << " copies of " << key << " at index " << index << "\n";
}
}
}
int main()
{
std::vector<std::string> x;
std::cout << "=== testing random-access iterators with <: ===\n";
test_loop(x, no_compare(), 25);
std::cout << "=== testing random-access iterators with compare: ===\n";
test_loop(x, cmp(), 25);
std::list<std::string> y;
std::cout << "=== testing bidirectional iterators with <: ===\n";
test_loop(y, no_compare(), 25);
std::cout << "=== testing bidirectional iterators with compare: ===\n";
test_loop(y, cmp(), 25);
std::cerr << "******TEST PASSED******\n";
return 0;
}

View File

@@ -5,7 +5,7 @@
content="text/html; charset=iso-8859-1"> content="text/html; charset=iso-8859-1">
<meta name="Template" <meta name="Template"
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot"> content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0"> <meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
<title>Call Traits</title> <title>Call Traits</title>
</head> </head>
@@ -592,7 +592,8 @@ would prevent template argument deduction from functioning.</p>
<p>The call_traits template will &quot;optimize&quot; the passing <p>The call_traits template will &quot;optimize&quot; the passing
of a small built-in type as a function parameter, this mainly has of a small built-in type as a function parameter, this mainly has
an effect when the parameter is used within a loop body. In the an effect when the parameter is used within a loop body. In the
following example (see <a href="algo_opt_examples.cpp">algo_opt_examples.cpp</a>), following example (see <a
href="../type_traits/examples/fill_example.cpp">fill_example.cpp</a>),
a version of std::fill is optimized in two ways: if the type a version of std::fill is optimized in two ways: if the type
passed is a single byte built-in type then std::memset is used to passed is a single byte built-in type then std::memset is used to
effect the fill, otherwise a conventional C++ implemention is effect the fill, otherwise a conventional C++ implemention is
@@ -751,7 +752,8 @@ Hinnant and John Maddock.</p>
<p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John <p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John
Maddock</a>, the latest version of this file can be found at <a Maddock</a>, the latest version of this file can be found at <a
href="http://www.boost.org/">www.boost.org</a>, and the boost href="http://www.boost.org/">www.boost.org</a>, and the boost
discussion list at <a href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p> discussion list at <a
href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
<p>.</p> <p>.</p>

View File

@@ -6,6 +6,8 @@
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// standalone test program for <boost/call_traits.hpp> // standalone test program for <boost/call_traits.hpp>
// 18 Mar 2002:
// Changed some names to prevent conflicts with some new type_traits additions.
// 03 Oct 2000: // 03 Oct 2000:
// Enabled extra tests for VC6. // Enabled extra tests for VC6.
@@ -17,6 +19,10 @@
#include <boost/call_traits.hpp> #include <boost/call_traits.hpp>
#include <boost/type_traits/type_traits_test.hpp> #include <boost/type_traits/type_traits_test.hpp>
// a way prevent warnings for unused variables
template<class T> inline void unused_variable(const T&) {}
// //
// struct contained models a type that contains a type (for example std::pair) // struct contained models a type that contains a type (for example std::pair)
// arrays are contained by value, and have to be treated as a special case: // arrays are contained by value, and have to be treated as a special case:
@@ -44,7 +50,7 @@ struct contained
reference get() { return v_; } reference get() { return v_; }
const_reference const_get()const { return v_; } const_reference const_get()const { return v_; }
// pass value: // pass value:
void call(param_type p){} void call(param_type){}
}; };
@@ -69,12 +75,12 @@ struct contained<T[N]>
// return by_ref: // return by_ref:
reference get() { return v_; } reference get() { return v_; }
const_reference const_get()const { return v_; } const_reference const_get()const { return v_; }
void call(param_type p){} void call(param_type){}
}; };
#endif #endif
template <class T> template <class T>
contained<typename boost::call_traits<T>::value_type> wrap(const T& t) contained<typename boost::call_traits<T>::value_type> test_wrap_type(const T& t)
{ {
typedef typename boost::call_traits<T>::value_type ct; typedef typename boost::call_traits<T>::value_type ct;
return contained<ct>(t); return contained<ct>(t);
@@ -156,10 +162,10 @@ struct call_traits_checker<T[N]>
// //
// check_wrap: // check_wrap:
template <class T, class U> template <class W, class U>
void check_wrap(const contained<T>& w, const U& u) void check_wrap(const W& w, const U& u)
{ {
cout << "checking contained<" << typeid(T).name() << ">..." << endl; cout << "checking " << typeid(W).name() << "..." << endl;
assert(w.value() == u); assert(w.value() == u);
} }
@@ -181,6 +187,12 @@ struct comparible_UDT
{ {
int i_; int i_;
comparible_UDT() : i_(2){} comparible_UDT() : i_(2){}
comparible_UDT(const comparible_UDT& other) : i_(other.i_){}
comparible_UDT& operator=(const comparible_UDT& other)
{
i_ = other.i_;
return *this;
}
bool operator == (const comparible_UDT& v){ return v.i_ == i_; } bool operator == (const comparible_UDT& v){ return v.i_ == i_; }
}; };
@@ -193,26 +205,23 @@ int main(int argc, char *argv[ ])
int i = 2; int i = 2;
c2(i); c2(i);
int* pi = &i; int* pi = &i;
#if (defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)) && !defined(__ICL) int a[2] = {1,2};
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) && !defined(__ICL)
call_traits_checker<int*> c3; call_traits_checker<int*> c3;
c3(pi); c3(pi);
call_traits_checker<int&> c4; call_traits_checker<int&> c4;
c4(i); c4(i);
call_traits_checker<const int&> c5; call_traits_checker<const int&> c5;
c5(i); c5(i);
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__) #if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__) && !defined(__SUNPRO_CC)
int a[2] = {1,2};
call_traits_checker<int[2]> c6; call_traits_checker<int[2]> c6;
c6(a); c6(a);
#endif #endif
#endif #endif
check_wrap(wrap(2), 2); check_wrap(test_wrap_type(2), 2);
const char ca[4] = "abc"; #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC)
// compiler can't deduce this for some reason: check_wrap(test_wrap_type(a), a);
//check_wrap(wrap(ca), ca);
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
check_wrap(wrap(a), a);
check_make_pair(test::make_pair(a, a), a, a); check_make_pair(test::make_pair(a, a), a, a);
#endif #endif
@@ -233,12 +242,12 @@ int main(int argc, char *argv[ ])
type_test(int*&, boost::call_traits<int*>::reference) type_test(int*&, boost::call_traits<int*>::reference)
type_test(int*const&, boost::call_traits<int*>::const_reference) type_test(int*const&, boost::call_traits<int*>::const_reference)
type_test(int*const, boost::call_traits<int*>::param_type) type_test(int*const, boost::call_traits<int*>::param_type)
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) #if defined(BOOST_MSVC6_MEMBER_TEMPLATES)
type_test(int&, boost::call_traits<int&>::value_type) type_test(int&, boost::call_traits<int&>::value_type)
type_test(int&, boost::call_traits<int&>::reference) type_test(int&, boost::call_traits<int&>::reference)
type_test(const int&, boost::call_traits<int&>::const_reference) type_test(const int&, boost::call_traits<int&>::const_reference)
type_test(int&, boost::call_traits<int&>::param_type) type_test(int&, boost::call_traits<int&>::param_type)
#if !(defined(__GNUC__) && (__GNUC__ < 4)) #if !(defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1)))
type_test(int&, boost::call_traits<cr_type>::value_type) type_test(int&, boost::call_traits<cr_type>::value_type)
type_test(int&, boost::call_traits<cr_type>::reference) type_test(int&, boost::call_traits<cr_type>::reference)
type_test(const int&, boost::call_traits<cr_type>::const_reference) type_test(const int&, boost::call_traits<cr_type>::const_reference)
@@ -261,16 +270,26 @@ int main(int argc, char *argv[ ])
type_test(const int(&)[3], boost::call_traits<const int[3]>::reference) type_test(const int(&)[3], boost::call_traits<const int[3]>::reference)
type_test(const int(&)[3], boost::call_traits<const int[3]>::const_reference) type_test(const int(&)[3], boost::call_traits<const int[3]>::const_reference)
type_test(const int*const, boost::call_traits<const int[3]>::param_type) type_test(const int*const, boost::call_traits<const int[3]>::param_type)
// test with abstract base class:
type_test(test_abc1, boost::call_traits<test_abc1>::value_type)
type_test(test_abc1&, boost::call_traits<test_abc1>::reference)
type_test(const test_abc1&, boost::call_traits<test_abc1>::const_reference)
type_test(const test_abc1&, boost::call_traits<test_abc1>::param_type)
#else #else
std::cout << "You're compiler does not support partial template instantiation, skipping 8 tests (8 errors)" << std::endl; std::cout << "You're compiler does not support partial template specialiation, skipping 8 tests (8 errors)" << std::endl;
failures += 8; failures += 12;
test_count += 8; test_count += 12;
#endif #endif
#else #else
std::cout << "You're compiler does not support partial template instantiation, skipping 20 tests (20 errors)" << std::endl; std::cout << "You're compiler does not support partial template specialiation, skipping 20 tests (20 errors)" << std::endl;
failures += 20; failures += 24;
test_count += 20; test_count += 24;
#endif #endif
// test with an incomplete type:
type_test(incomplete_type, boost::call_traits<incomplete_type>::value_type)
type_test(incomplete_type&, boost::call_traits<incomplete_type>::reference)
type_test(const incomplete_type&, boost::call_traits<incomplete_type>::const_reference)
type_test(const incomplete_type&, boost::call_traits<incomplete_type>::param_type)
return check_result(argc, argv); return check_result(argc, argv);
} }
@@ -312,6 +331,19 @@ void call_traits_test<T, isarray>::assert_construct(typename call_traits_test<T,
param_type p2(v); param_type p2(v);
param_type p3(r); param_type p3(r);
param_type p4(p); param_type p4(p);
unused_variable(v2);
unused_variable(v3);
unused_variable(v4);
unused_variable(r2);
unused_variable(r3);
unused_variable(cr2);
unused_variable(cr3);
unused_variable(cr4);
unused_variable(cr5);
unused_variable(p2);
unused_variable(p3);
unused_variable(p4);
} }
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <typename T> template <typename T>
@@ -348,6 +380,19 @@ void call_traits_test<T, true>::assert_construct(typename boost::call_traits<T>:
param_type p2(v); param_type p2(v);
param_type p3(r); param_type p3(r);
param_type p4(p); param_type p4(p);
unused_variable(v2);
unused_variable(v3);
unused_variable(v4);
unused_variable(v5);
#ifndef __BORLANDC__
unused_variable(r2);
unused_variable(cr2);
#endif
unused_variable(cr3);
unused_variable(p2);
unused_variable(p3);
unused_variable(p4);
} }
#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// //
@@ -355,26 +400,31 @@ void call_traits_test<T, true>::assert_construct(typename boost::call_traits<T>:
template struct call_traits_test<int>; template struct call_traits_test<int>;
template struct call_traits_test<const int>; template struct call_traits_test<const int>;
template struct call_traits_test<int*>; template struct call_traits_test<int*>;
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) #if defined(BOOST_MSVC6_MEMBER_TEMPLATES)
template struct call_traits_test<int&>; template struct call_traits_test<int&>;
template struct call_traits_test<const int&>; template struct call_traits_test<const int&>;
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC)
template struct call_traits_test<int[2], true>; template struct call_traits_test<int[2], true>;
#endif #endif
#endif #endif
#ifdef BOOST_MSVC #if defined(BOOST_MSVC) && _MSC_VER <= 1300
unsigned int expected_failures = 10; unsigned int expected_failures = 14;
#elif defined(__SUNPRO_CC) #elif defined(__SUNPRO_CC)
unsigned int expected_failures = 11; #if(__SUNPRO_CC <= 0x520)
unsigned int expected_failures = 18;
#elif(__SUNPRO_CC < 0x530)
unsigned int expected_failures = 17;
#else
unsigned int expected_failures = 6;
#endif
#elif defined(__BORLANDC__) #elif defined(__BORLANDC__)
unsigned int expected_failures = 2; unsigned int expected_failures = 2;
#elif defined(__GNUC__) #elif (defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1)))
unsigned int expected_failures = 4; unsigned int expected_failures = 4;
#elif defined(__HP_aCC)
unsigned int expected_failures = 24;
#else #else
unsigned int expected_failures = 0; unsigned int expected_failures = 0;
#endif #endif

124
checked_delete.html Normal file
View File

@@ -0,0 +1,124 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Boost: checked_delete.hpp documentation</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
<table border="0" width="100%">
<tr>
<td width="277">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277" height="86">
</td>
<td align="middle">
<h1>checked_delete.hpp</h1>
</td>
</tr>
<tr>
<td colspan="2" height="64">&nbsp;</td>
</tr>
</table>
<p>
The header <STRONG>&lt;boost/checked_delete.hpp&gt;</STRONG> defines two
function templates, <STRONG>checked_delete</STRONG> and <STRONG>checked_array_delete</STRONG>,
and two class templates, <STRONG>checked_deleter</STRONG> and <STRONG>checked_array_deleter</STRONG>.
</p>
<P>The C++ Standard allows, in 5.3.5/5, pointers to incomplete class types to be
deleted with a <EM>delete-expression</EM>. When the class has a non-trivial
destructor, or a class-specific operator delete, the behavior is undefined.
Some compilers issue a warning when an incomplete type is deleted, but
unfortunately, not all do, and programmers sometimes ignore or disable
warnings.</P>
<P>A particularly troublesome case is when a smart pointer's destructor, such as <STRONG>
boost::scoped_ptr&lt;T&gt;::~scoped_ptr</STRONG>, is instantiated with an
incomplete type. This can often lead to silent, hard to track failures.</P>
<P>The supplied function and class templates can be used to prevent these problems,
as they require a complete type, and cause a compilation error otherwise.</P>
<h3><a name="Synopsis">Synopsis</a></h3>
<pre>
namespace boost
{
template&lt;class T&gt; void checked_delete(T * p);
template&lt;class T&gt; void checked_array_delete(T * p);
template&lt;class T&gt; struct checked_deleter;
template&lt;class T&gt; struct checked_array_deleter;
}
</pre>
<h3>checked_delete</h3>
<h4><a name="checked_delete">template&lt;class T&gt; void checked_delete(T * p);</a></h4>
<blockquote>
<p>
<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete p</tt>
must be well-formed.
</p>
<p>
<b>Effects:</b> <tt>delete p;</tt>
</p>
</blockquote>
<h3>checked_array_delete</h3>
<h4><a name="checked_array_delete">template&lt;class T&gt; void checked_array_delete(T
* p);</a></h4>
<blockquote>
<p>
<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete [] p</tt>
must be well-formed.
</p>
<p>
<b>Effects:</b> <tt>delete [] p;</tt>
</p>
</blockquote>
<h3>checked_deleter</h3>
<pre>
template&lt;class T&gt; struct checked_deleter
{
typedef void result_type;
typedef T * argument_type;
void operator()(T * p) const;
};
</pre>
<h4>void checked_deleter&lt;T&gt;::operator()(T * p) const;</h4>
<blockquote>
<p>
<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete p</tt>
must be well-formed.
</p>
<p>
<b>Effects:</b> <tt>delete p;</tt>
</p>
</blockquote>
<h3>checked_array_deleter</h3>
<pre>
template&lt;class T&gt; struct checked_array_deleter
{
typedef void result_type;
typedef T * argument_type;
void operator()(T * p) const;
};
</pre>
<h4>void checked_array_deleter&lt;T&gt;::operator()(T * p) const;</h4>
<blockquote>
<p>
<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete [] p</tt>
must be well-formed.
</p>
<p>
<b>Effects:</b> <tt>delete [] p;</tt>
</p>
</blockquote>
<h3><a name="Acknowledgements">Acknowledgements</a></h3>
<p>
The function templates <STRONG>checked_delete</STRONG> and <STRONG>checked_array_delete</STRONG>
were originally part of <STRONG>&lt;boost/utility.hpp&gt;</STRONG>, and the
documentation acknowledged Beman Dawes, Dave Abrahams, Vladimir Prus, Rainer
Deyke, John Maddock, and others as contributors.
</p>
<p>
<br>
<small>Copyright <20> 2002 by Peter Dimov. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears in
all copies. This document is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.</small></p>
</body>
</html>

View File

@@ -11,7 +11,7 @@
// Revision History // Revision History
// 21 May 01 Initial version (Beman Dawes) // 21 May 01 Initial version (Beman Dawes)
#include <boost/utility.hpp> // for checked_delete #include <boost/checked_delete.hpp> // for checked_delete
// This program demonstrates compiler errors when trying to delete an // This program demonstrates compiler errors when trying to delete an
// incomplete type. // incomplete type.

View File

@@ -21,8 +21,8 @@ defined inside namespace boost.</p>
<p>The class compressed pair is very similar to std::pair, but if <p>The class compressed pair is very similar to std::pair, but if
either of the template arguments are empty classes, then the either of the template arguments are empty classes, then the
&quot;empty member optimisation&quot; is applied to compress the &quot;empty base-class optimisation&quot; is applied to compress
size of the pair.</p> the size of the pair.</p>
<pre>template &lt;class T1, class T2&gt; <pre>template &lt;class T1, class T2&gt;
class compressed_pair class compressed_pair

View File

@@ -199,7 +199,7 @@ struct compressed_pair_reference1_tester
}; };
template <class T1, class T2> template <class T1, class T2>
void compressed_pair_reference1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) void compressed_pair_reference1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
{ {
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// first param construct: // first param construct:
@@ -225,7 +225,7 @@ struct compressed_pair_reference2_tester
}; };
template <class T1, class T2> template <class T1, class T2>
void compressed_pair_reference2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) void compressed_pair_reference2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
{ {
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// second param construct: // second param construct:
@@ -252,7 +252,7 @@ struct compressed_pair_array1_tester
}; };
template <class T1, class T2> template <class T1, class T2>
void compressed_pair_array1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) void compressed_pair_array1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
{ {
// default construct: // default construct:
boost::compressed_pair<T1,T2> cp1; boost::compressed_pair<T1,T2> cp1;
@@ -282,7 +282,7 @@ struct compressed_pair_array2_tester
}; };
template <class T1, class T2> template <class T1, class T2>
void compressed_pair_array2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) void compressed_pair_array2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
{ {
// default construct: // default construct:
boost::compressed_pair<T1,T2> cp1; boost::compressed_pair<T1,T2> cp1;
@@ -312,7 +312,7 @@ struct compressed_pair_array_tester
}; };
template <class T1, class T2> template <class T1, class T2>
void compressed_pair_array_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) void compressed_pair_array_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
{ {
// default construct: // default construct:
boost::compressed_pair<T1,T2> cp1; boost::compressed_pair<T1,T2> cp1;
@@ -329,7 +329,7 @@ void compressed_pair_array_tester<T1, T2>::test(first_param_type p1, second_para
BOOST_TEST(sizeof(T2) == sizeof(cp1.second())); BOOST_TEST(sizeof(T2) == sizeof(cp1.second()));
} }
int test_main(int argc, char *argv[ ]) int test_main(int, char *[])
{ {
// declare some variables to pass to the tester: // declare some variables to pass to the tester:
non_empty1 ne1(2); non_empty1 ne1(2);

View File

@@ -308,7 +308,7 @@ implementation, the <tt>difference_type</tt> for any variable-length signed
integer type <tt>T</tt> is <tt>T</tt> itself. integer type <tt>T</tt> is <tt>T</tt> itself.
<hr> <hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" --></p> <p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" --></p>
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use, <p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
modify, sell and distribute this document is granted provided this copyright modify, sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &quot;as is&quot; notice appears in all copies. This document is provided &quot;as is&quot;

View File

@@ -36,10 +36,14 @@ int main(int, char*[])
std::vector<std::vector<int>::iterator> pointers; std::vector<std::vector<int>::iterator> pointers;
// Use counting iterator to fill in the array of pointers. // Use counting iterator to fill in the array of pointers.
// causes an ICE with MSVC6
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
std::copy(boost::make_counting_iterator(numbers.begin()), std::copy(boost::make_counting_iterator(numbers.begin()),
boost::make_counting_iterator(numbers.end()), boost::make_counting_iterator(numbers.end()),
std::back_inserter(pointers)); std::back_inserter(pointers));
#endif
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1300)
// Use indirect iterator to print out numbers by accessing // Use indirect iterator to print out numbers by accessing
// them through the array of pointers. // them through the array of pointers.
std::cout << "indirectly printing out the numbers from 0 to " std::cout << "indirectly printing out the numbers from 0 to "
@@ -48,6 +52,6 @@ int main(int, char*[])
boost::make_indirect_iterator(pointers.end()), boost::make_indirect_iterator(pointers.end()),
std::ostream_iterator<int>(std::cout, " ")); std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl; std::cout << std::endl;
#endif
return 0; return 0;
} }

View File

@@ -27,7 +27,9 @@
#include <climits> #include <climits>
#include <iterator> #include <iterator>
#include <stdlib.h> #include <stdlib.h>
#include <boost/utility.hpp> #ifndef __BORLANDC__
# include <boost/tuple/tuple.hpp>
#endif
#include <vector> #include <vector>
#include <list> #include <list>
#include <cassert> #include <cassert>
@@ -72,8 +74,12 @@ void category_test(
// Try some binary searches on the range to show that it's ordered // Try some binary searches on the range to show that it's ordered
assert(std::binary_search(start, finish, *internal)); assert(std::binary_search(start, finish, *internal));
CountingIterator x,y;
boost::tie(x,y) = std::equal_range(start, finish, *internal); // #including tuple crashed borland, so I had to give up on tie().
std::pair<CountingIterator,CountingIterator> xy(
std::equal_range(start, finish, *internal));
CountingIterator x = xy.first, y = xy.second;
assert(boost::detail::distance(x, y) == 1); assert(boost::detail::distance(x, y) == 1);
// Show that values outside the range can't be found // Show that values outside the range can't be found
@@ -234,14 +240,14 @@ int main()
test_integer<unsigned int>(); test_integer<unsigned int>();
test_integer<long>(); test_integer<long>();
test_integer<unsigned long>(); test_integer<unsigned long>();
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) #if defined(BOOST_HAS_LONG_LONG)
test_integer<long long>(); test_integer<long long>();
test_integer<unsigned long long>(); test_integer<unsigned long long>();
#endif #endif
// wrapping an iterator or non-built-in integer type causes an INTERNAL // wrapping an iterator or non-built-in integer type causes an INTERNAL
// COMPILER ERROR in MSVC without STLport. I'm clueless as to why. // COMPILER ERROR in MSVC without STLport. I'm clueless as to why.
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT) #if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 || defined(__SGI_STL_PORT)
// Test user-defined type. // Test user-defined type.
test_integer<my_int1>(); test_integer<my_int1>();
test_integer<my_int2>(); test_integer<my_int2>();

38
current_function.html Normal file
View File

@@ -0,0 +1,38 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Boost: current_function.hpp documentation</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
<table border="0" width="100%">
<tr>
<td width="277">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277" height="86">
</td>
<td align="middle">
<h1>current_function.hpp</h1>
</td>
</tr>
<tr>
<td colspan="2" height="64">&nbsp;</td>
</tr>
</table>
<p>
The header <STRONG>&lt;boost/current_function.hpp&gt;</STRONG> defines a single
macro, <STRONG>BOOST_CURRENT_FUNCTION</STRONG>,<STRONG> </STRONG>similar to the
C99 predefined identifier <STRONG>__func__</STRONG>.
</p>
<P><STRONG>BOOST_CURRENT_FUNCTION</STRONG> expands to a string literal containing
the (fully qualified, if possible) name of the enclosing function. If there is
no enclosing function, the behavior is undefined.</P>
<p>Some compilers do not provide a way to obtain the name of the current enclosing
function. On such compilers, the string literal has an unspecified value.</p>
<p>
<br>
<small>Copyright <20> 2002 by Peter Dimov. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears in
all copies. This document is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.</small></p>
</body>
</html>

32
current_function_test.cpp Normal file
View File

@@ -0,0 +1,32 @@
#if defined(_MSC_VER) && !defined(__ICL)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#endif
//
// current_function_test.cpp - a test for boost/current_function.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/current_function.hpp>
#include <cstdio>
void message(char const * file, long line, char const * func, char const * msg)
{
std::printf("%s(%ld): %s in function '%s'\n", file, line, msg, func);
}
#define MESSAGE(msg) message(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, msg)
int main()
{
MESSAGE("assertion failed");
}

View File

@@ -195,7 +195,7 @@ The policies type has only one public function, which is its constructor:
<pre> <pre>
template &lt;class Predicate, class BaseIterator&gt; template &lt;class Predicate, class BaseIterator&gt;
typename detail::filter_generator&lt;Predicate, BaseIterator&gt;::type typename filter_generator&lt;Predicate, BaseIterator&gt;::type
make_filter_iterator(BaseIterator first, BaseIterator last, const Predicate& p = Predicate()) make_filter_iterator(BaseIterator first, BaseIterator last, const Predicate& p = Predicate())
</pre> </pre>

View File

@@ -7,7 +7,6 @@
// "as is" without express or implied warranty, and with no claim as // "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose. // to its suitability for any purpose.
#include <boost/config.hpp> #include <boost/config.hpp>
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
@@ -20,8 +19,17 @@ struct is_positive_number {
int main() int main()
{ {
int numbers[] = { 0, -1, 4, -3, 5, 8, -2 }; int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 };
const int N = sizeof(numbers)/sizeof(int); const int N = sizeof(numbers_)/sizeof(int);
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
// Assume there won't be proper iterator traits for pointers. This
// is just a wrapper for int* which has the right traits.
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies, int> base_iterator;
#else
typedef int* base_iterator;
#endif
base_iterator numbers(numbers_);
// Example using make_filter_iterator() // Example using make_filter_iterator()
std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N), std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
@@ -30,7 +38,7 @@ int main()
std::cout << std::endl; std::cout << std::endl;
// Example using filter_iterator_generator // Example using filter_iterator_generator
typedef boost::filter_iterator_generator<is_positive_number, int*, int>::type typedef boost::filter_iterator_generator<is_positive_number, base_iterator, int>::type
FilterIter; FilterIter;
is_positive_number predicate; is_positive_number predicate;
FilterIter::policies_type policies(predicate, numbers + N); FilterIter::policies_type policies(predicate, numbers + N);

150
generator_iterator.htm Normal file
View File

@@ -0,0 +1,150 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title>Generator Iterator Adaptor Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">
<h1>Generator Iterator Adaptor</h1>
Defined in header <a href="../../boost/generator_iterator.hpp">boost/generator_iterator.hpp</a>
<p>
The generator iterator adaptor makes it easier to create custom input
iterators from 0-ary functions and function objects. The adaptor
takes a
<a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>
and creates a model of
<a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>.
Each increment retrieves an item from the generator and makes it
available to be retrieved by dereferencing. The motivation for this
iterator is that some concepts can be more naturally expressed as a
generator, while most STL algorithms expect an iterator. An example
is the <a href="../random/index.html">Random Number</a> library.
<h2>Synopsis</h2>
<blockquote>
<pre>
namespace boost {
template &lt;class Generator&gt;
class generator_iterator_policies;
template &lt;class Generator&gt;
class generator_iterator_generator;
template &lt;class Generator&gt;
typename generator_iterator_generator&lt;Generator&gt;::type
make_generator_iterator(Generator &amp; gen);
}
</pre>
</blockquote>
<hr>
<h2>The Generator Iterator Generator Class</h2>
The class generator_iterator_generator is a helper class whose purpose
is to construct a generator iterator type. The template parameter for
this class is the Generator function object type that is being
wrapped. The generator iterator adaptor only holds a reference (or
pointer) to the function object, therefore the function object must
outlive the generator iterator adaptor constructed from it.
<pre>
template &lt;class Generator>
class generator_iterator_generator
{
public:
typedef <a href="iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt...&gt; type; // the resulting generator iterator type
}
</pre>
<h3>Template Parameters</h3>
<table border>
<tr>
<th>Parameter</th>
<th>Description</th>
</tr>
<tr>
<td><tt><a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a></tt>
<td>The generator (0-ary function object) type being
wrapped. The return type of the function must be defined as
<tt>Generator::result_type</tt>. The function object must be a model
of
<a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>.
</td>
</table>
<h3>Concept Model</h3>
The generator iterator class is a model of
<a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>.
<h3>Members</h3>
The generator iterator implements the member functions
and operators required of the
<a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>
concept.
<br>
<hr>
<h2><a name="make_generator_iterator">The Generator Iterator Object Generator</a></h2>
The <tt>make_generator_iterator()</tt> function provides a
convenient way to create generator iterator objects. The function
saves the user the trouble of explicitly writing out the iterator
types.
<blockquote>
<pre>
template &lt;class Generator&gt;
typename generator_iterator_generator&lt;Generator&gt;::type
make_generator_iterator(Generator &amp; gen);
</pre>
</blockquote>
<hr>
<h3>Example</h3>
The following program shows how <code>generator_iterator</code>
transforms a generator into an input iterator.
<blockquote>
<pre>
#include &lt;iostream>
#include &lt;boost/generator_iterator.hpp>
class my_generator
{
public:
typedef int result_type;
my_generator() : state(0) { }
int operator()() { return ++state; }
private:
int state;
};
int main()
{
my_generator gen;
boost::generator_iterator_generator&lt;my_generator&gt;::type it = boost::make_generator_iterator(gen);
for(int i = 0; i &lt; 10; ++i, ++it)
std::cout &lt;&lt; *it &lt;&lt; std::endl;
}
</pre>
</blockquote>
<hr>
Written by Jens Maurer.
</body>
</html>

View File

@@ -346,7 +346,7 @@ int main()
test_integer<unsigned int>(); test_integer<unsigned int>();
test_integer<long>(); test_integer<long>();
test_integer<unsigned long>(); test_integer<unsigned long>();
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) #if defined(BOOST_HAS_LONG_LONG)
test_integer<long long>(); test_integer<long long>();
test_integer<unsigned long long>(); test_integer<unsigned long long>();
#endif #endif

38
include/boost/assert.hpp Normal file
View File

@@ -0,0 +1,38 @@
//
// boost/assert.hpp - BOOST_ASSERT(expr)
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
//
// 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.
//
// Note: There are no include guards. This is intentional.
//
// See http://www.boost.org/libs/utility/assert.html for documentation.
//
#undef BOOST_ASSERT
#if defined(BOOST_DISABLE_ASSERTS)
# define BOOST_ASSERT(expr) ((void)0)
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
#include <boost/current_function.hpp>
namespace boost
{
void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined
} // namespace boost
#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
#else
# include <assert.h>
# define BOOST_ASSERT(expr) assert(expr)
#endif

View File

@@ -3,7 +3,7 @@
// in all copies. This software is provided "as is" without express or implied // 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. // warranty, and with no claim as to its suitability for any purpose.
// See http://www.boost.org for most recent version including documentation. // See http://www.boost.org/libs/utility/call_traits.htm for Documentation.
// See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp // See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp
// for full copyright notices. // for full copyright notices.

View File

@@ -0,0 +1,69 @@
#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
#define BOOST_CHECKED_DELETE_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/checked_delete.hpp
//
// Copyright (c) 1999, 2000, 2001, 2002 boost.org
// Copyright (c) 2002, 2003 Peter Dimov
// Copyright (c) 2003 Daniel Frey
// Copyright (c) 2003 Howard Hinnant
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// See http://www.boost.org/libs/utility/checked_delete.html for documentation.
//
namespace boost
{
// verify that types are complete for increased safety
template<class T> inline void checked_delete(T * x)
{
// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete x;
}
template<class T> inline void checked_array_delete(T * x)
{
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete [] x;
}
template<class T> struct checked_deleter
{
typedef void result_type;
typedef T * argument_type;
void operator()(T * x) const
{
// boost:: disables ADL
boost::checked_delete(x);
}
};
template<class T> struct checked_array_deleter
{
typedef void result_type;
typedef T * argument_type;
void operator()(T * x) const
{
boost::checked_array_delete(x);
}
};
} // namespace boost
#endif // #ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED

View File

@@ -0,0 +1,58 @@
#ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
#define BOOST_CURRENT_FUNCTION_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/current_function.hpp - BOOST_CURRENT_FUNCTION
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// 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.
//
// http://www.boost.org/libs/utility/current_function.html
//
namespace boost
{
namespace detail
{
inline void current_function_helper()
{
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000))
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
#elif defined(__FUNCSIG__)
# define BOOST_CURRENT_FUNCTION __FUNCSIG__
#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
# define BOOST_CURRENT_FUNCTION __FUNC__
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
# define BOOST_CURRENT_FUNCTION __func__
#else
# define BOOST_CURRENT_FUNCTION "(unknown)"
#endif
}
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED

View File

@@ -34,20 +34,32 @@ namespace boost{
namespace detail{ namespace detail{
template <typename T, bool isp, bool b1, bool b2> template <typename T, bool small_>
struct ct_imp2
{
typedef const T& param_type;
};
template <typename T>
struct ct_imp2<T, true>
{
typedef const T param_type;
};
template <typename T, bool isp, bool b1>
struct ct_imp struct ct_imp
{ {
typedef const T& param_type; typedef const T& param_type;
}; };
template <typename T, bool isp> template <typename T, bool isp>
struct ct_imp<T, isp, true, true> struct ct_imp<T, isp, true>
{ {
typedef T const param_type; typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
}; };
template <typename T, bool b1, bool b2> template <typename T, bool b1>
struct ct_imp<T, true, b1, b2> struct ct_imp<T, true, b1>
{ {
typedef T const param_type; typedef T const param_type;
}; };
@@ -67,7 +79,11 @@ public:
// however compiler bugs prevent this - instead pass three bool's to // however compiler bugs prevent this - instead pass three bool's to
// ct_imp<T,bool,bool,bool> and add an extra partial specialisation // ct_imp<T,bool,bool,bool> and add an extra partial specialisation
// of ct_imp to handle the logic. (JM) // of ct_imp to handle the logic. (JM)
typedef typename detail::ct_imp<T, ::boost::is_pointer<typename remove_const<T>::type>::value, ::boost::is_arithmetic<typename remove_const<T>::type>::value, sizeof(T) <= sizeof(void*)>::param_type param_type; typedef typename detail::ct_imp<
T,
::boost::is_pointer<T>::value,
::boost::is_arithmetic<T>::value
>::param_type param_type;
}; };
template <typename T> template <typename T>
@@ -79,7 +95,7 @@ struct call_traits<T&>
typedef T& param_type; // hh removed const typedef T& param_type; // hh removed const
}; };
#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x551) #if defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
// these are illegal specialisations; cv-qualifies applied to // these are illegal specialisations; cv-qualifies applied to
// references have no effect according to [8.3.2p1], // references have no effect according to [8.3.2p1],
// C++ Builder requires them though as it treats cv-qualified // C++ Builder requires them though as it treats cv-qualified
@@ -109,7 +125,7 @@ struct call_traits<T&const volatile>
typedef T& param_type; // hh removed const typedef T& param_type; // hh removed const
}; };
#endif #endif
#ifndef __SUNPRO_CC
template <typename T, std::size_t N> template <typename T, std::size_t N>
struct call_traits<T [N]> struct call_traits<T [N]>
{ {
@@ -135,6 +151,7 @@ public:
typedef const array_type& const_reference; typedef const array_type& const_reference;
typedef const T* const param_type; typedef const T* const param_type;
}; };
#endif
} }

View File

@@ -32,6 +32,10 @@
namespace boost namespace boost
{ {
template <class T1, class T2>
class compressed_pair;
// compressed_pair // compressed_pair
namespace details namespace details
@@ -104,10 +108,10 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y) compressed_pair_imp(first_param_type x, second_param_type y)
: first_(x), second_(y) {} : first_(x), second_(y) {}
explicit compressed_pair_imp(first_param_type x) compressed_pair_imp(first_param_type x)
: first_(x) {} : first_(x) {}
explicit compressed_pair_imp(second_param_type y) compressed_pair_imp(second_param_type y)
: second_(y) {} : second_(y) {}
first_reference first() {return first_;} first_reference first() {return first_;}
@@ -116,10 +120,10 @@ namespace details
second_reference second() {return second_;} second_reference second() {return second_;}
second_const_reference second() const {return second_;} second_const_reference second() const {return second_;}
void swap(compressed_pair_imp& y) void swap(::boost::compressed_pair<T1, T2>& y)
{ {
cp_swap(first_, y.first_); cp_swap(first_, y.first());
cp_swap(second_, y.second_); cp_swap(second_, y.second());
} }
private: private:
first_type first_; first_type first_;
@@ -147,10 +151,10 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y) compressed_pair_imp(first_param_type x, second_param_type y)
: first_type(x), second_(y) {} : first_type(x), second_(y) {}
explicit compressed_pair_imp(first_param_type x) compressed_pair_imp(first_param_type x)
: first_type(x) {} : first_type(x) {}
explicit compressed_pair_imp(second_param_type y) compressed_pair_imp(second_param_type y)
: second_(y) {} : second_(y) {}
first_reference first() {return *this;} first_reference first() {return *this;}
@@ -159,10 +163,10 @@ namespace details
second_reference second() {return second_;} second_reference second() {return second_;}
second_const_reference second() const {return second_;} second_const_reference second() const {return second_;}
void swap(compressed_pair_imp& y) void swap(::boost::compressed_pair<T1,T2>& y)
{ {
// no need to swap empty base class: // no need to swap empty base class:
cp_swap(second_, y.second_); cp_swap(second_, y.second());
} }
private: private:
second_type second_; second_type second_;
@@ -189,10 +193,10 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y) compressed_pair_imp(first_param_type x, second_param_type y)
: second_type(y), first_(x) {} : second_type(y), first_(x) {}
explicit compressed_pair_imp(first_param_type x) compressed_pair_imp(first_param_type x)
: first_(x) {} : first_(x) {}
explicit compressed_pair_imp(second_param_type y) compressed_pair_imp(second_param_type y)
: second_type(y) {} : second_type(y) {}
first_reference first() {return first_;} first_reference first() {return first_;}
@@ -201,10 +205,10 @@ namespace details
second_reference second() {return *this;} second_reference second() {return *this;}
second_const_reference second() const {return *this;} second_const_reference second() const {return *this;}
void swap(compressed_pair_imp& y) void swap(::boost::compressed_pair<T1,T2>& y)
{ {
// no need to swap empty base class: // no need to swap empty base class:
cp_swap(first_, y.first_); cp_swap(first_, y.first());
} }
private: private:
@@ -233,10 +237,10 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y) compressed_pair_imp(first_param_type x, second_param_type y)
: first_type(x), second_type(y) {} : first_type(x), second_type(y) {}
explicit compressed_pair_imp(first_param_type x) compressed_pair_imp(first_param_type x)
: first_type(x) {} : first_type(x) {}
explicit compressed_pair_imp(second_param_type y) compressed_pair_imp(second_param_type y)
: second_type(y) {} : second_type(y) {}
first_reference first() {return *this;} first_reference first() {return *this;}
@@ -246,7 +250,7 @@ namespace details
second_const_reference second() const {return *this;} second_const_reference second() const {return *this;}
// //
// no need to swap empty bases: // no need to swap empty bases:
void swap(compressed_pair_imp&) {} void swap(::boost::compressed_pair<T1,T2>&) {}
}; };
// JM // JM
@@ -272,7 +276,7 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type) compressed_pair_imp(first_param_type x, second_param_type)
: first_type(x) {} : first_type(x) {}
explicit compressed_pair_imp(first_param_type x) compressed_pair_imp(first_param_type x)
: first_type(x) {} : first_type(x) {}
first_reference first() {return *this;} first_reference first() {return *this;}
@@ -281,7 +285,7 @@ namespace details
second_reference second() {return *this;} second_reference second() {return *this;}
second_const_reference second() const {return *this;} second_const_reference second() const {return *this;}
void swap(compressed_pair_imp&) {} void swap(::boost::compressed_pair<T1,T2>&) {}
private: private:
}; };
@@ -305,7 +309,7 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y) compressed_pair_imp(first_param_type x, second_param_type y)
: first_(x), second_(y) {} : first_(x), second_(y) {}
explicit compressed_pair_imp(first_param_type x) compressed_pair_imp(first_param_type x)
: first_(x), second_(x) {} : first_(x), second_(x) {}
first_reference first() {return first_;} first_reference first() {return first_;}
@@ -314,10 +318,10 @@ namespace details
second_reference second() {return second_;} second_reference second() {return second_;}
second_const_reference second() const {return second_;} second_const_reference second() const {return second_;}
void swap(compressed_pair_imp<T1, T2, 5>& y) void swap(::boost::compressed_pair<T1, T2>& y)
{ {
cp_swap(first_, y.first_); cp_swap(first_, y.first());
cp_swap(second_, y.second_); cp_swap(second_, y.second());
} }
private: private:
first_type first_; first_type first_;
@@ -401,7 +405,10 @@ public:
compressed_pair() : base() {} compressed_pair() : base() {}
compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
explicit compressed_pair(first_param_type x) : base(x) {} #if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530))
explicit
#endif
compressed_pair(first_param_type x) : base(x) {}
first_reference first() {return base::first();} first_reference first() {return base::first();}
first_const_reference first() const {return base::first();} first_const_reference first() const {return base::first();}
@@ -409,7 +416,7 @@ public:
second_reference second() {return base::second();} second_reference second() {return base::second();}
second_const_reference second() const {return base::second();} second_const_reference second() const {return base::second();}
void swap(compressed_pair& y) { base::swap(y); } void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
}; };
template <class T1, class T2> template <class T1, class T2>

View File

@@ -33,7 +33,7 @@
namespace boost{ namespace boost{
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) #ifdef BOOST_MSVC6_MEMBER_TEMPLATES
// //
// use member templates to emulate // use member templates to emulate
// partial specialisation: // partial specialisation:
@@ -64,7 +64,8 @@ struct reference_call_traits
typedef T const_reference; typedef T const_reference;
typedef T param_type; typedef T param_type;
}; };
template <bool simple, bool reference>
template <bool pointer, bool arithmetic, bool reference>
struct call_traits_chooser struct call_traits_chooser
{ {
template <class T> template <class T>
@@ -73,8 +74,9 @@ struct call_traits_chooser
typedef standard_call_traits<T> type; typedef standard_call_traits<T> type;
}; };
}; };
template <> template <>
struct call_traits_chooser<true, false> struct call_traits_chooser<true, false, false>
{ {
template <class T> template <class T>
struct rebind struct rebind
@@ -82,8 +84,9 @@ struct call_traits_chooser<true, false>
typedef simple_call_traits<T> type; typedef simple_call_traits<T> type;
}; };
}; };
template <> template <>
struct call_traits_chooser<false, true> struct call_traits_chooser<false, false, true>
{ {
template <class T> template <class T>
struct rebind struct rebind
@@ -91,12 +94,50 @@ struct call_traits_chooser<false, true>
typedef reference_call_traits<T> type; typedef reference_call_traits<T> type;
}; };
}; };
template <bool size_is_small>
struct call_traits_sizeof_chooser2
{
template <class T>
struct small_rebind
{
typedef simple_call_traits<T> small_type;
};
};
template<>
struct call_traits_sizeof_chooser2<false>
{
template <class T>
struct small_rebind
{
typedef standard_call_traits<T> small_type;
};
};
template <>
struct call_traits_chooser<false, true, false>
{
template <class T>
struct rebind
{
enum { sizeof_choice = (sizeof(T) <= sizeof(void*)) };
typedef call_traits_sizeof_chooser2<(sizeof(T) <= sizeof(void*))> chooser;
typedef typename chooser::template small_rebind<T> bound_type;
typedef typename bound_type::small_type type;
};
};
} // namespace detail } // namespace detail
template <typename T> template <typename T>
struct call_traits struct call_traits
{ {
private: private:
typedef detail::call_traits_chooser<(is_pointer<T>::value || is_arithmetic<T>::value) && sizeof(T) <= sizeof(void*), is_reference<T>::value> chooser; typedef detail::call_traits_chooser<
::boost::is_pointer<T>::value,
::boost::is_arithmetic<T>::value,
::boost::is_reference<T>::value
> chooser;
typedef typename chooser::template rebind<T> bound_type; typedef typename chooser::template rebind<T> bound_type;
typedef typename bound_type::type call_traits_type; typedef typename bound_type::type call_traits_type;
public: public:

View File

@@ -38,7 +38,7 @@
namespace boost namespace boost
{ {
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) #ifdef BOOST_MSVC6_MEMBER_TEMPLATES
// //
// use member templates to emulate // use member templates to emulate
// partial specialisation. Note that due to // partial specialisation. Note that due to
@@ -168,7 +168,7 @@ public:
compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x) compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
: T2(x.second()), _first(x.first()) {} : T2(x.second()), _first(x.first()) {}
#ifdef BOOST_MSVC #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
// Total weirdness. If the assignment to _first is moved after // Total weirdness. If the assignment to _first is moved after
// the call to the inherited operator=, then this breaks graph/test/graph.cpp // the call to the inherited operator=, then this breaks graph/test/graph.cpp
// by way of iterator_adaptor. // by way of iterator_adaptor.

View File

@@ -0,0 +1,75 @@
// (C) Copyright Jens Maurer 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
//
// Revision History:
// 15 Nov 2001 Jens Maurer
// created.
// See http://www.boost.org/libs/utility/iterator_adaptors.htm for documentation.
#ifndef BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
#define BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
#include <boost/iterator_adaptors.hpp>
#include <boost/ref.hpp>
namespace boost {
template<class Generator>
class generator_iterator_policies
{
public:
generator_iterator_policies() { }
template<class Base>
void initialize(Base& base) {
m_value = (*base)();
}
// The Iter template argument is necessary for compatibility with a MWCW
// bug workaround
template <class IteratorAdaptor>
void increment(IteratorAdaptor& iter) {
m_value = (*iter.base())();
}
template <class IteratorAdaptor>
const typename Generator::result_type&
dereference(const IteratorAdaptor&) const
{ return m_value; }
template <class IteratorAdaptor1, class IteratorAdaptor2>
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
{ return x.base() == y.base() &&
x.policies().m_value == y.policies().m_value; }
private:
typename Generator::result_type m_value;
};
template<class Generator>
struct generator_iterator_generator
{
typedef iterator_adaptor<Generator*, generator_iterator_policies<Generator>,
typename Generator::result_type, const typename Generator::result_type&,
const typename Generator::result_type*, std::input_iterator_tag,
long> type;
};
template <class Generator>
inline typename generator_iterator_generator<Generator>::type
make_generator_iterator(Generator & gen)
{
typedef typename generator_iterator_generator<Generator>::type result_t;
return result_t(&gen);
}
} // namespace boost
#endif // BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP

View File

@@ -0,0 +1,33 @@
// Boost next_prior.hpp header file ---------------------------------------//
// (C) Copyright Boost.org 1999-2003. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See http://www.boost.org/libs/utility for documentation.
#ifndef BOOST_NEXT_PRIOR_HPP_INCLUDED
#define BOOST_NEXT_PRIOR_HPP_INCLUDED
namespace boost {
// Helper functions for classes like bidirectional iterators not supporting
// operator+ and operator-
//
// Usage:
// const std::list<T>::iterator p = get_some_iterator();
// const std::list<T>::iterator prev = boost::prior(p);
// Contributed by Dave Abrahams
template <class T>
inline T next(T x) { return ++x; }
template <class T>
inline T prior(T x) { return --x; }
} // namespace boost
#endif // BOOST_NEXT_PRIOR_HPP_INCLUDED

View File

@@ -0,0 +1,33 @@
// Boost noncopyable.hpp header file --------------------------------------//
// (C) Copyright Boost.org 1999-2003. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See http://www.boost.org/libs/utility for documentation.
#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
#define BOOST_NONCOPYABLE_HPP_INCLUDED
namespace boost {
// Private copy constructor and copy assignment ensure classes derived from
// class noncopyable cannot be copied.
// Contributed by Dave Abrahams
class noncopyable
{
protected:
noncopyable() {}
~noncopyable() {}
private: // emphasize the following members are private
noncopyable( const noncopyable& );
const noncopyable& operator=( const noncopyable& );
};
} // namespace boost
#endif // BOOST_NONCOPYABLE_HPP_INCLUDED

View File

@@ -6,9 +6,18 @@
// software is provided "as is" without express or implied warranty, and // software is provided "as is" without express or implied warranty, and
// with no claim as to its suitability for any purpose. // with no claim as to its suitability for any purpose.
// See http://www.boost.org for most recent version including documentation. // See http://www.boost.org/libs/utility/operators.htm for documentation.
// Revision History // Revision History
// 21 Oct 02 Modified implementation of operators to allow compilers with a
// correct named return value optimization (NRVO) to produce optimal
// code. (Daniel Frey)
// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel)
// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker)
// 27 Aug 01 'left' form for non commutative operators added;
// additional classes for groups of related operators added;
// workaround for empty base class optimization
// bug of GCC 3.0 (Helmut Zeisel)
// 25 Jun 01 output_iterator_helper changes: removed default template // 25 Jun 01 output_iterator_helper changes: removed default template
// parameters, added support for self-proxying, additional // parameters, added support for self-proxying, additional
// documentation and tests (Aleksey Gurtovoy) // documentation and tests (Aleksey Gurtovoy)
@@ -81,7 +90,14 @@
namespace boost { namespace boost {
namespace detail { namespace detail {
// Helmut Zeisel, empty base class optimization bug with GCC 3.0.0
#if defined(__GNUC__) && __GNUC__==3 && __GNUC_MINOR__==0 && __GNU_PATCHLEVEL__==0
class empty_base {
bool dummy;
};
#else
class empty_base {}; class empty_base {};
#endif
} // namespace detail } // namespace detail
} // namespace boost } // namespace boost
@@ -136,106 +152,107 @@ struct equality_comparable1 : B
friend bool operator!=(const T& x, const T& y) { return !(x == y); } friend bool operator!=(const T& x, const T& y) { return !(x == y); }
}; };
template <class T, class U, class B = ::boost::detail::empty_base> // NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
struct multipliable2 : B
{ #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
friend T operator*(T x, const U& y) { return x *= y; }
friend T operator*(const U& y, T x) { return x *= y; } // This is the optimal implementation for ISO/ANSI C++,
// but it requires the compiler to implement the NRVO.
// If the compiler has no NRVO, this is the best symmetric
// implementation available.
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base> \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
friend T operator OP( const U& lhs, const T& rhs ) \
{ T nrv( rhs ); nrv OP##= lhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base> \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; };
template <class T, class B = ::boost::detail::empty_base> #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
struct multipliable1 : B template <class T, class U, class B = ::boost::detail::empty_base> \
{ struct NAME##2 : B \
friend T operator*(T x, const T& y) { return x *= y; } { \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class U, class B = ::boost::detail::empty_base> \
struct NAME##2_left : B \
{ \
friend T operator OP( const U& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base> \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; };
template <class T, class U, class B = ::boost::detail::empty_base> #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
struct addable2 : B
{ // For compilers without NRVO the following code is optimal, but not symmetric!
friend T operator+(T x, const U& y) { return x += y; } // Note that the implementation of NAME##2_left only looks cool, but doesn't
friend T operator+(const U& y, T x) { return x += y; } // provide optimization opportunities to the compiler :)
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base> \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base> \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
}; };
template <class T, class B = ::boost::detail::empty_base> #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
struct addable1 : B template <class T, class U, class B = ::boost::detail::empty_base> \
{ struct NAME##2 : B \
friend T operator+(T x, const T& y) { return x += y; } { \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
}; \
\
template <class T, class U, class B = ::boost::detail::empty_base> \
struct NAME##2_left : B \
{ \
friend T operator OP( const U& lhs, const T& rhs ) \
{ return T( lhs ) OP##= rhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base> \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
}; };
template <class T, class U, class B = ::boost::detail::empty_base> #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
struct subtractable2 : B
{
friend T operator-(T x, const U& y) { return x -= y; }
};
template <class T, class B = ::boost::detail::empty_base> BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
struct subtractable1 : B BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
{ BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
friend T operator-(T x, const T& y) { return x -= y; } BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
}; BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
template <class T, class U, class B = ::boost::detail::empty_base> #undef BOOST_BINARY_OPERATOR_COMMUTATIVE
struct dividable2 : B #undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
{
friend T operator/(T x, const U& y) { return x /= y; }
};
template <class T, class B = ::boost::detail::empty_base>
struct dividable1 : B
{
friend T operator/(T x, const T& y) { return x /= y; }
};
template <class T, class U, class B = ::boost::detail::empty_base>
struct modable2 : B
{
friend T operator%(T x, const U& y) { return x %= y; }
};
template <class T, class B = ::boost::detail::empty_base>
struct modable1 : B
{
friend T operator%(T x, const T& y) { return x %= y; }
};
template <class T, class U, class B = ::boost::detail::empty_base>
struct xorable2 : B
{
friend T operator^(T x, const U& y) { return x ^= y; }
friend T operator^(const U& y, T x) { return x ^= y; }
};
template <class T, class B = ::boost::detail::empty_base>
struct xorable1 : B
{
friend T operator^(T x, const T& y) { return x ^= y; }
};
template <class T, class U, class B = ::boost::detail::empty_base>
struct andable2 : B
{
friend T operator&(T x, const U& y) { return x &= y; }
friend T operator&(const U& y, T x) { return x &= y; }
};
template <class T, class B = ::boost::detail::empty_base>
struct andable1 : B
{
friend T operator&(T x, const T& y) { return x &= y; }
};
template <class T, class U, class B = ::boost::detail::empty_base>
struct orable2 : B
{
friend T operator|(T x, const U& y) { return x |= y; }
friend T operator|(const U& y, T x) { return x |= y; }
};
template <class T, class B = ::boost::detail::empty_base>
struct orable1 : B
{
friend T operator|(T x, const T& y) { return x |= y; }
};
// incrementable and decrementable contributed by Jeremy Siek // incrementable and decrementable contributed by Jeremy Siek
@@ -244,9 +261,9 @@ struct incrementable : B
{ {
friend T operator++(T& x, int) friend T operator++(T& x, int)
{ {
incrementable_type tmp(x); incrementable_type nrv(x);
++x; ++x;
return tmp; return nrv;
} }
private: // The use of this typedef works around a Borland bug private: // The use of this typedef works around a Borland bug
typedef T incrementable_type; typedef T incrementable_type;
@@ -257,9 +274,9 @@ struct decrementable : B
{ {
friend T operator--(T& x, int) friend T operator--(T& x, int)
{ {
decrementable_type tmp(x); decrementable_type nrv(x);
--x; --x;
return tmp; return nrv;
} }
private: // The use of this typedef works around a Borland bug private: // The use of this typedef works around a Borland bug
typedef T decrementable_type; typedef T decrementable_type;
@@ -286,30 +303,46 @@ struct indexable : B
}; };
// More operator classes (contributed by Daryle Walker) --------------------// // More operator classes (contributed by Daryle Walker) --------------------//
// (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
template <class T, class U, class B = ::boost::detail::empty_base> #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
struct left_shiftable2 : B
{ #define BOOST_BINARY_OPERATOR( NAME, OP ) \
friend T operator<<(T x, const U& y) { return x <<= y; } template <class T, class U, class B = ::boost::detail::empty_base> \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base> \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; };
template <class T, class B = ::boost::detail::empty_base> #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
struct left_shiftable1 : B
{ #define BOOST_BINARY_OPERATOR( NAME, OP ) \
friend T operator<<(T x, const T& y) { return x <<= y; } template <class T, class U, class B = ::boost::detail::empty_base> \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base> \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
}; };
template <class T, class U, class B = ::boost::detail::empty_base> #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
struct right_shiftable2 : B
{
friend T operator>>(T x, const U& y) { return x >>= y; }
};
template <class T, class B = ::boost::detail::empty_base> BOOST_BINARY_OPERATOR( left_shiftable, << )
struct right_shiftable1 : B BOOST_BINARY_OPERATOR( right_shiftable, >> )
{
friend T operator>>(T x, const T& y) { return x >>= y; } #undef BOOST_BINARY_OPERATOR
};
template <class T, class U, class B = ::boost::detail::empty_base> template <class T, class U, class B = ::boost::detail::empty_base>
struct equivalent2 : B struct equivalent2 : B
@@ -463,12 +496,125 @@ struct shiftable1
, right_shiftable1<T, B , right_shiftable1<T, B
> > {}; > > {};
template <class T, class U, class B = ::boost::detail::empty_base>
struct ring_operators2
: additive2<T, U
, subtractable2_left<T, U
, multipliable2<T, U, B
> > > {};
template <class T, class B = ::boost::detail::empty_base>
struct ring_operators1
: additive1<T
, multipliable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base>
struct ordered_ring_operators2
: ring_operators2<T, U
, totally_ordered2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base>
struct ordered_ring_operators1
: ring_operators1<T
, totally_ordered1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base>
struct field_operators2
: ring_operators2<T, U
, dividable2<T, U
, dividable2_left<T, U, B
> > > {};
template <class T, class B = ::boost::detail::empty_base>
struct field_operators1
: ring_operators1<T
, dividable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base>
struct ordered_field_operators2
: field_operators2<T, U
, totally_ordered2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base>
struct ordered_field_operators1
: field_operators1<T
, totally_ordered1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base>
struct euclidian_ring_operators2
: ring_operators2<T, U
, dividable2<T, U
, dividable2_left<T, U
, modable2<T, U
, modable2_left<T, U, B
> > > > > {};
template <class T, class B = ::boost::detail::empty_base>
struct euclidian_ring_operators1
: ring_operators1<T
, dividable1<T
, modable1<T, B
> > > {};
template <class T, class U, class B = ::boost::detail::empty_base>
struct ordered_euclidian_ring_operators2
: totally_ordered2<T, U
, euclidian_ring_operators2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base>
struct ordered_euclidian_ring_operators1
: totally_ordered1<T
, euclidian_ring_operators1<T, B
> > {};
template <class T, class P, class B = ::boost::detail::empty_base>
struct input_iteratable
: equality_comparable1<T
, incrementable<T
, dereferenceable<T, P, B
> > > {};
template <class T, class B = ::boost::detail::empty_base>
struct output_iteratable
: incrementable<T, B
> {};
template <class T, class P, class B = ::boost::detail::empty_base>
struct forward_iteratable
: input_iteratable<T, P, B
> {};
template <class T, class P, class B = ::boost::detail::empty_base>
struct bidirectional_iteratable
: forward_iteratable<T, P
, decrementable<T, B
> > {};
// To avoid repeated derivation from equality_comparable,
// which is an indirect base class of bidirectional_iterable,
// random_access_iteratable must not be derived from totally_ordered1
// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
template <class T, class P, class D, class R, class B = ::boost::detail::empty_base>
struct random_access_iteratable
: bidirectional_iteratable<T, P
, less_than_comparable1<T
, additive2<T, D
, indexable<T, D, R, B
> > > > {};
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
} // namespace boost } // namespace boost
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE #endif // BOOST_NO_OPERATORS_IN_NAMESPACE
// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE3 - // BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 -
// //
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an // When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used // operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
@@ -479,6 +625,7 @@ struct shiftable1
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
// The template is already in boost so we have nothing to do. // The template is already in boost so we have nothing to do.
# define BOOST_IMPORT_TEMPLATE4(template_name)
# define BOOST_IMPORT_TEMPLATE3(template_name) # define BOOST_IMPORT_TEMPLATE3(template_name)
# define BOOST_IMPORT_TEMPLATE2(template_name) # define BOOST_IMPORT_TEMPLATE2(template_name)
# define BOOST_IMPORT_TEMPLATE1(template_name) # define BOOST_IMPORT_TEMPLATE1(template_name)
@@ -489,6 +636,7 @@ struct shiftable1
// Bring the names in with a using-declaration // Bring the names in with a using-declaration
// to avoid stressing the compiler. // to avoid stressing the compiler.
# define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name;
# define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name; # define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name;
# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name; # define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name; # define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
@@ -497,6 +645,10 @@ struct shiftable1
// Otherwise, because a Borland C++ 5.5 bug prevents a using declaration // Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
// from working, we are forced to use inheritance for that compiler. // from working, we are forced to use inheritance for that compiler.
# define BOOST_IMPORT_TEMPLATE4(template_name) \
template <class T, class U, class V, class W, class B = ::boost::detail::empty_base> \
struct template_name : ::template_name<T, U, V, W, B> {};
# define BOOST_IMPORT_TEMPLATE3(template_name) \ # define BOOST_IMPORT_TEMPLATE3(template_name) \
template <class T, class U, class V, class B = ::boost::detail::empty_base> \ template <class T, class U, class V, class B = ::boost::detail::empty_base> \
struct template_name : ::template_name<T, U, V, B> {}; struct template_name : ::template_name<T, U, V, B> {};
@@ -542,6 +694,15 @@ template<class T> struct is_chained_base {
} // namespace boost } // namespace boost
// Import a 4-type-argument operator template into boost (if neccessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
BOOST_IMPORT_TEMPLATE4(template_name4) \
template<class T, class U, class V, class W, class B> \
struct is_chained_base< ::boost::template_name4<T, U, V, W, B> > { \
typedef ::boost::detail::true_t value; \
};
// Import a 3-type-argument operator template into boost (if neccessary) and // Import a 3-type-argument operator template into boost (if neccessary) and
// provide a specialization of 'is_chained_base<>' for it. // provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \ # define BOOST_OPERATOR_TEMPLATE3(template_name3) \
@@ -610,6 +771,8 @@ BOOST_OPERATOR_TEMPLATE1(template_name##1)
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
BOOST_IMPORT_TEMPLATE4(template_name4)
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \ # define BOOST_OPERATOR_TEMPLATE3(template_name3) \
BOOST_IMPORT_TEMPLATE3(template_name3) BOOST_IMPORT_TEMPLATE3(template_name3)
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \ # define BOOST_OPERATOR_TEMPLATE2(template_name2) \
@@ -632,8 +795,11 @@ BOOST_OPERATOR_TEMPLATE(equality_comparable)
BOOST_OPERATOR_TEMPLATE(multipliable) BOOST_OPERATOR_TEMPLATE(multipliable)
BOOST_OPERATOR_TEMPLATE(addable) BOOST_OPERATOR_TEMPLATE(addable)
BOOST_OPERATOR_TEMPLATE(subtractable) BOOST_OPERATOR_TEMPLATE(subtractable)
BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
BOOST_OPERATOR_TEMPLATE(dividable) BOOST_OPERATOR_TEMPLATE(dividable)
BOOST_OPERATOR_TEMPLATE2(dividable2_left)
BOOST_OPERATOR_TEMPLATE(modable) BOOST_OPERATOR_TEMPLATE(modable)
BOOST_OPERATOR_TEMPLATE2(modable2_left)
BOOST_OPERATOR_TEMPLATE(xorable) BOOST_OPERATOR_TEMPLATE(xorable)
BOOST_OPERATOR_TEMPLATE(andable) BOOST_OPERATOR_TEMPLATE(andable)
BOOST_OPERATOR_TEMPLATE(orable) BOOST_OPERATOR_TEMPLATE(orable)
@@ -658,14 +824,27 @@ BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
BOOST_OPERATOR_TEMPLATE(bitwise) BOOST_OPERATOR_TEMPLATE(bitwise)
BOOST_OPERATOR_TEMPLATE1(unit_steppable) BOOST_OPERATOR_TEMPLATE1(unit_steppable)
BOOST_OPERATOR_TEMPLATE(shiftable) BOOST_OPERATOR_TEMPLATE(shiftable)
BOOST_OPERATOR_TEMPLATE(ring_operators)
BOOST_OPERATOR_TEMPLATE(ordered_ring_operators)
BOOST_OPERATOR_TEMPLATE(field_operators)
BOOST_OPERATOR_TEMPLATE(ordered_field_operators)
BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators)
BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators)
BOOST_OPERATOR_TEMPLATE2(input_iteratable)
BOOST_OPERATOR_TEMPLATE1(output_iteratable)
BOOST_OPERATOR_TEMPLATE2(forward_iteratable)
BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable)
BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
#undef BOOST_OPERATOR_TEMPLATE #undef BOOST_OPERATOR_TEMPLATE
#undef BOOST_OPERATOR_TEMPLATE4
#undef BOOST_OPERATOR_TEMPLATE3 #undef BOOST_OPERATOR_TEMPLATE3
#undef BOOST_OPERATOR_TEMPLATE2 #undef BOOST_OPERATOR_TEMPLATE2
#undef BOOST_OPERATOR_TEMPLATE1 #undef BOOST_OPERATOR_TEMPLATE1
#undef BOOST_IMPORT_TEMPLATE1 #undef BOOST_IMPORT_TEMPLATE1
#undef BOOST_IMPORT_TEMPLATE2 #undef BOOST_IMPORT_TEMPLATE2
#undef BOOST_IMPORT_TEMPLATE3 #undef BOOST_IMPORT_TEMPLATE3
#undef BOOST_IMPORT_TEMPLATE4
// The following 'operators' classes can only be used portably if the derived class // The following 'operators' classes can only be used portably if the derived class
// declares ALL of the required member operators. // declares ALL of the required member operators.
@@ -699,20 +878,18 @@ template <class T,
class P = V const *, class P = V const *,
class R = V const &> class R = V const &>
struct input_iterator_helper struct input_iterator_helper
: equality_comparable1<T : input_iteratable<T, P
, incrementable<T
, dereferenceable<T, P
, boost::iterator<std::input_iterator_tag, V, D, P, R , boost::iterator<std::input_iterator_tag, V, D, P, R
> > > > {}; > > {};
template<class Derived> template<class T>
struct output_iterator_helper struct output_iterator_helper
: boost::incrementable<Derived : output_iteratable<T
, boost::iterator<std::output_iterator_tag, void, void, void, void , boost::iterator<std::output_iterator_tag, void, void, void, void
> > > >
{ {
Derived& operator*() { return static_cast<Derived&>(*this); } T& operator*() { return static_cast<T&>(*this); }
Derived& operator++() { return static_cast<Derived&>(*this); } T& operator++() { return static_cast<T&>(*this); }
}; };
template <class T, template <class T,
@@ -721,11 +898,9 @@ template <class T,
class P = V*, class P = V*,
class R = V&> class R = V&>
struct forward_iterator_helper struct forward_iterator_helper
: equality_comparable1<T : forward_iteratable<T, P
, incrementable<T
, dereferenceable<T, P
, boost::iterator<std::forward_iterator_tag, V, D, P, R , boost::iterator<std::forward_iterator_tag, V, D, P, R
> > > > {}; > > {};
template <class T, template <class T,
class V, class V,
@@ -733,11 +908,9 @@ template <class T,
class P = V*, class P = V*,
class R = V&> class R = V&>
struct bidirectional_iterator_helper struct bidirectional_iterator_helper
: equality_comparable1<T : bidirectional_iteratable<T, P
, unit_steppable<T
, dereferenceable<T, P
, boost::iterator<std::bidirectional_iterator_tag, V, D, P, R , boost::iterator<std::bidirectional_iterator_tag, V, D, P, R
> > > > {}; > > {};
template <class T, template <class T,
class V, class V,
@@ -745,13 +918,9 @@ template <class T,
class P = V*, class P = V*,
class R = V&> class R = V&>
struct random_access_iterator_helper struct random_access_iterator_helper
: totally_ordered1<T : random_access_iteratable<T, P, D, R
, unit_steppable<T
, dereferenceable<T, P
, additive2<T, D
, indexable<T, D, R
, boost::iterator<std::random_access_iterator_tag, V, D, P, R , boost::iterator<std::random_access_iterator_tag, V, D, P, R
> > > > > > > >
{ {
friend D requires_difference_operator(const T& x, const T& y) { friend D requires_difference_operator(const T& x, const T& y) {
return x - y; return x - y;

163
include/boost/ref.hpp Normal file
View File

@@ -0,0 +1,163 @@
#ifndef BOOST_REF_HPP_INCLUDED
# define BOOST_REF_HPP_INCLUDED
# if _MSC_VER+0 >= 1020
# pragma once
# endif
# include <boost/config.hpp>
# include <boost/utility/addressof.hpp>
# include <boost/mpl/bool.hpp>
//
// ref.hpp - ref/cref, useful helper functions
//
// Copyright (C) 1999, 2000 Jaakko J<>rvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2001, 2002 Peter Dimov
// Copyright (C) 2002 David Abrahams
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// See http://www.boost.org/libs/bind/ref.html for documentation.
//
namespace boost
{
template<class T> class reference_wrapper
{
public:
typedef T type;
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
explicit reference_wrapper(T& t): t_(&t) {}
#else
explicit reference_wrapper(T& t): t_(addressof(t)) {}
#endif
operator T& () const { return *t_; }
T& get() const { return *t_; }
T* get_pointer() const { return t_; }
private:
T* t_;
};
# if defined(__BORLANDC__) && (__BORLANDC__ <= 0x570)
# define BOOST_REF_CONST
# else
# define BOOST_REF_CONST const
# endif
template<class T> inline reference_wrapper<T> BOOST_REF_CONST ref(T & t)
{
return reference_wrapper<T>(t);
}
template<class T> inline reference_wrapper<T const> BOOST_REF_CONST cref(T const & t)
{
return reference_wrapper<T const>(t);
}
# undef BOOST_REF_CONST
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<typename T>
class is_reference_wrapper
: public mpl::false_
{
};
template<typename T>
class is_reference_wrapper<reference_wrapper<T> >
: public mpl::true_
{
};
template<typename T>
class unwrap_reference
{
public:
typedef T type;
};
template<typename T>
class unwrap_reference<reference_wrapper<T> >
{
public:
typedef T type;
};
# else // no partial specialization
} // namespace boost
#include <boost/type.hpp>
namespace boost
{
namespace detail
{
typedef char (&yes_reference_wrapper_t)[1];
typedef char (&no_reference_wrapper_t)[2];
no_reference_wrapper_t is_reference_wrapper_test(...);
template<typename T>
yes_reference_wrapper_t is_reference_wrapper_test(type< reference_wrapper<T> >);
template<bool wrapped>
struct reference_unwrapper
{
template <class T>
struct apply
{
typedef T type;
};
};
template<>
struct reference_unwrapper<true>
{
template <class T>
struct apply
{
typedef typename T::type type;
};
};
}
template<typename T>
class is_reference_wrapper
{
public:
BOOST_STATIC_CONSTANT(
bool, value = (
sizeof(detail::is_reference_wrapper_test(type<T>()))
== sizeof(detail::yes_reference_wrapper_t)));
typedef ::boost::mpl::bool_<value> type;
};
template <typename T>
class unwrap_reference
: public detail::reference_unwrapper<
is_reference_wrapper<T>::value
>::template apply<T>
{};
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
} // namespace boost
#endif // #ifndef BOOST_REF_HPP_INCLUDED

View File

@@ -1,119 +1,21 @@
// boost utility.hpp header file -------------------------------------------// // Boost utility.hpp header file -------------------------------------------//
// (C) Copyright boost.org 1999. Permission to copy, use, modify, sell // (C) Copyright Boost.org 1999-2003. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright // and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without // 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 // express or implied warranty, and with no claim as to its suitability for
// any purpose. // any purpose.
// See http://www.boost.org for most recent version including documentation. // See http://www.boost.org/libs/utility for documentation.
// Classes appear in alphabetical order
// Revision History
// 21 May 01 checked_delete() and checked_array_delete() added (Beman Dawes,
// suggested by Dave Abrahams, generalizing idea from Vladimir Prus)
// 21 May 01 made next() and prior() inline (Beman Dawes)
// 26 Jan 00 protected noncopyable destructor added (Miki Jovanovic)
// 10 Dec 99 next() and prior() templates added (Dave Abrahams)
// 30 Aug 99 moved cast templates to cast.hpp (Beman Dawes)
// 3 Aug 99 cast templates added
// 20 Jul 99 name changed to utility.hpp
// 9 Jun 99 protected noncopyable default ctor
// 2 Jun 99 Initial Version. Class noncopyable only contents (Dave Abrahams)
#ifndef BOOST_UTILITY_HPP #ifndef BOOST_UTILITY_HPP
#define BOOST_UTILITY_HPP #define BOOST_UTILITY_HPP
#include <boost/config.hpp> // broken compiler workarounds #include <boost/utility/addressof.hpp>
#include <boost/static_assert.hpp> #include <boost/utility/base_from_member.hpp>
#include <cstddef> // for size_t #include <boost/checked_delete.hpp>
#include <utility> // for std::pair #include <boost/next_prior.hpp>
#include <boost/noncopyable.hpp>
namespace boost
{
// checked_delete() and checked_array_delete() -----------------------------//
// verify that types are complete for increased safety
template< typename T >
inline void checked_delete(T * x)
{
BOOST_STATIC_ASSERT( sizeof(T) != 0 ); // assert type complete at point
// of instantiation
delete x;
}
template< typename T >
inline void checked_array_delete(T * x)
{
BOOST_STATIC_ASSERT( sizeof(T) != 0 ); // assert type complete at point
// of instantiation
delete [] x;
}
// next() and prior() template functions -----------------------------------//
// Helper functions for classes like bidirectional iterators not supporting
// operator+ and operator-.
//
// Usage:
// const std::list<T>::iterator p = get_some_iterator();
// const std::list<T>::iterator prev = boost::prior(p);
// Contributed by Dave Abrahams
template <class T>
inline T next(T x) { return ++x; }
template <class T>
inline T prior(T x) { return --x; }
// class noncopyable -------------------------------------------------------//
// Private copy constructor and copy assignment ensure classes derived from
// class noncopyable cannot be copied.
// Contributed by Dave Abrahams
class noncopyable
{
protected:
noncopyable(){}
~noncopyable(){}
private: // emphasize the following members are private
noncopyable( const noncopyable& );
const noncopyable& operator=( const noncopyable& );
}; // noncopyable
// class tied -------------------------------------------------------//
// A helper for conveniently assigning the two values from a pair
// into separate variables. The idea for this comes from Jaakko J<>rvi's
// Binder/Lambda Library.
// Constributed by Jeremy Siek
template <class A, class B>
class tied {
public:
inline tied(A& a, B& b) : _a(a), _b(b) { }
template <class U, class V>
inline tied& operator=(const std::pair<U,V>& p) {
_a = p.first;
_b = p.second;
return *this;
}
protected:
A& _a;
B& _b;
};
template <class A, class B>
inline tied<A,B> tie(A& a, B& b) { return tied<A,B>(a, b); }
} // namespace boost
#endif // BOOST_UTILITY_HPP #endif // BOOST_UTILITY_HPP

View File

@@ -0,0 +1,43 @@
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
// Doug Gregor (gregod@cs.rpi.edu)
// Peter Dimov
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_UTILITY_ADDRESSOF_HPP
# define BOOST_UTILITY_ADDRESSOF_HPP
# include <boost/config.hpp>
# include <boost/detail/workaround.hpp>
# if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
# include <boost/type_traits/add_pointer.hpp>
# endif
namespace boost {
// Do not make addressof() inline. Breaks MSVC 7. (Peter Dimov)
// VC7 strips const from nested classes unless we add indirection here
# if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
template <typename T> typename add_pointer<T>::type
# else
template <typename T> T*
# endif
addressof(T& v)
{
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
}
}
#endif // BOOST_UTILITY_ADDRESSOF_HPP

View File

@@ -0,0 +1,59 @@
// boost utility/base_from_member.hpp header file --------------------------//
// (C) Copyright Daryle Walker 2001. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_UTILITY_BASE_FROM_MEMBER_HPP
#define BOOST_UTILITY_BASE_FROM_MEMBER_HPP
#include <boost/utility_fwd.hpp> // required for parameter defaults
namespace boost
{
// Base-from-member class template -----------------------------------------//
// Helper to initialize a base object so a derived class can use this
// object in the initialization of another base class. Used by
// Dietmar Kuehl from ideas by Ron Klatcho to solve the problem of a
// base class needing to be initialized by a member.
// Contributed by Daryle Walker
template < typename MemberType, int UniqueID >
class base_from_member
{
protected:
MemberType member;
explicit base_from_member()
: member()
{}
template< typename T1 >
explicit base_from_member( T1 x1 )
: member( x1 )
{}
template< typename T1, typename T2 >
base_from_member( T1 x1, T2 x2 )
: member( x1, x2 )
{}
template< typename T1, typename T2, typename T3 >
base_from_member( T1 x1, T2 x2, T3 x3 )
: member( x1, x2, x3 )
{}
}; // boost::base_from_member
} // namespace boost
#endif // BOOST_UTILITY_BASE_FROM_MEMBER_HPP

View File

@@ -0,0 +1,82 @@
// (C) 2002, Fernando Luis Cacciola Carballal.
//
// This material is provided "as is", with absolutely no warranty expressed
// or implied. Any use is at your own risk.
//
// Permission to use or copy this software for any purpose is hereby granted
// without fee, provided the above notices are retained on all copies.
// Permission to modify the code and to distribute modified code is granted,
// provided the above notices are retained, and a notice that the code was
// modified is included with the above copyright notice.
//
// 21 Ago 2002 (Created) Fernando Cacciola
//
#ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
#define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
#include "boost/detail/select_type.hpp"
#include "boost/type_traits/cv_traits.hpp"
namespace boost {
namespace vinit_detail {
template<class T>
class const_T_base
{
protected :
const_T_base() : x() {}
T x ;
} ;
template<class T>
struct non_const_T_base
{
protected :
non_const_T_base() : x() {}
mutable T x ;
} ;
template<class T>
struct select_base
{
typedef typename
detail::if_true< ::boost::is_const<T>::value >
::template then< const_T_base<T>, non_const_T_base<T> >::type type ;
} ;
} // namespace vinit_detail
template<class T>
class value_initialized : private vinit_detail::select_base<T>::type
{
public :
value_initialized() {}
operator T&() const { return this->x ; }
T& data() const { return this->x ; }
} ;
template<class T>
T const& get ( value_initialized<T> const& x )
{
return x.data() ;
}
template<class T>
T& get ( value_initialized<T>& x )
{
return x.data() ;
}
} // namespace boost
#endif

View File

@@ -0,0 +1,34 @@
// Boost utility_fwd.hpp header file ---------------------------------------//
// (C) Copyright boost.org 2001. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See http://www.boost.org/libs/utility for documentation.
#ifndef BOOST_UTILITY_FWD_HPP
#define BOOST_UTILITY_FWD_HPP
namespace boost
{
// From <boost/utility/base_from_member.hpp> -------------------------------//
template < typename MemberType, int UniqueID = 0 >
class base_from_member;
// From <boost/utility.hpp> ------------------------------------------------//
class noncopyable;
// Also has a few function templates
} // namespace boost
#endif // BOOST_UTILITY_FWD_HPP

34
index.html Normal file
View File

@@ -0,0 +1,34 @@
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Boost Utility Library</title>
</head>
<body bgcolor="#FFFFFF">
<h1><IMG SRC="../../c++boost.gif" WIDTH="276" HEIGHT="86" align="center">Boost
Utility Library</h1>
<p>The Boost Utility Library isn't really a single library at all. It is just a
collection for components too small to be called libraries in their own right.</p>
<p>But that doesn't mean there isn't useful stuff here. Take a look:</p>
<blockquote>
<p>
<a href="assert.html">assert</a><br>
<a href="base_from_member.html">base_from_member</a><br>
<a href="call_traits.htm">call_traits</a><br>
<a href="checked_delete.html">checked_delete</a><br>
<a href="compressed_pair.htm">compressed_pair</a><br>
<a href="iterator_adaptors.htm">iterator_adaptors</a><br>
<a href="operators.htm">operators</a><br>
<a href="tie.html">tie</a><br>
<a href="throw_exception.html">throw_exception</a><br>
<a href="utility.htm">utility</a><br>
<a href="value_init.htm">value_init</a></p>
</blockquote>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->09 January, 2003<!--webbot bot="Timestamp" endspan i-checksum="38582" --></p>
<p>&nbsp;</p>
</body>
</html>

View File

@@ -203,10 +203,10 @@ explicit indirect_iterator_generator::type(const BaseIterator&amp; it)
<blockquote> <blockquote>
<pre> <pre>
template &lt;class BaseIterator, template &lt;class BaseIterator,
class Value, class Pointer, class Reference, class Value, class Reference, class ConstReference,
class ConstPointer, class ConstReference&gt; class Category, class Pointer, class ConstPointer&gt;
class indirect_iterator_pair_generator struct indirect_iterator_pair_generator;
{ {
public: public:
typedef <tt><a href= typedef <tt><a href=
@@ -292,13 +292,6 @@ b,c,d,e,f,g,h,
in particular, the result type of its <tt>operator*()</tt>.<br> in particular, the result type of its <tt>operator*()</tt>.<br>
<b>Default:</b> <tt>Value&amp;</tt> <b>Default:</b> <tt>Value&amp;</tt>
<tr>
<td><tt>Pointer</tt>
<td>The <tt>pointer</tt> type of the resulting <tt>iterator</tt>, and
in particular, the result type of its <tt>operator-&gt;()</tt>.<br>
<b>Default:</b> <tt>Value*</tt>
<tr> <tr>
<td><tt>ConstReference</tt> <td><tt>ConstReference</tt>
@@ -307,6 +300,19 @@ b,c,d,e,f,g,h,
<tt>operator*()</tt>.<br> <tt>operator*()</tt>.<br>
<b>Default:</b> <tt>const Value&amp;</tt> <b>Default:</b> <tt>const Value&amp;</tt>
<tr>
<td><tt>Category</tt>
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseIterator&gt;::iterator_category</tt>
<tr>
<td><tt>Pointer</tt>
<td>The <tt>pointer</tt> type of the resulting <tt>iterator</tt>, and
in particular, the result type of its <tt>operator-&gt;()</tt>.<br>
<b>Default:</b> <tt>Value*</tt>
<tr> <tr>
<td><tt>ConstPointer</tt> <td><tt>ConstPointer</tt>
@@ -314,11 +320,6 @@ b,c,d,e,f,g,h,
and in particular, the result type of its <tt>operator-&gt;()</tt>.<br> and in particular, the result type of its <tt>operator-&gt;()</tt>.<br>
<b>Default:</b> <tt>const Value*</tt> <b>Default:</b> <tt>const Value*</tt>
<tr>
<td><tt>Category</tt>
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseIterator&gt;::iterator_category</tt>
</table> </table>
<h3>Concept Model</h3> <h3>Concept Model</h3>
@@ -422,7 +423,7 @@ a,b,c,d,e,f,g,
<hr> <hr>
<p>Revised <p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" --> <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->18 Sep 2001<!--webbot bot="Timestamp" endspan i-checksum="14941" -->
<p>&copy; Copyright Jeremy Siek and David Abrahams 2001. Permission to <p>&copy; Copyright Jeremy Siek and David Abrahams 2001. Permission to

View File

@@ -33,8 +33,8 @@ int main(int, char*[])
char mutable_characters[N]; char mutable_characters[N];
char* pointers_to_mutable_chars[N]; char* pointers_to_mutable_chars[N];
for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j)
pointers_to_mutable_chars[i] = &mutable_characters[i]; pointers_to_mutable_chars[j] = &mutable_characters[j];
PairGen::iterator mutable_indirect_first(pointers_to_mutable_chars), PairGen::iterator mutable_indirect_first(pointers_to_mutable_chars),
mutable_indirect_last(pointers_to_mutable_chars + N); mutable_indirect_last(pointers_to_mutable_chars + N);
@@ -51,10 +51,12 @@ int main(int, char*[])
// Example of using make_indirect_iterator() // Example of using make_indirect_iterator()
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
std::copy(boost::make_indirect_iterator(pointers_to_chars), std::copy(boost::make_indirect_iterator(pointers_to_chars),
boost::make_indirect_iterator(pointers_to_chars + N), boost::make_indirect_iterator(pointers_to_chars + N),
std::ostream_iterator<char>(std::cout, ",")); std::ostream_iterator<char>(std::cout, ","));
std::cout << std::endl; std::cout << std::endl;
#endif
return 0; return 0;
} }

View File

@@ -31,7 +31,7 @@ typedef std::set<storage::iterator> iterator_set;
void more_indirect_iterator_tests() void more_indirect_iterator_tests()
{ {
// For some reason all heck breaks loose in the compiler under these conditions. // For some reason all heck breaks loose in the compiler under these conditions.
#if !defined(BOOST_MSVC) || !defined(__STL_DEBUG) #if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 || !defined(__STL_DEBUG)
storage store(1000); storage store(1000);
std::generate(store.begin(), store.end(), rand); std::generate(store.begin(), store.end(), rand);
@@ -46,7 +46,7 @@ void more_indirect_iterator_tests()
typedef boost::indirect_iterator_pair_generator< typedef boost::indirect_iterator_pair_generator<
pointer_deque::iterator pointer_deque::iterator
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #ifdef BOOST_NO_STD_ITERATOR_TRAITS
, int , int
#endif #endif
> IndirectDeque; > IndirectDeque;
@@ -75,7 +75,7 @@ void more_indirect_iterator_tests()
typedef boost::indirect_iterator_generator< typedef boost::indirect_iterator_generator<
iterator_set::iterator iterator_set::iterator
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #ifdef BOOST_NO_STD_ITERATOR_TRAITS
, int , int
#endif #endif
>::type indirect_set_iterator; >::type indirect_set_iterator;
@@ -117,7 +117,7 @@ main()
ptr[k] = array + k; ptr[k] = array + k;
typedef boost::indirect_iterator_generator<dummyT** typedef boost::indirect_iterator_generator<dummyT**
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #ifdef BOOST_NO_STD_ITERATOR_TRAITS
, dummyT , dummyT
#endif #endif
>::type indirect_iterator; >::type indirect_iterator;
@@ -127,7 +127,7 @@ main()
indirect_iterator i(ptr); indirect_iterator i(ptr);
boost::random_access_iterator_test(i, N, array); boost::random_access_iterator_test(i, N, array);
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #ifndef BOOST_NO_STD_ITERATOR_TRAITS
boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array); boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
#endif #endif
@@ -139,7 +139,7 @@ main()
dummyT*const* const_ptr = ptr; dummyT*const* const_ptr = ptr;
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #ifndef BOOST_NO_STD_ITERATOR_TRAITS
boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array); boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array);
#endif #endif
boost::const_nonconst_iterator_test(i, ++j); boost::const_nonconst_iterator_test(i, ++j);

View File

@@ -4,7 +4,9 @@
// "as is" without express or implied warranty, and with no claim as // "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose. // to its suitability for any purpose.
// 8 Mar 2001 Jeremy Siek // 04 Nov 2001 Jeremy Siek
// Updated with respect to new named parameter interface.
// 08 Mar 2001 Jeremy Siek
// Initial checkin. // Initial checkin.
#include <boost/iterator_adaptors.hpp> #include <boost/iterator_adaptors.hpp>
@@ -26,9 +28,8 @@ main()
{ {
typedef boost::iterator_adaptor<my_iter, boost::default_iterator_policies, typedef boost::iterator_adaptor<my_iter, boost::default_iterator_policies,
boost::iterator_traits_generator boost::reference_is<dummyT>,
::reference<dummyT> boost::iterator_category_is<std::input_iterator_tag> > iter_type;
::iterator_category<std::input_iterator_tag> > iter_type;
BOOST_STATIC_ASSERT((boost::is_same<iter_type::iterator_category*, BOOST_STATIC_ASSERT((boost::is_same<iter_type::iterator_category*,
std::input_iterator_tag*>::value)); std::input_iterator_tag*>::value));
@@ -42,12 +43,11 @@ main()
{ {
typedef boost::iterator_adaptor<dummyT*, typedef boost::iterator_adaptor<dummyT*,
boost::default_iterator_policies, boost::default_iterator_policies,
boost::iterator_traits_generator boost::value_type_is<dummyT>,
::value_type<dummyT> boost::reference_is<const dummyT&>,
::reference<const dummyT&> boost::pointer_is<const dummyT*> ,
::pointer<const dummyT*> boost::iterator_category_is<std::forward_iterator_tag>,
::iterator_category<std::forward_iterator_tag> boost::difference_type_is<std::ptrdiff_t> > adaptor_type;
::difference_type<std::ptrdiff_t> > adaptor_type;
adaptor_type i(array); adaptor_type i(array);

View File

@@ -7,7 +7,7 @@
#include <functional> #include <functional>
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <boost/pending/iterator_adaptors.hpp> #include <boost/iterator_adaptors.hpp>
#include <boost/pending/integer_range.hpp> #include <boost/pending/integer_range.hpp>
int int
@@ -21,8 +21,7 @@ main(int, char*[])
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
typedef std::binder1st< std::multiplies<int> > Function; typedef std::binder1st< std::multiplies<int> > Function;
typedef boost::transform_iterator<Function, int*, typedef boost::transform_iterator_generator<Function, int*
boost::iterator<std::random_access_iterator_tag, int>
>::type doubling_iterator; >::type doubling_iterator;
doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)), doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)),

View File

@@ -9,6 +9,10 @@
// See http://www.boost.org for most recent version including documentation. // See http://www.boost.org for most recent version including documentation.
// Revision History // Revision History
// 30 Nov 01 Added permutation_iterator.(Toon Knapen)
// 19 Nov 01 Added generator_iterator. (Jens Maurer)
// 04 Nov 01 Updated with respect to change in named parameters.
// (Jeremy Siek)
// 08 Mar 01 Moved indirect and transform tests to separate files. // 08 Mar 01 Moved indirect and transform tests to separate files.
// (Jeremy Siek) // (Jeremy Siek)
// 19 Feb 01 Take adavantage of improved iterator_traits to do more tests // 19 Feb 01 Take adavantage of improved iterator_traits to do more tests
@@ -47,15 +51,20 @@
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
#include <numeric>
#include <boost/iterator_adaptors.hpp> #include <boost/iterator_adaptors.hpp>
#include <boost/generator_iterator.hpp>
#include <boost/pending/iterator_tests.hpp> #include <boost/pending/iterator_tests.hpp>
#include <boost/pending/integer_range.hpp> #include <boost/pending/integer_range.hpp>
#include <boost/concept_archetype.hpp> #include <boost/concept_archetype.hpp>
#include <boost/type_traits/same_traits.hpp>
#include <boost/permutation_iterator.hpp>
#include <stdlib.h> #include <stdlib.h>
#include <vector> #include <vector>
#include <deque> #include <deque>
#include <set> #include <set>
#include <list>
struct my_iterator_tag : public std::random_access_iterator_tag { }; struct my_iterator_tag : public std::random_access_iterator_tag { };
@@ -97,6 +106,18 @@ typedef std::deque<int> storage;
typedef std::deque<int*> pointer_deque; typedef std::deque<int*> pointer_deque;
typedef std::set<storage::iterator> iterator_set; typedef std::set<storage::iterator> iterator_set;
template <class T> struct foo;
void blah(int) { }
struct my_gen
{
typedef int result_type;
my_gen() : n(0) { }
int operator()() { return ++n; }
int n;
};
int int
main() main()
{ {
@@ -105,17 +126,62 @@ main()
const int N = sizeof(array)/sizeof(dummyT); const int N = sizeof(array)/sizeof(dummyT);
// sanity check, if this doesn't pass the test is buggy // sanity check, if this doesn't pass the test is buggy
boost::random_access_iterator_test(array,N,array); boost::random_access_iterator_test(array, N, array);
// Check that the policy concept checks and the default policy // Check that the policy concept checks and the default policy
// implementation match up. // implementation match up.
boost::function_requires< boost::function_requires<
boost::RandomAccessIteratorPoliciesConcept< boost::RandomAccessIteratorPoliciesConcept<
boost::default_iterator_policies, int*, boost::default_iterator_policies,
boost::iterator_adaptor<storage::iterator, boost::default_iterator_policies>,
boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t, boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t,
int*, int&> int*, int&>
> >(); > >();
// Test the named parameters
{
// Test computation of defaults
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
boost::value_type_is<int> > Iter1;
// don't use std::iterator_traits here to avoid VC++ problems
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, int>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, int&>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, int*>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::iterator_category, std::random_access_iterator_tag>::value));
}
{
// Test computation of default when the Value is const
typedef boost::iterator_adaptor<std::list<int>::iterator,
boost::default_iterator_policies,
boost::value_type_is<const int> > Iter1;
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, int>::value));
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) || BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
// We currently don't know how to workaround this bug.
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, int&>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, int*>::value));
#else
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, const int&>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, const int*>::value));
#endif
}
{
// Test with no defaults
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
boost::reference_is<long>,
boost::pointer_is<float*>,
boost::value_type_is<char>,
boost::iterator_category_is<std::input_iterator_tag>,
boost::difference_type_is<int>
> Iter1;
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, char>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, long>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, float*>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::difference_type, int>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::iterator_category, std::input_iterator_tag>::value));
}
// Test the iterator_adaptor // Test the iterator_adaptor
{ {
boost::iterator_adaptor<dummyT*, boost::default_iterator_policies, dummyT> i(array); boost::iterator_adaptor<dummyT*, boost::default_iterator_policies, dummyT> i(array);
@@ -159,7 +225,7 @@ main()
std::reverse(reversed, reversed + N); std::reverse(reversed, reversed + N);
typedef boost::reverse_iterator_generator<dummyT* typedef boost::reverse_iterator_generator<dummyT*
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
, dummyT , dummyT
#endif #endif
>::type reverse_iterator; >::type reverse_iterator;
@@ -167,13 +233,13 @@ main()
reverse_iterator i(reversed + N); reverse_iterator i(reversed + N);
boost::random_access_iterator_test(i, N, array); boost::random_access_iterator_test(i, N, array);
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array); boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
#endif #endif
typedef boost::reverse_iterator_generator<const dummyT* typedef boost::reverse_iterator_generator<const dummyT*
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
, const dummyT , dummyT, const dummyT&, const dummyT
#endif #endif
>::type const_reverse_iterator; >::type const_reverse_iterator;
@@ -182,7 +248,7 @@ main()
const dummyT* const_reversed = reversed; const dummyT* const_reversed = reversed;
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array); boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
#endif #endif
@@ -217,7 +283,11 @@ main()
// Many compilers' builtin deque iterators don't interoperate well, though // Many compilers' builtin deque iterators don't interoperate well, though
// STLport fixes that problem. // STLport fixes that problem.
#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && !defined(BOOST_MSVC) #if defined(__SGI_STL_PORT) \
|| (!BOOST_WORKAROUND(__GNUC__, < 3) \
&& !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) \
&& !BOOST_WORKAROUND(BOOST_MSVC, <= 1200))
boost::const_nonconst_iterator_test(i, ++j); boost::const_nonconst_iterator_test(i, ++j);
#endif #endif
} }
@@ -235,12 +305,12 @@ main()
typedef boost::detail::non_bidirectional_category<dummyT*>::type category; typedef boost::detail::non_bidirectional_category<dummyT*>::type category;
typedef boost::filter_iterator_generator<one_or_four, dummyT* typedef boost::filter_iterator_generator<one_or_four, dummyT*
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
, dummyT , dummyT
#endif #endif
>::type filter_iter; >::type filter_iter;
#if defined(__BORLANDC__) #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
// Borland is choking on accessing the policies_type explicitly // Borland is choking on accessing the policies_type explicitly
// from the filter_iter. // from the filter_iter.
boost::forward_iterator_test(make_filter_iterator(array, array+N, boost::forward_iterator_test(make_filter_iterator(array, array+N,
@@ -251,8 +321,7 @@ main()
boost::forward_iterator_test(i, dummyT(1), dummyT(4)); boost::forward_iterator_test(i, dummyT(1), dummyT(4));
#endif #endif
#if !defined(__BORLANDC__) #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
//
enum { is_forward = boost::is_same< enum { is_forward = boost::is_same<
filter_iter::iterator_category, filter_iter::iterator_category,
std::forward_iterator_tag>::value }; std::forward_iterator_tag>::value };
@@ -262,7 +331,7 @@ main()
// On compilers not supporting partial specialization, we can do more type // On compilers not supporting partial specialization, we can do more type
// deduction with deque iterators than with pointers... unless the library // deduction with deque iterators than with pointers... unless the library
// is broken ;-( // is broken ;-(
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT) #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && !__SGI_STL_PORT)
std::deque<dummyT> array2; std::deque<dummyT> array2;
std::copy(array+0, array+N, std::back_inserter(array2)); std::copy(array+0, array+N, std::back_inserter(array2));
boost::forward_iterator_test( boost::forward_iterator_test(
@@ -274,7 +343,7 @@ main()
dummyT(1), dummyT(4)); dummyT(1), dummyT(4));
#endif #endif
#if !defined(BOOST_MSVC) // This just freaks MSVC out completely #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // This just freaks MSVC6 out completely
boost::forward_iterator_test( boost::forward_iterator_test(
boost::make_filter_iterator<one_or_four>( boost::make_filter_iterator<one_or_four>(
boost::make_reverse_iterator(array2.end()), boost::make_reverse_iterator(array2.end()),
@@ -283,7 +352,7 @@ main()
dummyT(4), dummyT(1)); dummyT(4), dummyT(1));
#endif #endif
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
boost::forward_iterator_test( boost::forward_iterator_test(
boost::make_filter_iterator(array+0, array+N, one_or_four()), boost::make_filter_iterator(array+0, array+N, one_or_four()),
dummyT(1), dummyT(4)); dummyT(1), dummyT(4));
@@ -298,7 +367,8 @@ main()
// check operator-> with a forward iterator // check operator-> with a forward iterator
{ {
boost::forward_iterator_archetype<dummyT> forward_iter; boost::forward_iterator_archetype<dummyT> forward_iter;
#if defined(__BORLANDC__)
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>, typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
boost::default_iterator_policies, boost::default_iterator_policies,
dummyT, const dummyT&, const dummyT*, dummyT, const dummyT&, const dummyT*,
@@ -306,12 +376,12 @@ main()
#else #else
typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>, typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
boost::default_iterator_policies, boost::default_iterator_policies,
boost::iterator_traits_generator boost::reference_is<const dummyT&>,
::value_type<dummyT> boost::pointer_is<const dummyT*> ,
::reference<const dummyT&> boost::iterator_category_is<std::forward_iterator_tag>,
::pointer<const dummyT*> boost::value_type_is<dummyT>,
::iterator_category<std::forward_iterator_tag> boost::difference_type_is<std::ptrdiff_t>
::difference_type<std::ptrdiff_t> > adaptor_type; > adaptor_type;
#endif #endif
adaptor_type i(forward_iter); adaptor_type i(forward_iter);
int zero = 0; int zero = 0;
@@ -330,6 +400,55 @@ main()
if (zero) // don't do this, just make sure it compiles if (zero) // don't do this, just make sure it compiles
assert((*i).m_x == i->foo()); assert((*i).m_x == i->foo());
} }
{
// check generator_iterator
my_gen g1;
boost::generator_iterator_generator<my_gen>::type gen =
boost::make_generator_iterator(g1);
assert(*gen == 1);
++gen;
gen++;
assert(*gen == 3);
}
{
// check permutation_iterator
typedef std::deque< int > element_range_type;
typedef std::list< int > index_type;
static const int element_range_size = 10;
static const int index_size = 4;
element_range_type elements( element_range_size );
for(element_range_type::iterator el_it = elements.begin();
el_it != elements.end();
++el_it)
{
*el_it = std::distance( elements.begin(), el_it );
}
index_type indices( index_size );
for(index_type::iterator i_it = indices.begin();
i_it != indices.end();
++i_it)
{
*i_it = element_range_size - index_size
+ std::distance(indices.begin(), i_it );
}
std::reverse( indices.begin(), indices.end() );
typedef boost::permutation_iterator_generator< element_range_type::iterator, index_type::iterator >::type permutation_type;
permutation_type begin = boost::make_permutation_iterator( elements.begin(), indices.begin() );
permutation_type end = boost::make_permutation_iterator( elements.begin(), indices.end() );
int expected_outcome[] = { 9, 8, 7, 6 };
assert( std::equal( begin, end, expected_outcome ) );
}
std::cout << "test successful " << std::endl; std::cout << "test successful " << std::endl;
return 0; return 0;
} }

View File

@@ -26,6 +26,37 @@
"../../more/generic_programming.html#adaptors">adaptors</a> which apply "../../more/generic_programming.html#adaptors">adaptors</a> which apply
specific useful behaviors to arbitrary base iterators. specific useful behaviors to arbitrary base iterators.
<h2>Backward Compatibility Note</h2>
<p>The library's interface has changed since it was first released, breaking
backward compatibility:
<ol>
<li><a href="#policies">Policies classes</a> now operate on instances of the
whole <tt>iterator_adaptor</tt> object, rather than just operating on the
<tt>Base</tt> object. This change not only gives the policies class access
to both members of a pair of interacting iterators, but also eliminates the
need for the ugly <tt>type&lt;Reference&gt;</tt> and
<tt>type&lt;Difference&gt;</tt> parameters to various policy functions.
<li>The <a href="#named_template_parameters">Named Template Parameter</a>
interface has been made simpler, easier to use, and compatible with more
compilers.
</ol>
<h2>Other Documentation</h2>
<p><a href="iterator_adaptors.pdf">``Policy Adaptors and the Boost Iterator
Adaptor Library''</a> is a technical paper describing this library and the
powerful design pattern on which it is based. It was presented at the <a
href="http://www.oonumerics.org/tmpw01">C++ Template Workshop</a> at OOPSLA
2001; the slides from the talk are available <a
href="iterator_adaptors.ppt">here</a>. Please note that while the slides
incorporate the minor interface changes described in the previous section,
the paper does not.
<h2>Table of Contents</h2> <h2>Table of Contents</h2>
<ul> <ul>
@@ -61,6 +92,8 @@
<li><a href="#declaration_synopsis">Declaration Synopsis</a> <li><a href="#declaration_synopsis">Declaration Synopsis</a>
<li><a href="#portability">Portability</a>
<li><a href="#notes">Notes</a> <li><a href="#notes">Notes</a>
</ul> </ul>
@@ -91,9 +124,15 @@
"../../boost/function_output_iterator.hpp">boost/function_output_iterator.hpp</a></tt><br> "../../boost/function_output_iterator.hpp">boost/function_output_iterator.hpp</a></tt><br>
<a href="function_output_iterator.htm">Function Output Iterator Adaptor</a> <a href="function_output_iterator.htm">Function Output Iterator Adaptor</a>
<li>Header <tt><a href="../../boost/generator_iterator.hpp">boost/generator_iterator.hpp</a></tt><br>
<a href="generator_iterator.htm">Generator Iterator Adaptor</a>
<li>Header <tt><a href="../../boost/permutation_iterator.hpp">boost/permutation_iterator.hpp</a></tt><br>
<a href="permutation_iterator.htm">Permutation Iterator Adaptor</a>
<li>Header <tt><a href="../../boost/shared_container_iterator.hpp">boost/shared_container_iterator.hpp</a></tt><br>
<a href="shared_container_iterator.html">Shared_Container Iterator Adaptor</a>
</ul> </ul>
<p><b><a href="file:///c:/boost/site/people/dave_abrahams.htm">Dave <p><b><a href="../../people/dave_abrahams.htm">Dave
Abrahams</a></b> started the library, applying <a href= Abrahams</a></b> started the library, applying <a href=
"../../more/generic_programming.html#policy">policy class</a> technique and "../../more/generic_programming.html#policy">policy class</a> technique and
handling const/non-const iterator interactions. He also contributed the handling const/non-const iterator interactions. He also contributed the
@@ -102,7 +141,7 @@
<tt><a href="counting_iterator.htm">counting_iterator_generator</a></tt> to <tt><a href="counting_iterator.htm">counting_iterator_generator</a></tt> to
cover all incrementable types. He edited most of the documentation, cover all incrementable types. He edited most of the documentation,
sometimes heavily.<br> sometimes heavily.<br>
<b><a href="file:///c:/boost/site/people/jeremy_siek.htm">Jeremy <b><a href="../../people/jeremy_siek.htm">Jeremy
Siek</a></b> contributed the <a href="transform_iterator.htm">transform Siek</a></b> contributed the <a href="transform_iterator.htm">transform
iterator</a> adaptor, the integer-only version of <tt><a href= iterator</a> adaptor, the integer-only version of <tt><a href=
"counting_iterator.htm">counting_iterator_generator</a></tt>, "counting_iterator.htm">counting_iterator_generator</a></tt>,
@@ -114,7 +153,14 @@
"filter_iterator.htm">filter_</a></tt> iterator generators and made some "filter_iterator.htm">filter_</a></tt> iterator generators and made some
simplifications to the main <tt><a href= simplifications to the main <tt><a href=
"#iterator_adaptor">iterator_adaptor</a></tt> template.<br> "#iterator_adaptor">iterator_adaptor</a></tt> template.<br>
<b><a href="../../people/jens_maurer.htm">Jens Maurer</a></b>
contributed the <a href="generator_iterator.htm">generator iterator</a>
adaptor.<br>
Toon Knapen contributed the <a href="permutation_iterator.htm">permutation
iterator</a> adaptor.<br>
<b><a href="../../people/ronald_garcia.htm">Ronald Garcia</a></b>
contributed the <a href="shared_container_iterator.html">shared container iterator</a>
adaptor.<br>
<h2><a name="iterator_adaptor">Class template</a> <h2><a name="iterator_adaptor">Class template</a>
<tt>iterator_adaptor</tt></h2> <tt>iterator_adaptor</tt></h2>
@@ -131,11 +177,11 @@
<p><tt>iterator_adaptor</tt> is declared like this: <p><tt>iterator_adaptor</tt> is declared like this:
<pre> <pre>
template &lt;class Base, class Policies, template &lt;class Base, class Policies,
class ValueOrNamedParams = typename std::iterator_traits&lt;Base&gt;::value_type, class ValueOrNamedParam = typename std::iterator_traits&lt;Base&gt;::value_type,
class ReferenceOrNamedParams = <i>...(see below)</i>, class ReferenceOrNamedParam = <i>...(see below)</i>,
class PointerOrNamedParams = <i>...(see below)</i>, class PointerOrNamedParam = <i>...(see below)</i>,
class CategoryOrNamedParams = typename std::iterator_traits&lt;Base&gt;::iterator_category, class CategoryOrNamedParam = typename std::iterator_traits&lt;Base&gt;::iterator_category,
class DistanceOrNamedParams = typename std::iterator_traits&lt;Base&gt;::difference_type&gt; class DistanceOrNamedParam = typename std::iterator_traits&lt;Base&gt;::difference_type&gt;
struct iterator_adaptor; struct iterator_adaptor;
</pre> </pre>
@@ -143,7 +189,7 @@ struct iterator_adaptor;
<p>Although <tt>iterator_adaptor</tt> takes seven template parameters, <p>Although <tt>iterator_adaptor</tt> takes seven template parameters,
defaults have been carefully chosen to minimize the number of parameters defaults have been carefully chosen to minimize the number of parameters
you must supply in most cases, especially if <tt>BaseType</tt> is an you must supply in most cases, especially if <tt>Base</tt> is an
iterator. iterator.
<table border="1" summary="iterator_adaptor template parameters"> <table border="1" summary="iterator_adaptor template parameters">
@@ -152,17 +198,26 @@ struct iterator_adaptor;
<th>Description <th>Description
<tr> <th>Requirements
<td><tt>BaseType</tt>
<td>The type being wrapped. <tr>
<td><tt>Base</tt>
<td>The data type on which the resulting iterator is based. Do
not be misled by the name &quot;Base&quot;: this is not a base
class.
<td>
<a href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>,
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default&nbsp;Constructible</a>
<tr> <tr>
<td><tt>Policies</tt> <td><tt>Policies</tt>
<td>A <a href="../../more/generic_programming.html#policy">policy <td>A <a href="../../more/generic_programming.html#policy">policy
class</a> that supplies core functionality to the resulting iterator. A class</a> that supplies core functionality to the resulting iterator.
detailed description can be found <a href="#policies">below</a>.
<td>See table <a href="#policies">below</a>.
<tr> <tr>
<td><tt>Value</tt> <td><tt>Value</tt>
@@ -173,7 +228,7 @@ struct iterator_adaptor;
"#1">[1]</a>. If the <tt>value_type</tt> you wish to use is an abstract "#1">[1]</a>. If the <tt>value_type</tt> you wish to use is an abstract
base class see note <a href="#5">[5]</a>.<br> base class see note <a href="#5">[5]</a>.<br>
<b>Default:</b> <b>Default:</b>
<tt>std::iterator_traits&lt;BaseType&gt;::value_type</tt> <a href= <tt>std::iterator_traits&lt;Base&gt;::value_type</tt> <a href=
"#2">[2]</a> "#2">[2]</a>
<tr> <tr>
@@ -183,36 +238,57 @@ struct iterator_adaptor;
particular, the result type of <tt>operator*()</tt>.<br> particular, the result type of <tt>operator*()</tt>.<br>
<b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&amp;</tt> is <b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&amp;</tt> is
used. Otherwise used. Otherwise
<tt>std::iterator_traits&lt;BaseType&gt;::reference</tt> is used. <tt>std::iterator_traits&lt;Base&gt;::reference</tt> is used. <a href="#7">[7]</a>
<td><a
href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterators</a>,
<a
href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterators</a>,
and <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterators</a>
require that Reference is a true reference type (e.g. not a proxy).
<tr> <tr>
<td><tt>Pointer</tt> <td><tt>Pointer</tt>
<td>The <tt>pointer</tt> type of the resulting iterator, and in <td>The <tt>pointer</tt> type of the resulting iterator, and in
particular, the result type of <tt>operator-&gt;()</tt>.<br> particular, the result type of <tt>operator-&gt;()</tt>.<br>
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>, <b>Default:</b> If <tt>Value</tt> was not supplied, <tt>std::iterator_traits&lt;Base&gt;::pointer</tt>. <a
otherwise <tt>std::iterator_traits&lt;BaseType&gt;::pointer</tt>. href="#7">[7]</a> Otherwise, if <code>iterator_category</code> is
<code>input_iterator</code>, then a class yielding
<tt>Value*</tt> when <code>operator-&gt;()</code> is applied.
Otherwise, <tt>Value*</tt>.
<td><code>value_type*</code> or a
class which yields <code>value_type*</code> when
<code>operator-&gt;()</code> is applied.
<tr> <tr>
<td><tt>Category</tt> <td><tt>Category</tt>
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br> <td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
<b>Default:</b> <b>Default:</b>
<tt>std::iterator_traits&lt;BaseType&gt;::iterator_category</tt> <tt>std::iterator_traits&lt;Base&gt;::iterator_category</tt>
<td>One of
<code>std::input_iterator_tag</code>,
<code>std::output_iterator_tag</code>,
<code>std::forward_iterator_tag</code>,
<code>std::bidirectional_iterator_tag</code>, or
<code>std::random_access_iterator_tag</code>.
<tr> <tr>
<td><tt>Distance</tt> <td><tt>Distance</tt>
<td>The <tt>difference_type</tt> for the resulting iterator.<br> <td>The <tt>difference_type</tt> for the resulting iterator.<br>
<b>Default:</b> <b>Default:</b>
<tt>std::iterator_traits&lt;BaseType&gt;::difference_type</tt> <tt>std::iterator_traits&lt;Base&gt;::difference_type</tt>
<td>A signed integral type
<tr> <tr>
<td><tt>NamedParams</tt> <td><tt>NamedParam</tt>
<td>A list of named template parameters generated using the <td>A named template parameter (see below).
<a href="#iterator_traits_generator">
<tt>iterator_traits_generator</tt></a> class (see below).
</table> </table>
<h3><a name="named_template_parameters">Named Template Parameters</a></h3> <h3><a name="named_template_parameters">Named Template Parameters</a></h3>
@@ -223,59 +299,32 @@ struct iterator_adaptor;
template parameter, but use the defaults for the third through template parameter, but use the defaults for the third through
fifth. As a solution to these problems we provide a mechanism for fifth. As a solution to these problems we provide a mechanism for
naming the last five template parameters, and providing them in naming the last five template parameters, and providing them in
any order through the <tt>iterator_traits_generator</tt> class. any order through a set of named template parameters. The following
classes are provided for specifying the parameters. Any of these
classes can be used for any of the last five template parameters
of <tt>iterator_adaptor</tt>.
<blockquote> <blockquote>
<pre> <pre>
<a name="iterator_traits_generator">class iterator_traits_generator</a> template &lt;class Value&gt; struct value_type_is;
{ template &lt;class Reference&gt; struct reference_is;
public: template &lt;class Pointer&gt; struct pointer_is;
template &lt;class Value&gt; template &lt;class Distance&gt; struct difference_type_is;
struct value_type : public <i>recursive magic</i> { }; template &lt;class Category&gt; struct iterator_category_is;
template &lt;class Reference&gt;
struct reference : public <i>recursive magic</i> { };
template &lt;class Pointer&gt;
struct pointer : public <i>recursive magic</i> { };
template &lt;class Distance&gt;
struct difference_type : public <i>recursive magic</i> { };
template &lt;class Category&gt;
struct iterator_category : public <i>recursive magic</i> { };
};
</pre> </pre>
</blockquote> </blockquote>
The <tt>iterator_traits_generator</tt> is used to create a list of For example, the following adapts <tt>foo_iterator</tt> to create
of template arguments. For example, suppose you want to set the an <a href=
<tt>Reference</tt> and <tt>Category</tt> parameters, and use the "http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>
defaults for the rest. Then you can use the traits generator as with <tt>reference</tt> type <tt>foo</tt>, and whose other traits
follows: are determined according to the defaults described <a
href="#template_parameters">above</a>.
<blockquote> <blockquote>
<pre> <pre>
iterator_traits_generator::reference&lt;foo&gt;::category&lt;std::input_iterator_tag&gt; typedef iterator_adaptor&lt;foo_iterator, foo_policies,
</pre> reference_is&lt;foo&gt;, iterator_category_is&lt;std::input_iterator_tag&gt;
</blockquote> &gt; MyIterator;
This generated type can then be passed into the <tt>iterator_adaptor</tt>
class to replace any of the last five parameters. If you use the traits
generator in the <i>i</i>th parameter position, then the parameters <i>i</i>
through 7 will use the types specified in the generator. For example, the
following adapts <tt>foo_iterator</tt> to create an <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a> with
<tt>reference</tt> type <tt>foo</tt>, and whose other traits are determined
according to the defaults described <a href="#template_parameters">above</a>.
<blockquote>
<pre>
iterator_adaptor&lt;foo_iterator, foo_policies,
iterator_traits_generator
::reference&lt;foo&gt;
::iterator_category&lt;std::input_iterator_tag&gt;
&gt;
</pre> </pre>
</blockquote> </blockquote>
@@ -297,12 +346,16 @@ iterator_adaptor&lt;foo_iterator, foo_policies,
<table border="1" summary="iterator_adaptor Policies operations"> <table border="1" summary="iterator_adaptor Policies operations">
<caption> <caption>
<b>Core Iterator Operations</b><br> <b>Policies Class Requirements</b><br>
<tt>T</tt>: adapted iterator type; <tt>p</tt>: object of type T; <tt>n</tt>: <tt>T::size_type</tt>; <tt>x</tt>: <tt>T::difference_type</tt>; <tt>p1</tt>, <tt>p2</tt>: iterators <tt><b>T</b></tt>: adapted iterator type; <tt><b>x, y</b></tt>: objects of type
T; <tt><b>p</b></tt>: <tt>T::policies_type</tt>
<tt><b>d</b></tt>:
<tt>T::difference_type</tt>; <tt><b>i1</b></tt>, <tt><b>i2</b></tt>:
<tt>T::base_type</tt>
</caption> </caption>
<tr> <tr>
<th>Operation <th>Expression
<th>Effects <th>Effects
@@ -311,7 +364,7 @@ iterator_adaptor&lt;foo_iterator, foo_policies,
<th>Required for Iterator Categories <th>Required for Iterator Categories
<tr> <tr>
<td><tt>initialize</tt> <td nowrap><tt>p.initialize(b)</tt>
<td>optionally modify base iterator during iterator construction <td>optionally modify base iterator during iterator construction
@@ -323,79 +376,66 @@ iterator_adaptor&lt;foo_iterator, foo_policies,
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward</a>/ <a "http://www.sgi.com/tech/stl/ForwardIterator.html">Forward</a>/ <a
href= href=
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/ "http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random&nbsp;Access</a>
Access</a>
<tr> <tr>
<td><tt>dereference</tt> <td nowrap><tt>p.dereference(x)</tt>
<td>returns an element of the iterator's <tt>reference</tt> type <td>returns an element of the iterator's <tt>reference</tt> type
<td><tt>*p</tt>, <tt>p[n]</tt> <td><tt>*x</tt>, <tt>x[d]</tt>
<tr> <tr>
<td><tt>equal</tt> <td nowrap><tt>p.equal(x, y)</tt>
<td>tests the iterator for equality <td>tests the iterator for equality
<td><tt>p1&nbsp;==&nbsp;p2</tt>, <tt>p1&nbsp;!=&nbsp;p2</tt> <td><tt>i1&nbsp;==&nbsp;i2</tt>, <tt>i1&nbsp;!=&nbsp;i2</tt>
<tr> <tr>
<td><tt>increment</tt> <td nowrap><tt>p.increment(x)</tt>
<td>increments the iterator <td>increments the iterator
<td><tt>++p</tt>, <tt>p++</tt> <td><tt>++x</tt>, <tt>x++</tt>
<tr> <tr>
<td><tt>decrement</tt> <td nowrap><tt>p.decrement(x)</tt>
<td>decrements the iterator <td>decrements the iterator
<td><tt>--p</tt>, <tt>p--</tt> <td><tt>--x</tt>, <tt>x--</tt>
<td><a href= <td><a href=
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/ "http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random&nbsp;Access</a>
Access</a>
<tr> <tr>
<td><tt>less</tt> <td nowrap><tt>p.distance(x, y)</tt>
<td>imposes a <a href= <td>measures the distance between iterators
"http://www.sgi.com/tech/stl/StrictWeakOrdering.html">Strict Weak
Ordering</a> relation on iterators
<td> <td><tt>y&nbsp;-&nbsp;x</tt>, <tt>x&nbsp;&lt;&nbsp;y</tt>
<tt>p1&nbsp;&lt;&nbsp;p2</tt>,
<tt>p1&nbsp;&lt;=&nbsp;p2</tt>,
<tt>p1&nbsp;&gt;&nbsp;p2</tt>,
<tt>p1&nbsp;&gt;=&nbsp;p2</tt>
<td rowspan="3"><a href= <td rowspan="2"><a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access</a> Access</a>
<tr> <tr>
<td><tt>distance</tt> <td nowrap><tt>p.advance(x, n)</tt>
<td>measures the distance between iterators
<td><tt>p1 - p2</tt>
<tr>
<td><tt>advance</tt>
<td>adds an integer offset to iterators <td>adds an integer offset to iterators
<td> <td>
<tt>p&nbsp;+&nbsp;x</tt>, <tt>x&nbsp;+&nbsp;d</tt>,
<tt>x&nbsp;+&nbsp;p</tt>, <tt>d&nbsp;+&nbsp;x</tt>,
<tt>p&nbsp;+=&nbsp;x</tt>,
<tt>p&nbsp;-&nbsp;x</tt>, <br>
<tt>p&nbsp;-=&nbsp;x</tt> <tt>x&nbsp;+=&nbsp;d</tt>,
<tt>x&nbsp;-&nbsp;d</tt>,<br>
<tt>x&nbsp;-=&nbsp;d</tt>
</table> </table>
@@ -414,40 +454,40 @@ iterator_adaptor&lt;foo_iterator, foo_policies,
<pre> <pre>
struct <a name="default_iterator_policies">default_iterator_policies</a> struct <a name="default_iterator_policies">default_iterator_policies</a>
{ {
template &lt;class BaseType&gt; // Some of these members were defined static, but Borland got confused
void initialize(BaseType&amp;) // and thought they were non-const. Also, Sun C++ does not like static
// function templates.
template &lt;class Base&gt;
void initialize(Base&amp;)
{ } { }
template &lt;class Reference, class BaseType&gt; template &lt;class IteratorAdaptor&gt;
Reference dereference(type&lt;Reference&gt;, const BaseType&amp; x) const typename IteratorAdaptor::reference dereference(const IteratorAdaptor&amp; x) const
{ return *x; } { return *x.base(); }
template &lt;class BaseType&gt; template &lt;class IteratorAdaptor&gt;
static void increment(BaseType&amp; x) void increment(IteratorAdaptor&amp; x)
{ ++x; } { ++x.base(); }
template &lt;class BaseType1, class BaseType2&gt; template &lt;class IteratorAdaptor&gt;
bool equal(BaseType1&amp; x, BaseType2&amp; y) const void decrement(IteratorAdaptor&amp; x)
{ return x == y; } { --x.base(); }
template &lt;class BaseType&gt; template &lt;class IteratorAdaptor, class DifferenceType&gt;
static void decrement(BaseType&amp; x) void advance(IteratorAdaptor&amp; x, DifferenceType n)
{ --x; } { x.base() += n; }
template &lt;class BaseType, class DifferenceType&gt; template &lt;class IteratorAdaptor1, class IteratorAdaptor2&gt;
static void advance(BaseType&amp; x, DifferenceType n) typename IteratorAdaptor1::difference_type
{ x += n; } distance(const IteratorAdaptor1&amp; x, const IteratorAdaptor2&amp; y) const
{ return y.base() - x.base(); }
template &lt;class Difference, class BaseType1, class BaseType2&gt; template &lt;class IteratorAdaptor1, class IteratorAdaptor2&gt;
Difference distance(type&lt;Difference&gt;, BaseType1&amp; x, BaseType2&amp; y) const bool equal(const IteratorAdaptor1&amp; x, const IteratorAdaptor2&amp; y) const
{ return y - x; } { return x.base() == y.base(); }
template &lt;class BaseType1, class BaseType2&gt;
bool less(BaseType1&amp; x, BaseType2&amp; y) const
{ return x &lt; y; }
}; };
</pre> </pre></blockquote>
</blockquote>
<p>Template member functions are used throughout <p>Template member functions are used throughout
<tt>default_iterator_policies</tt> so that it can be employed with a wide <tt>default_iterator_policies</tt> so that it can be employed with a wide
@@ -480,15 +520,30 @@ struct <a name="default_iterator_policies">default_iterator_policies</a>
iterator_adaptor(const iterator_adaptor(const
iterator_adaptor&lt;B,Policies,V,R,P,Category,Distance&gt;&amp;)</tt> iterator_adaptor&lt;B,Policies,V,R,P,Category,Distance&gt;&amp;)</tt>
<br><br> <br><br>
This constructor allows for conversion from non-<tt>const</tt> to This constructor allows for conversion from mutable to
constant adapted iterators. See <a href= constant adapted iterators. See <a href=
"#iterator_interactions">below</a> for more details.<br> "#iterator_interactions">below</a> for more details.<br>
Requires: <tt>B</tt> is convertible to <tt>Base</tt>. Requires: <tt>B</tt> is convertible to <tt>Base</tt>.
<tr> <tr>
<td><tt>base_type base() const;</tt> <td><tt>const base_type& base() const;</tt>
<br><br> <br><br>
Return a copy of the base object. Return a const reference to the base object.
<tr> <td><tt>base_type& base();</tt>
<br><br>
Return a reference to the base object. This is to give the policies object
access to the base object. See <a href="#policies">above</a> for policies
iterator_adaptor interaction.<a href="#8">[8]</a>
<tr>
<td><tt>const Policies& policies() const;</tt>
<br><br>
Return a const reference to the policies object.
<tr> <td><tt>Policies& policies();</tt>
<br><br>
Return a reference to the policies object.
</table> </table>
<h3><a name="example">Example</a></h3> <h3><a name="example">Example</a></h3>
@@ -506,40 +561,37 @@ struct <a name="default_iterator_policies">default_iterator_policies</a>
argument and that we'll need to be able to deduce the <tt>result_type</tt> argument and that we'll need to be able to deduce the <tt>result_type</tt>
of the function so we can use it for the adapted iterator's of the function so we can use it for the adapted iterator's
<tt>value_type</tt>. <a href= <tt>value_type</tt>. <a href=
"http://www.sgi.com/Technology/STL/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a> "http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>
is the <a href="../../more/generic_programming.html#concept">Concept</a> is the <a href="../../more/generic_programming.html#concept">Concept</a>
that fulfills those requirements. that fulfills those requirements.
<p>To implement a transform iterator we will only change one of the base <p>To implement a transform iterator we will only change one of the base
iterator's behaviors, so the <tt>transform_iterator_policies</tt> class can iterator's behaviors, so the <tt>transform_iterator_policies</tt> class can
inherit the rest from <tt>default_iterator_policies</tt>. We will define inherit the rest from <tt>default_iterator_policies</tt>. We will define the
the <tt>dereference()</tt> member function, which is used to implement <tt>dereference()</tt> member function, which is used to implement
<tt>operator*()</tt> of the adapted iterator. The implementation will <tt>operator*()</tt> of the adapted iterator. The implementation will
dereference the base iterator and apply the function object. The dereference the base iterator and apply the function object. The complete
<tt>type&lt;Reference&gt;</tt> parameter is used to convey the appropriate code for <tt>transform_iterator_policies</tt> is:<br>
return type. The complete code for <tt>transform_iterator_policies</tt>
is:<br>
<br> <br>
<blockquote><pre>
<blockquote> template &lt;class AdaptableUnaryFunction&gt;
<pre> struct transform_iterator_policies : public default_iterator_policies
template &lt;class AdaptableUnaryFunction&gt; {
struct transform_iterator_policies : public default_iterator_policies
{
transform_iterator_policies() { } transform_iterator_policies() { }
transform_iterator_policies(const AdaptableUnaryFunction&amp; f) transform_iterator_policies(const AdaptableUnaryFunction&amp; f)
: m_f(f) { } : m_f(f) { }
template &lt;class Reference, class BaseIterator&gt; template &lt;class IteratorAdaptor&gt;
Reference dereference(type&lt;Reference&gt;, const BaseIterator&amp; i) const typename IteratorAdaptor::reference
{ return m_f(*i); } dereference(const IteratorAdaptor&amp; iter) const
{ return m_f(*iter.base()); }
AdaptableUnaryFunction m_f; AdaptableUnaryFunction m_f;
}; };
</pre>
</blockquote> </pre></blockquote>
<p>The next step is to use the <tt>iterator_adaptor</tt> template to <p>The next step is to use the <tt>iterator_adaptor</tt> template to
construct the transform iterator type. The nicest way to package the construct the transform iterator type. The nicest way to package the
@@ -575,7 +627,7 @@ public:
<p>As a finishing touch, we will create an <a href= <p>As a finishing touch, we will create an <a href=
"../../more/generic_programming.html#object_generator">object generator</a> "../../more/generic_programming.html#object_generator">object generator</a>
for the transform iterator. This is a function that makes it more for the transform iterator. Our object generator makes it more
convenient to create a transform iterator.<br> convenient to create a transform iterator.<br>
<br> <br>
@@ -611,10 +663,10 @@ int main(int, char*[])
{ {
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
const int N = sizeof(x)/sizeof(int); const int N = sizeof(x)/sizeof(int);
std::cout &lt;&lt; "multiplying the array by 2:" &lt;&lt; std::endl; std::cout &lt;&lt; &quot;multiplying the array by 2:&quot; &lt;&lt; std::endl;
std::copy(boost::make_transform_iterator(x, std::bind1st(std::multiplies&lt;int&gt;(), 2)), std::copy(boost::make_transform_iterator(x, std::bind1st(std::multiplies&lt;int&gt;(), 2)),
boost::make_transform_iterator(x + N, std::bind1st(std::multiplies&lt;int&gt;(), 2)), boost::make_transform_iterator(x + N, std::bind1st(std::multiplies&lt;int&gt;(), 2)),
std::ostream_iterator&lt;int&gt;(std::cout, " ")); std::ostream_iterator&lt;int&gt;(std::cout, &quot; &quot;));
std::cout &lt;&lt; std::endl; std::cout &lt;&lt; std::endl;
return 0; return 0;
} }
@@ -658,7 +710,7 @@ int main(int, char*[])
<li>Interoperable iterators can be freely mixed in comparison expressions <li>Interoperable iterators can be freely mixed in comparison expressions
so long as the <tt>Policies</tt> class has <tt>equal</tt> (and, for so long as the <tt>Policies</tt> class has <tt>equal</tt> (and, for
random access iterators, <tt>less</tt>) members that can accept both random access iterators, <tt>distance</tt>) members that can accept both
<tt>Base</tt> types in either order. <tt>Base</tt> types in either order.
<li>Interoperable iterators can be freely mixed in subtraction <li>Interoperable iterators can be freely mixed in subtraction
@@ -712,11 +764,12 @@ they share the same <tt>Policies</tt> and since <tt>Category</tt> and
the projection <tt>const_iterator</tt>. the projection <tt>const_iterator</tt>.
<li> Since <tt>projection_iterator_policies</tt> implements only the <li> Since <tt>projection_iterator_policies</tt> implements only the
<tt>dereference</tt> operation, and inherits all other behaviors from <tt><a <tt>dereference</tt> operation, and inherits all other behaviors from
href="#default_iterator_policies">default_iterator_policies</a></tt>, which has <tt><a
fully-templatized <tt>equal</tt>, <tt>less</tt>, and <tt>distance</tt> href="#default_iterator_policies">default_iterator_policies</a></tt>,
operations, the <tt>iterator</tt> and <tt>const_iterator</tt> can be freely which has fully-templatized <tt>equal</tt> and <tt>distance</tt>
mixed in comparison and subtraction expressions. operations, the <tt>iterator</tt> and <tt>const_iterator</tt> can be
freely mixed in comparison and subtraction expressions.
</ul> </ul>
@@ -724,7 +777,7 @@ mixed in comparison and subtraction expressions.
<p>There is an unlimited number of ways the <tt>iterator_adaptors</tt> <p>There is an unlimited number of ways the <tt>iterator_adaptors</tt>
class can be used to create iterators. One interesting exercise would be to class can be used to create iterators. One interesting exercise would be to
re-implement the iterators of <tt>std::list</tt> and <tt>std::slist</tt> re-implement the iterators of <tt>std::list</tt> and <tt>slist</tt>
using <tt>iterator_adaptors</tt>, where the adapted <tt>Iterator</tt> types using <tt>iterator_adaptors</tt>, where the adapted <tt>Iterator</tt> types
would be node pointers. would be node pointers.
@@ -761,16 +814,17 @@ struct iterator_adaptor
iterator_adaptor(); iterator_adaptor();
explicit iterator_adaptor(const Base&amp;, const Policies&amp; = Policies()); explicit iterator_adaptor(const Base&amp;, const Policies&amp; = Policies());
base_type base() const; base_type& base();
const base_type& base() const;
template &lt;class B, class V, class R, class P&gt; template &lt;class B, class V, class R, class P&gt;
iterator_adaptor( iterator_adaptor(
const iterator_adaptor&lt;B,Policies,V,R,P,Category,Distance&gt;&amp;); const iterator_adaptor&lt;B,Policies,V,R,P,Category,Distance&gt;&amp;);
reference operator*() const; reference operator*() const; <a href="#6">[6]</a>
<i>operator_arrow_result_type</i> operator-&gt;() const; <a href= <i>operator_arrow_result_type</i> operator-&gt;() const; <a href=
"#3">[3]</a> "#3">[3]</a>
<i>value_type</i> operator[](difference_type n) const; <a href="#3">[4]</a> <i>value_type</i> operator[](difference_type n) const; <a href="#3">[4]</a>, <a href="#6">[6]</a>
iterator_adaptor&amp; operator++(); iterator_adaptor&amp; operator++();
iterator_adaptor&amp; operator++(int); iterator_adaptor&amp; operator++(int);
@@ -806,6 +860,19 @@ bool operator==(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
// and similarly for operators !=, &lt;, &lt;=, &gt;=, &gt; // and similarly for operators !=, &lt;, &lt;=, &gt;=, &gt;
</pre> </pre>
<h3><a name="portability">Portability</a></h3>
<p>Generally, the iterator adaptors library can be compiled with all compilers
supporting iterator traits and type traits.</p>
<p>Microsoft VC++ is not able to handle iterator adaptors based on a
<code>vector<T>::iterator</code> without specifying all template paramters explicitly.
In case not all template parameters are specified explicitly, the iterator adaptors
library will deduce these types using iterator_traits. But since in VC++ a
<code>vector<T>::iterator</code> is a <code>T*</code>, VC++ can't handle using
iterator_traits due to the lack of partial template specialization.</p>
<h3><a name="notes">Notes</a></h3> <h3><a name="notes">Notes</a></h3>
<p><a name="1">[1]</a> The standard specifies that the <tt>value_type</tt> <p><a name="1">[1]</a> The standard specifies that the <tt>value_type</tt>
@@ -814,12 +881,12 @@ bool operator==(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
<tt>reference</tt> types for all <a href= <tt>reference</tt> types for all <a href=
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterators</a> are "http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterators</a> are
<tt>const T*</tt> and <tt>const T&amp;</tt>, respectively. Stripping the <tt>const T*</tt> and <tt>const T&amp;</tt>, respectively. Stripping the
<tt>const</tt>-ness of <tt>Value</tt> allows you to easily <tt>const</tt>-ness of <tt>Value</tt> allows you to easily make a constant
make a <tt>const</tt> iterator adaptor by supplying a <tt>const</tt> type iterator by supplying a <tt>const</tt> type for <tt>Value</tt>, and allowing
for <tt>Value</tt>, and allowing the defaults for the <tt>Pointer</tt> and the defaults for the <tt>Pointer</tt> and <tt>Reference</tt> parameters to
<tt>Reference</tt> parameters to take effect. Although compilers that don't take effect. Although compilers that don't support partial specialization
support partial specialization won't strip <tt>const</tt> for you, having a won't strip <tt>const</tt> for you, having a <tt>const value_type</tt> is
<tt>const value_type</tt> is often harmless in practice. often harmless in practice.
<p><a name="2">[2]</a> If your compiler does not support partial <p><a name="2">[2]</a> If your compiler does not support partial
specialization and the base iterator is a builtin pointer type, you specialization and the base iterator is a builtin pointer type, you
@@ -857,10 +924,50 @@ bool operator==(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
Forward Iterator</a>, so you will need to use a less restrictive Forward Iterator</a>, so you will need to use a less restrictive
iterator category such as <tt>std::input_iterator_tag</tt>. iterator category such as <tt>std::input_iterator_tag</tt>.
<p><a name="6">[6]</a>
There is a common misconception that an iterator should have two
versions of <tt>operator*</tt> and of <tt>operator[]</tt>, one
version that is a <tt>const</tt> member function and one version
that is non-<tt>const</tt>. Perhaps the source of this
misconception is that containers typically have const and
non-const versions of many of their member functions. Iterators,
however, are different. A particular iterator type can be either
<i>mutable</i> or <i>constant</i> (but not both). One can assign
to and change the object pointed to by a mutable iterator whereas a
constant iterator returns constant objects when dereferenced. Whether
the iterator object itself is <tt>const</tt> has nothing to do with
whether the iterator is mutable or constant. This is analogous to
the way built-in pointer types behave. For example, one can
modify objects pointed to by a <tt>const</tt> pointer
<pre>
int* const x = new int;
int i = 3;
*x = i;
</pre>
but one cannot modify objects pointed to by a pointer
to <tt>const</tt>
<pre>
int const* x = new int;
int i = 3;
*x = i;
</pre>
<p><a name="7">[7]</a>
If you are using a compiler that does not have a version of
<tt>std::iterator_traits</tt> that works for pointers (i.e., if your
compiler does not support partial specialization) then if the
<tt>Base</tt> type is a const pointer, then the correct defaults
for the <tt>reference</tt> and <tt>pointer</tt> types can not be
deduced. You must specify these types explicitly.
<p><a name="8">[8]</a>
Exposing the base object might be considered as being dangerous.
A possible fix would require compiler support for template friends.
As this is not widely available today, the base object remains exposed for now.
<hr> <hr>
<p>Revised <p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->12 Jul 2001<!--webbot bot="Timestamp" endspan i-checksum="14985" --> <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->30 Nov 2001<!--webbot bot="Timestamp" endspan i-checksum="15239" -->
<p>&copy; Copyright Dave Abrahams and Jeremy Siek 2001. Permission to copy, <p>&copy; Copyright Dave Abrahams and Jeremy Siek 2001. Permission to copy,
@@ -871,7 +978,7 @@ bool operator==(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
</body> </body>
<!-- LocalWords: HTML html charset alt gif abrahams htm const <!-- LocalWords: HTML html charset alt gif abrahams htm const iterator
incrementable david abrahams incrementable david abrahams
--> -->
@@ -887,5 +994,7 @@ bool operator==(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
<!-- LocalWords: iostream hpp sizeof InputIterator constness ConstIterator <!-- LocalWords: iostream hpp sizeof InputIterator constness ConstIterator
David Abrahams David Abrahams
--> -->
<!-- LocalWords: Iterators dereferenced
-->
</html> </html>

BIN
iterator_adaptors.pdf Normal file

Binary file not shown.

BIN
iterator_adaptors.ppt Normal file

Binary file not shown.

View File

@@ -1,4 +1,4 @@
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, // (C) Copyright David Abrahams 2002. Permission to copy, use, modify,
// sell and distribute this software is granted provided this // sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided // copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as // "as is" without express or implied warranty, and with no claim as
@@ -22,7 +22,7 @@
// 19 Jan 2001 Initial version with iterator operators (David Abrahams) // 19 Jan 2001 Initial version with iterator operators (David Abrahams)
#include <boost/detail/iterator.hpp> #include <boost/detail/iterator.hpp>
#include <boost/type_traits.hpp> #include <boost/type_traits/is_same.hpp>
#include <boost/operators.hpp> #include <boost/operators.hpp>
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
#include <iterator> #include <iterator>
@@ -31,6 +31,11 @@
#include <cassert> #include <cassert>
#include <iostream> #include <iostream>
// A UDT for which we can specialize std::iterator_traits<element*> on
// compilers which don't support partial specialization. There's no
// other reasonable way to test pointers on those compilers.
struct element {};
// An iterator for which we can get traits. // An iterator for which we can get traits.
struct my_iterator1 struct my_iterator1
: boost::forward_iterator_helper<my_iterator1, char, long, const char*, const char&> : boost::forward_iterator_helper<my_iterator1, char, long, const char*, const char&>
@@ -77,42 +82,47 @@ struct my_iterator2
struct my_iterator3 : my_iterator1 struct my_iterator3 : my_iterator1
{ {
typedef int difference_type; typedef int difference_type;
my_iterator3(const char* p) : my_iterator1(p) {} my_iterator3(const char* p)
: my_iterator1(p) {}
}; };
//
// Assertion tools. Used instead of BOOST_STATIC_ASSERT because that
// doesn't give us a nice stack backtrace
//
template <bool = false> struct assertion;
template <> struct assertion<true>
{
typedef char type;
};
template <class T, class U>
struct assert_same
: assertion<(::boost::is_same<T,U>::value)>
{
};
// Iterator tests
template <class Iterator, template <class Iterator,
class value_type, class difference_type, class pointer, class reference, class category> class value_type, class difference_type, class pointer, class reference, class category>
struct non_portable_tests struct non_portable_tests
{ {
// Unfortunately, the VC6 standard library doesn't supply these :( typedef typename boost::detail::iterator_traits<Iterator>::pointer test_pt;
BOOST_STATIC_ASSERT(( typedef typename boost::detail::iterator_traits<Iterator>::reference test_rt;
boost::is_same< typedef typename assert_same<test_pt, pointer>::type a1;
typename boost::detail::iterator_traits<Iterator>::pointer, typedef typename assert_same<test_rt, reference>::type a2;
pointer
>::value));
BOOST_STATIC_ASSERT((
boost::is_same<
typename boost::detail::iterator_traits<Iterator>::reference,
reference
>::value));
}; };
template <class Iterator, template <class Iterator,
class value_type, class difference_type, class pointer, class reference, class category> class value_type, class difference_type, class pointer, class reference, class category>
struct portable_tests struct portable_tests
{ {
BOOST_STATIC_ASSERT(( typedef typename boost::detail::iterator_traits<Iterator>::difference_type test_dt;
boost::is_same< typedef typename boost::detail::iterator_traits<Iterator>::iterator_category test_cat;
typename boost::detail::iterator_traits<Iterator>::difference_type, typedef typename assert_same<test_dt, difference_type>::type a1;
difference_type typedef typename assert_same<test_cat, category>::type a2;
>::value));
BOOST_STATIC_ASSERT((
boost::is_same<
typename boost::detail::iterator_traits<Iterator>::iterator_category,
category
>::value));
}; };
// Test iterator_traits // Test iterator_traits
@@ -121,11 +131,8 @@ template <class Iterator,
struct input_iterator_test struct input_iterator_test
: portable_tests<Iterator,value_type,difference_type,pointer,reference,category> : portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
{ {
BOOST_STATIC_ASSERT(( typedef typename boost::detail::iterator_traits<Iterator>::value_type test_vt;
boost::is_same< typedef typename assert_same<test_vt, value_type>::type a1;
typename boost::detail::iterator_traits<Iterator>::value_type,
value_type
>::value));
}; };
template <class Iterator, template <class Iterator,
@@ -149,14 +156,13 @@ struct maybe_pointer_test
input_iterator_test<std::istream_iterator<int>, int, std::ptrdiff_t, int*, int&, std::input_iterator_tag> input_iterator_test<std::istream_iterator<int>, int, std::ptrdiff_t, int*, int&, std::input_iterator_tag>
istream_iterator_test; istream_iterator_test;
//
#if defined(__BORLANDC__) && !defined(__SGI_STL_PORT) #if defined(__BORLANDC__) && !defined(__SGI_STL_PORT)
typedef ::std::char_traits<char>::off_type distance; typedef ::std::char_traits<char>::off_type distance;
non_pointer_test<std::ostream_iterator<int>,int, non_pointer_test<std::ostream_iterator<int>,int,
distance,int*,int&,std::output_iterator_tag> ostream_iterator_test; distance,int*,int&,std::output_iterator_tag> ostream_iterator_test;
#elif defined(BOOST_MSVC_STD_ITERATOR) #elif defined(BOOST_MSVC_STD_ITERATOR)
non_pointer_test<std::ostream_iterator<int>, non_pointer_test<std::ostream_iterator<int>,
int, void, void, void, std::output_iterator_tag> int, void, int*, int&, std::output_iterator_tag>
ostream_iterator_test; ostream_iterator_test;
#else #else
non_pointer_test<std::ostream_iterator<int>, non_pointer_test<std::ostream_iterator<int>,
@@ -170,6 +176,7 @@ non_pointer_test<std::ostream_iterator<int>,
#else #else
typedef std::ptrdiff_t std_list_diff_type; typedef std::ptrdiff_t std_list_diff_type;
#endif #endif
non_pointer_test<std::list<int>::iterator, int, std_list_diff_type, int*, int&, std::bidirectional_iterator_tag> non_pointer_test<std::list<int>::iterator, int, std_list_diff_type, int*, int&, std::bidirectional_iterator_tag>
list_iterator_test; list_iterator_test;
@@ -193,7 +200,7 @@ int main()
char chars[100]; char chars[100];
int ints[100]; int ints[100];
for (std::ptrdiff_t length = 3; length < 100; length += length / 3) for (int length = 3; length < 100; length += length / 3)
{ {
std::list<int> l(length); std::list<int> l(length);
assert(boost::detail::distance(l.begin(), l.end()) == length); assert(boost::detail::distance(l.begin(), l.end()) == length);

View File

@@ -75,6 +75,12 @@ protected:
}; // test_opr_base }; // test_opr_base
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
// A definition is required even for integral static constants
const std::size_t test_opr_base::fruit_length;
const std::size_t test_opr_base::scratch_length;
#endif
template <typename T, typename R = T&, typename P = T*> template <typename T, typename R = T&, typename P = T*>
class test_opr class test_opr
: public test_opr_base : public test_opr_base
@@ -94,7 +100,8 @@ public:
private: private:
// Test data // Test data
static iter_type const fruit_begin, fruit_end; static iter_type const fruit_begin;
static iter_type const fruit_end;
// Test parts // Test parts
static void post_increment_test(); static void post_increment_test();
@@ -117,12 +124,12 @@ test_opr_base::scratch_array_type
test_opr_base::scratch = ""; test_opr_base::scratch = "";
template <typename T, typename R, typename P> template <typename T, typename R, typename P>
typename test_opr<T, R, P>::iter_type const typename test_opr<T, R, P>::iter_type const
test_opr<T, R, P>::fruit_begin( fruit ); test_opr<T, R, P>::fruit_begin = test_iter<T,R,P>( fruit );
template <typename T, typename R, typename P> template <typename T, typename R, typename P>
typename test_opr<T, R, P>::iter_type const typename test_opr<T, R, P>::iter_type const
test_opr<T, R, P>::fruit_end( fruit + fruit_length ); test_opr<T, R, P>::fruit_end = test_iter<T,R,P>( fruit + fruit_length );
// Main testing function // Main testing function

View File

@@ -12,7 +12,7 @@
// 9 Jun 99 Add unnamed namespace // 9 Jun 99 Add unnamed namespace
// 2 Jun 99 Initial Version // 2 Jun 99 Initial Version
#include <boost/utility.hpp> #include <boost/noncopyable.hpp>
#include <iostream> #include <iostream>
// This program demonstrates compiler errors resulting from trying to copy // This program demonstrates compiler errors resulting from trying to copy
@@ -20,7 +20,7 @@
namespace namespace
{ {
class DontTreadOnMe : boost::noncopyable class DontTreadOnMe : private boost::noncopyable
{ {
public: public:
DontTreadOnMe() { std::cout << "defanged!" << std::endl; } DontTreadOnMe() { std::cout << "defanged!" << std::endl; }

View File

@@ -347,7 +347,7 @@ void test(Number* = 0)
// factoring out difference_type for the assert below confused Borland :( // factoring out difference_type for the assert below confused Borland :(
typedef boost::detail::is_signed< typedef boost::detail::is_signed<
#ifndef BOOST_MSVC #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
typename typename
#endif #endif
boost::detail::numeric_traits<Number>::difference_type boost::detail::numeric_traits<Number>::difference_type
@@ -374,7 +374,7 @@ int main()
test<unsigned int>(); test<unsigned int>();
test<long>(); test<long>();
test<unsigned long>(); test<unsigned long>();
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) #if defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_INTEGRAL_INT64_T)
test<long long>(); test<long long>();
test<unsigned long long>(); test<unsigned long long>();
#elif defined(BOOST_MSVC) #elif defined(BOOST_MSVC)

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,8 @@
// See http://www.boost.org for most recent version including documentation. // See http://www.boost.org for most recent version including documentation.
// Revision History // Revision History
// 01 Oct 01 Added tests for "left" operators
// and new grouped operators. (Helmut Zeisel)
// 20 May 01 Output progress messages. Added tests for new operator // 20 May 01 Output progress messages. Added tests for new operator
// templates. Updated random number generator. Changed tests to // templates. Updated random number generator. Changed tests to
// use Boost Test Tools library. (Daryle Walker) // use Boost Test Tools library. (Daryle Walker)
@@ -184,6 +186,74 @@ namespace
template <class T, class U> template <class T, class U>
T true_value(Wrapped4<T,U> x) { return x.value(); } T true_value(Wrapped4<T,U> x) { return x.value(); }
// U must be convertible to T
template <class T, class U>
class Wrapped5
: boost::ordered_field_operators2<Wrapped5<T, U>, U>
, boost::ordered_field_operators1<Wrapped5<T, U> >
{
public:
explicit Wrapped5( T v = T() ) : _value(v) {}
// Conversion from U to Wrapped5<T,U>
Wrapped5(U u) : _value(u) {}
T value() const { return _value; }
bool operator<(const Wrapped5& x) const { return _value < x._value; }
bool operator<(U u) const { return _value < u; }
bool operator>(U u) const { return _value > u; }
bool operator==(const Wrapped5& u) const { return _value == u._value; }
bool operator==(U u) const { return _value == u; }
Wrapped5& operator/=(const Wrapped5& u) { _value /= u._value; return *this;}
Wrapped5& operator/=(U u) { _value /= u; return *this;}
Wrapped5& operator*=(const Wrapped5& u) { _value *= u._value; return *this;}
Wrapped5& operator*=(U u) { _value *= u; return *this;}
Wrapped5& operator-=(const Wrapped5& u) { _value -= u._value; return *this;}
Wrapped5& operator-=(U u) { _value -= u; return *this;}
Wrapped5& operator+=(const Wrapped5& u) { _value += u._value; return *this;}
Wrapped5& operator+=(U u) { _value += u; return *this;}
private:
T _value;
};
template <class T, class U>
T true_value(Wrapped5<T,U> x) { return x.value(); }
// U must be convertible to T
template <class T, class U>
class Wrapped6
: boost::ordered_euclidian_ring_operators2<Wrapped6<T, U>, U>
, boost::ordered_euclidian_ring_operators1<Wrapped6<T, U> >
{
public:
explicit Wrapped6( T v = T() ) : _value(v) {}
// Conversion from U to Wrapped6<T,U>
Wrapped6(U u) : _value(u) {}
T value() const { return _value; }
bool operator<(const Wrapped6& x) const { return _value < x._value; }
bool operator<(U u) const { return _value < u; }
bool operator>(U u) const { return _value > u; }
bool operator==(const Wrapped6& u) const { return _value == u._value; }
bool operator==(U u) const { return _value == u; }
Wrapped6& operator%=(const Wrapped6& u) { _value %= u._value; return *this;}
Wrapped6& operator%=(U u) { _value %= u; return *this;}
Wrapped6& operator/=(const Wrapped6& u) { _value /= u._value; return *this;}
Wrapped6& operator/=(U u) { _value /= u; return *this;}
Wrapped6& operator*=(const Wrapped6& u) { _value *= u._value; return *this;}
Wrapped6& operator*=(U u) { _value *= u; return *this;}
Wrapped6& operator-=(const Wrapped6& u) { _value -= u._value; return *this;}
Wrapped6& operator-=(U u) { _value -= u; return *this;}
Wrapped6& operator+=(const Wrapped6& u) { _value += u._value; return *this;}
Wrapped6& operator+=(U u) { _value += u; return *this;}
private:
T _value;
};
template <class T, class U>
T true_value(Wrapped6<T,U> x) { return x.value(); }
// MyInt uses only the single template-argument form of all_operators<> // MyInt uses only the single template-argument form of all_operators<>
typedef Wrapped1<int> MyInt; typedef Wrapped1<int> MyInt;
@@ -193,6 +263,10 @@ namespace
typedef Wrapped4<short, short> MyShort; typedef Wrapped4<short, short> MyShort;
typedef Wrapped5<double, int> MyDoubleInt;
typedef Wrapped6<long, int> MyLongInt;
template <class X1, class Y1, class X2, class Y2> template <class X1, class Y1, class X2, class Y2>
void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2) void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
{ {
@@ -267,6 +341,13 @@ namespace
BOOST_TEST( (x1 - y1).value() == (x2 - y2) ); BOOST_TEST( (x1 - y1).value() == (x2 - y2) );
} }
template <class X1, class Y1, class X2, class Y2>
void test_subtractable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
BOOST_TEST( (y1 - x1).value() == (y2 - x2) );
}
template <class X1, class Y1, class X2, class Y2> template <class X1, class Y1, class X2, class Y2>
void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2) void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{ {
@@ -275,6 +356,14 @@ namespace
BOOST_TEST( (x1 / y1).value() == (x2 / y2) ); BOOST_TEST( (x1 / y1).value() == (x2 / y2) );
} }
template <class X1, class Y1, class X2, class Y2>
void test_dividable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
if ( x2 != 0 )
BOOST_TEST( (y1 / x1).value() == (y2 / x2) );
}
template <class X1, class Y1, class X2, class Y2> template <class X1, class Y1, class X2, class Y2>
void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2) void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{ {
@@ -283,6 +372,14 @@ namespace
BOOST_TEST( (x1 % y1).value() == (x2 % y2) ); BOOST_TEST( (x1 % y1).value() == (x2 % y2) );
} }
template <class X1, class Y1, class X2, class Y2>
void test_modable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
if ( x2 != 0 )
BOOST_TEST( (y1 % x1).value() == (y2 % x2) );
}
template <class X1, class Y1, class X2, class Y2> template <class X1, class Y1, class X2, class Y2>
void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{ {
@@ -374,6 +471,14 @@ namespace
test_decrementable( x1, x2 ); test_decrementable( x1, x2 );
} }
template <class X1, class Y1, class X2, class Y2>
void test_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
test_subtractable_left( x1, y1, x2, y2 );
test_dividable_left( x1, y1, x2, y2 );
test_modable_left( x1, y1, x2, y2 );
}
template <class Big, class Small> template <class Big, class Small>
struct tester struct tester
{ {
@@ -388,6 +493,18 @@ namespace
} }
}; };
template <class Big, class Small>
struct tester_left
{
void operator()(boost::minstd_rand& randomizer) const
{
Big b1 = Big( randomizer() );
Small s = Small( randomizer() );
test_left( Wrapped6<Big, Small>(b1), s, b1, s );
}
};
// added as a regression test. We had a bug which this uncovered. // added as a regression test. We had a bug which this uncovered.
struct Point struct Point
: boost::addable<Point : boost::addable<Point
@@ -427,6 +544,13 @@ template Wrapped2<unsigned int, unsigned char>;
template Wrapped2<unsigned long, unsigned int>; template Wrapped2<unsigned long, unsigned int>;
template Wrapped2<unsigned long, unsigned char>; template Wrapped2<unsigned long, unsigned char>;
template Wrapped2<unsigned long, unsigned long>; template Wrapped2<unsigned long, unsigned long>;
template Wrapped6<long, int>;
template Wrapped6<long, signed char>;
template Wrapped6<int, signed char>;
template Wrapped6<unsigned long, unsigned int>;
template Wrapped6<unsigned long, unsigned char>;
template Wrapped6<unsigned int, unsigned char>;
#endif #endif
#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) ) #define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) )
@@ -445,7 +569,7 @@ test_main( int , char * [] )
cout << "Created point, and operated on it." << endl; cout << "Created point, and operated on it." << endl;
for (int n = 0; n < 10000; ++n) for (int n = 0; n < 1000; ++n) // was 10,000 but took too long (Beman)
{ {
boost::minstd_rand r; boost::minstd_rand r;
tester<long, int>()(r); tester<long, int>()(r);
@@ -459,6 +583,14 @@ test_main( int , char * [] )
tester<unsigned long, unsigned long>()(r); tester<unsigned long, unsigned long>()(r);
tester<unsigned int, unsigned int>()(r); tester<unsigned int, unsigned int>()(r);
tester<unsigned int, unsigned char>()(r); tester<unsigned int, unsigned char>()(r);
tester_left<long, int>()(r);
tester_left<long, signed char>()(r);
tester_left<int, signed char>()(r);
tester_left<unsigned long, unsigned int>()(r);
tester_left<unsigned long, unsigned char>()(r);
tester_left<unsigned int, unsigned char>()(r);
} }
cout << "Did random tester loop." << endl; cout << "Did random tester loop." << endl;
@@ -653,5 +785,106 @@ test_main( int , char * [] )
cout << "Performed tests on MyShort objects.\n"; cout << "Performed tests on MyShort objects.\n";
MyDoubleInt di1(1);
MyDoubleInt di2(2.);
MyDoubleInt half(0.5);
MyDoubleInt di;
MyDoubleInt tmp;
BOOST_TEST( di1.value() == 1 );
BOOST_TEST( di2.value() == 2 );
BOOST_TEST( di2.value() == 2 );
BOOST_TEST( di.value() == 0 );
cout << "Created MyDoubleInt objects.\n";
PRIVATE_EXPR_TEST( (di = di2), (di.value() == 2) );
BOOST_TEST( di2 == di );
BOOST_TEST( 2 == di );
BOOST_TEST( di == 2 );
BOOST_TEST( di1 < di2 );
BOOST_TEST( 1 < di2 );
BOOST_TEST( di1 <= di2 );
BOOST_TEST( 1 <= di2 );
BOOST_TEST( di2 > di1 );
BOOST_TEST( di2 > 1 );
BOOST_TEST( di2 >= di1 );
BOOST_TEST( di2 >= 1 );
BOOST_TEST( di1 / di2 == half );
BOOST_TEST( di1 / 2 == half );
BOOST_TEST( 1 / di2 == half );
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=2) == half) );
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=di2) == half) );
BOOST_TEST( di1 * di2 == di2 );
BOOST_TEST( di1 * 2 == di2 );
BOOST_TEST( 1 * di2 == di2 );
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=2) == di2) );
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=di2) == di2) );
BOOST_TEST( di2 - di1 == di1 );
BOOST_TEST( di2 - 1 == di1 );
BOOST_TEST( 2 - di1 == di1 );
PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=1) == di1) );
PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=di1) == di1) );
BOOST_TEST( di1 + di1 == di2 );
BOOST_TEST( di1 + 1 == di2 );
BOOST_TEST( 1 + di1 == di2 );
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=1) == di2) );
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=di1) == di2) );
cout << "Performed tests on MyDoubleInt objects.\n";
MyLongInt li1(1);
MyLongInt li2(2);
MyLongInt li;
MyLongInt tmp2;
BOOST_TEST( li1.value() == 1 );
BOOST_TEST( li2.value() == 2 );
BOOST_TEST( li.value() == 0 );
cout << "Created MyLongInt objects.\n";
PRIVATE_EXPR_TEST( (li = li2), (li.value() == 2) );
BOOST_TEST( li2 == li );
BOOST_TEST( 2 == li );
BOOST_TEST( li == 2 );
BOOST_TEST( li1 < li2 );
BOOST_TEST( 1 < li2 );
BOOST_TEST( li1 <= li2 );
BOOST_TEST( 1 <= li2 );
BOOST_TEST( li2 > li1 );
BOOST_TEST( li2 > 1 );
BOOST_TEST( li2 >= li1 );
BOOST_TEST( li2 >= 1 );
BOOST_TEST( li1 % li2 == li1 );
BOOST_TEST( li1 % 2 == li1 );
BOOST_TEST( 1 % li2 == li1 );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=2) == li1) );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=li2) == li1) );
BOOST_TEST( li1 / li2 == 0 );
BOOST_TEST( li1 / 2 == 0 );
BOOST_TEST( 1 / li2 == 0 );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=2) == 0) );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=li2) == 0) );
BOOST_TEST( li1 * li2 == li2 );
BOOST_TEST( li1 * 2 == li2 );
BOOST_TEST( 1 * li2 == li2 );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=2) == li2) );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=li2) == li2) );
BOOST_TEST( li2 - li1 == li1 );
BOOST_TEST( li2 - 1 == li1 );
BOOST_TEST( 2 - li1 == li1 );
PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=1) == li1) );
PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=li1) == li1) );
BOOST_TEST( li1 + li1 == li2 );
BOOST_TEST( li1 + 1 == li2 );
BOOST_TEST( 1 + li1 == li2 );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=1) == li2) );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=li1) == li2) );
cout << "Performed tests on MyLongInt objects.\n";
return boost::exit_success; return boost::exit_success;
} }

177
permutation_iterator.htm Normal file
View File

@@ -0,0 +1,177 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title>Permutation Iterator Adaptor Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1>Permutation Iterator Adaptor</h1>
<p>Defined in header <a href="../../boost/permutation_iterator.hpp">boost/permutation_iterator.hpp</a></p>
<p>The permutation iterator adaptor provides an iterator to a permutation of a given range.
(<a href="http://www.cut-the-knot.com/do_you_know/permutation.html">see definition of permutation</a>).
The adaptor takes two arguments
<ul>
<li>an iterator to the range V on which the <a href="http://www.cut-the-knot.com/do_you_know/permutation.html">permutation</a> will be applied</li>
<li>the reindexing scheme that defines how the elements of V will be permuted.</li>
</ul>
<p>Note that the permutation iterator is not limited to strict permutations of the given range V.
The distance between begin and end of the reindexing iterators is allowed to be smaller compared to the
size of the range V, in which case the permutation iterator only provides a permutation of a subrange of V.
The indexes neither need to be unique. In this same context, it must be noted that the past the end permutation iterator is
completely defined by means of the past-the-end iterator to the indices</p>
<h2>Synopsis</h2>
<blockquote>
<pre>
namespace boost {
template &lt;class IndexIterator&gt;
class permutation_iterator_policies;
template &lt;class ElementIterator, class IndexIterator&gt;
class permutation_iterator_generator;
template &lt;class ElementIterator, class IndexIterator&gt;
typename permutation_iterator_generator&lt;ElementIterator, IndexIterator&gt;::type
make_permutation_iterator(ElementIterator&amp; base, IndexIterator&amp; indexing);
}
</pre>
</blockquote>
<h2>The Permutation Iterator Generator Class Template</h2>
<p>The <code>permutation_iterator_generator</code> is a helper class whose purpose
is to construct a permutation iterator <strong>type</strong>. This class has
two template arguments, the first being the iterator type over the range V, the
second being the type of the iterator over the indices.
<blockquote>
<pre>
template &lt;class ElementIterator, class IndexIterator&gt;
class permutation_iterator_generator
{
public:
typedef <a href="iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt...&gt; type; // the resulting permutation iterator type
}
</pre>
</blockquote>
<h3>Template Parameters</h3>
<table border>
<tr>
<th>Parameter</th>
<th>Description</th>
</tr>
<tr>
<td><tt>ElementIterator</tt></td>
<td>The iterator over the elements to be permuted. This type must be a model
of <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a></td>
</td>
<tr>
<td><tt>IndexIterator</tt></td>
<td>The iterator over the new indexing scheme. This type must at least be a model
of <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>.
The <code>IndexIterator::value_type</code> must be convertible to the
<code>ElementIterator::difference_type</code>.</td>
</table>
<h3>Concept Model</h3>
The permutation iterator is always a model of the same concept as the IndexIterator.
<h3>Members</h3>
The permutation iterator implements the member functions
and operators required for the
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterator</a>
concept. However, the permutation iterator can only meet the complexity guarantees
of the same concept as the IndexIterator. Thus for instance, although the permutation
iterator provides <code>operator+=(distance)</code>, this operation will take linear time
in case the IndexIterator is a model of ForwardIterator instead of amortized constant time.
<br>
<h2><a name="make_generator_iterator">The Permutation Iterator Object Generator</a></h2>
The <code>make_permutation_iterator()</code> function provides a
convenient way to create permutation iterator objects. The function
saves the user the trouble of explicitly writing out the iterator
types.
<blockquote>
<pre>
template &lt;class ElementIterator, class IndexIterator &gt;
typename permutation_iterator_generator&lt;ElementIterator, IndexIterator&gt;::type
make_permutation_iterator(ElementIterator&amp; base, IndexIterator&amp; indices);
</pre>
</blockquote>
<h2>Example</h2>
<blockquote>
<pre>
using namespace boost;
int i = 0;
typedef std::vector< int > element_range_type;
typedef std::list< int > index_type;
static const int element_range_size = 10;
static const int index_size = 4;
element_range_type elements( element_range_size );
for(element_range_type::iterator el_it = elements.begin() ; el_it != elements.end() ; ++el_it) *el_it = std::distance(elements.begin(), el_it);
index_type indices( index_size );
for(index_type::iterator i_it = indices.begin() ; i_it != indices.end() ; ++i_it ) *i_it = element_range_size - index_size + std::distance(indices.begin(), i_it);
std::reverse( indices.begin(), indices.end() );
typedef permutation_iterator_generator< element_range_type::iterator, index_type::iterator >::type permutation_type;
permutation_type begin = make_permutation_iterator( elements.begin(), indices.begin() );
permutation_type it = begin;
permutation_type end = make_permutation_iterator( elements.begin(), indices.end() );
std::cout << "The original range is : ";
std::copy( elements.begin(), elements.end(), std::ostream_iterator< int >( std::cout, " " ) );
std::cout << "\n";
std::cout << "The reindexing scheme is : ";
std::copy( indices.begin(), indices.end(), std::ostream_iterator< int >( std::cout, " " ) );
std::cout << "\n";
std::cout << "The permutated range is : ";
std::copy( begin, end, std::ostream_iterator< int >( std::cout, " " ) );
std::cout << "\n";
std::cout << "Elements at even indices in the permutation : ";
it = begin;
for(i = 0; i < index_size / 2 ; ++i, it+=2 ) std::cout << *it << " ";
std::cout << "\n";
std::cout << "Permutation backwards : ";
it = begin + (index_size);
assert( it != begin );
for( ; it-- != begin ; ) std::cout << *it << " ";
std::cout << "\n";
std::cout << "Iterate backward with stride 2 : ";
it = begin + (index_size - 1);
for(i = 0 ; i < index_size / 2 ; ++i, it-=2 ) std::cout << *it << " ";
std::cout << "\n";
</pre>
</blockquote>
<br><br><br><hr>
Thanks: The permutation iterator is only a small addition to the superb iterator adaptors
library of David Abrahams and Jeremy Siek.
<br><br>
Copyright 2001 Toon Knapen.
</body>
</html>

View File

@@ -371,7 +371,7 @@ Betty
</pre> </pre>
<hr> <hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" --></p> <p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" --></p>
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use, <p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
modify, sell and distribute this document is granted provided this copyright modify, sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &quot;as is&quot; notice appears in all copies. This document is provided &quot;as is&quot;

115
ref_ct_test.cpp Normal file
View File

@@ -0,0 +1,115 @@
// compile-time test for "boost/ref.hpp" header content
// see 'ref_test.cpp' for run-time part
#include <boost/ref.hpp>
#include <boost/type_traits/same_traits.hpp>
#include <boost/static_assert.hpp>
namespace {
template< typename T, typename U >
void ref_test(boost::reference_wrapper<U>)
{
typedef typename boost::reference_wrapper<U>::type type;
BOOST_STATIC_ASSERT((boost::is_same<U,type>::value));
BOOST_STATIC_ASSERT((boost::is_same<T,type>::value));
}
template< typename T >
void assignable_test(T x)
{
x = x;
}
template< bool R, typename T >
void is_reference_wrapper_test(T)
{
BOOST_STATIC_ASSERT(boost::is_reference_wrapper<T>::value == R);
}
template< typename R, typename Ref >
void cxx_reference_test(Ref)
{
BOOST_STATIC_ASSERT((boost::is_same<R,Ref>::value));
}
template< typename R, typename Ref >
void unwrap_reference_test(Ref)
{
typedef typename boost::unwrap_reference<Ref>::type type;
BOOST_STATIC_ASSERT((boost::is_same<R,type>::value));
}
} // namespace
int main()
{
int i = 0;
int& ri = i;
int const ci = 0;
int const& rci = ci;
// 'ref/cref' functions test
ref_test<int>(boost::ref(i));
ref_test<int>(boost::ref(ri));
ref_test<int const>(boost::ref(ci));
ref_test<int const>(boost::ref(rci));
ref_test<int const>(boost::cref(i));
ref_test<int const>(boost::cref(ri));
ref_test<int const>(boost::cref(ci));
ref_test<int const>(boost::cref(rci));
// test 'assignable' requirement
assignable_test(boost::ref(i));
assignable_test(boost::ref(ri));
assignable_test(boost::cref(i));
assignable_test(boost::cref(ci));
assignable_test(boost::cref(rci));
// 'is_reference_wrapper' test
is_reference_wrapper_test<true>(boost::ref(i));
is_reference_wrapper_test<true>(boost::ref(ri));
is_reference_wrapper_test<true>(boost::cref(i));
is_reference_wrapper_test<true>(boost::cref(ci));
is_reference_wrapper_test<true>(boost::cref(rci));
is_reference_wrapper_test<false>(i);
is_reference_wrapper_test<false, int&>(ri);
is_reference_wrapper_test<false>(ci);
is_reference_wrapper_test<false, int const&>(rci);
// ordinary references/function template arguments deduction test
cxx_reference_test<int>(i);
cxx_reference_test<int>(ri);
cxx_reference_test<int>(ci);
cxx_reference_test<int>(rci);
cxx_reference_test<int&, int&>(i);
cxx_reference_test<int&, int&>(ri);
cxx_reference_test<int const&, int const&>(i);
cxx_reference_test<int const&, int const&>(ri);
cxx_reference_test<int const&, int const&>(ci);
cxx_reference_test<int const&, int const&>(rci);
// 'unwrap_reference' test
unwrap_reference_test<int>(boost::ref(i));
unwrap_reference_test<int>(boost::ref(ri));
unwrap_reference_test<int const>(boost::cref(i));
unwrap_reference_test<int const>(boost::cref(ci));
unwrap_reference_test<int const>(boost::cref(rci));
unwrap_reference_test<int>(i);
unwrap_reference_test<int>(ri);
unwrap_reference_test<int>(ci);
unwrap_reference_test<int>(rci);
unwrap_reference_test<int&, int&>(i);
unwrap_reference_test<int&, int&>(ri);
unwrap_reference_test<int const&, int const&>(i);
unwrap_reference_test<int const&, int const&>(ri);
unwrap_reference_test<int const&, int const&>(ci);
unwrap_reference_test<int const&, int const&>(rci);
return 0;
}

74
ref_test.cpp Normal file
View File

@@ -0,0 +1,74 @@
// run-time test for "boost/ref.hpp" header content
// see 'ref_ct_test.cpp' for compile-time part
#if defined(_MSC_VER) && !defined(__ICL)
# pragma warning(disable: 4786) // identifier truncated in debug info
# pragma warning(disable: 4710) // function not inlined
# pragma warning(disable: 4711) // function selected for automatic inline expansion
# pragma warning(disable: 4514) // unreferenced inline removed
#endif
#include <boost/ref.hpp>
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
# pragma warning(push, 3)
#endif
#include <iostream>
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
# pragma warning(pop)
#endif
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
namespace {
using namespace boost;
template <class T>
struct ref_wrapper
{
// Used to verify implicit conversion
static T* get_pointer(T& x)
{
return &x;
}
static T const* get_const_pointer(T const& x)
{
return &x;
}
template <class Arg>
static T* passthru(Arg x)
{
return get_pointer(x);
}
template <class Arg>
static T const* cref_passthru(Arg x)
{
return get_const_pointer(x);
}
static void test(T x)
{
BOOST_TEST(passthru(ref(x)) == &x);
BOOST_TEST(&ref(x).get() == &x);
BOOST_TEST(cref_passthru(cref(x)) == &x);
BOOST_TEST(&cref(x).get() == &x);
}
};
} // namespace unnamed
int test_main(int, char * [])
{
ref_wrapper<int>::test(1);
ref_wrapper<int const>::test(1);
return 0;
}

View File

@@ -312,7 +312,7 @@ simply use <tt>reverse_iterator_generator</tt> twice!<br><br>
<p>Revised <p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" --> <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" -->
<p>&copy; Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell <p>&copy; Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell

View File

@@ -10,17 +10,26 @@
int main(int, char*[]) int main(int, char*[])
{ {
char letters[] = "hello world!"; char letters_[] = "hello world!";
const int N = sizeof(letters)/sizeof(char) - 1; const int N = sizeof(letters_)/sizeof(char) - 1;
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
// Assume there won't be proper iterator traits for pointers. This
// is just a wrapper for char* which has the right traits.
typedef boost::iterator_adaptor<char*, boost::default_iterator_policies, char> base_iterator;
#else
typedef char* base_iterator;
#endif
base_iterator letters(letters_);
std::cout << "original sequence of letters:\t" std::cout << "original sequence of letters:\t"
<< letters << std::endl; << letters_ << std::endl;
std::sort(letters, letters + N); std::sort(letters, letters + N);
// Use reverse_iterator_generator to print a sequence // Use reverse_iterator_generator to print a sequence
// of letters in reverse order. // of letters in reverse order.
boost::reverse_iterator_generator<char*>::type boost::reverse_iterator_generator<base_iterator>::type
reverse_letters_first(letters + N), reverse_letters_first(letters + N),
reverse_letters_last(letters); reverse_letters_last(letters);

View File

@@ -0,0 +1,332 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Shared Container Iterator Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
align="center" width="277" height="86">
<h1>Shared Container Iterator</h1>
Defined in header
<a href="../../boost/shared_container_iterator.hpp">boost/shared_container_iterator.hpp</a>
<p>
The purpose of the shared container iterator is to attach the lifetime
of a container to the lifetime of its iterators. In other words,
the container will be deleted after the last iterator is destroyed.
The shared container iterator is typically used to implement functions
that return iterators over a
range of objects that will only be needed for the lifetime of
the iterators. By returning a pair of shared iterators from a
function, the callee can ensure that the underlying container's
lifetime will be properly managed.
<p>
The shared container iterator augments an iterator into a shared
container with a reference counted pointer to the container.
Assuming no other references exist to the container, it will be
destroyed when the last shared container iterator is destroyed.
In all other ways, the shared container iterator
behaves the same as its base iterator.
<h2>Synopsis</h2>
<pre>
namespace boost {
template &lt;typename <a href="http://www.sgi.com/tech/stl/Container.html">Container</a>&gt;
class shared_container_iterator_generator;
template &lt;typename <a href="http://www.sgi.com/tech/stl/Container.html">Container</a>&gt;
typename shared_container_iterator_generator&lt;Container&gt;::type
make_shared_container_iterator(typename Container::iterator base,
boost::shared_ptr&lt;Container&gt; const&amp; container);
std::pair&lt
typename shared_container_iterator_generator&lt;Container&gt;::type,
typename shared_container_iterator_generator&lt;Container&gt;::type
&gt;
make_shared_container_range(boost::shared_ptr&lt;Container&gt; const&amp; container);
}
</pre>
<hr>
<h2><a name="generator">The Shared Container Iterator Type Generator</a></h2>
The class <tt>shared_container_iterator_generator</tt> is a helper
class to construct a shared container iterator type. The template
parameter for this class is a type that models the
<a href="http://www.sgi.com/tech/stl/Container.html">Container</a>
concept.
<pre>
template &lt;typename Container&gt;
class shared_container_iterator_generator
{
public:
typedef <a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt;...&gt; type;
};
</pre>
<h3>Example</h3>
<p>
The following example illustrates how to use the
<tt>shared_counter_iterator_generator</tt> to create an iterator that
regulates the lifetime of a reference counted <tt>std::vector</tt>.
Though the original <tt>shared_ptr</tt> to the vector ceases to exist, the
<tt>shared_counter_iterator</tt>s extend the lifetime of the container.
<p>
<a href="./shared_iterator_example1.cpp">shared_iterator_example1.cpp</a>:
<PRE>
<font color="#008040">#include "shared_container_iterator.hpp"</font>
<font color="#008040">#include "boost/shared_ptr.hpp"</font>
<font color="#008040">#include &lt;algorithm&gt;</font>
<font color="#008040">#include &lt;iostream&gt;</font>
<font color="#008040">#include &lt;vector&gt;</font>
<B>typedef</B> boost::shared_container_iterator_generator&lt; std::vector&lt;<B>int</B>&gt; &gt;::type iterator;
<B>void</B> set_range(iterator& i, iterator& end) {
boost::shared_ptr&lt; std::vector&lt;<B>int</B>&gt; &gt; ints(<B>new</B> std::vector&lt;<B>int</B>&gt;());
ints-&gt;push_back(<font color="#0000A0">0</font>);
ints-&gt;push_back(<font color="#0000A0">1</font>);
ints-&gt;push_back(<font color="#0000A0">2</font>);
ints-&gt;push_back(<font color="#0000A0">3</font>);
ints-&gt;push_back(<font color="#0000A0">4</font>);
ints-&gt;push_back(<font color="#0000A0">5</font>);
i = iterator(ints-&gt;begin(),ints);
end = iterator(ints-&gt;end(),ints);
}
<B>int</B> main() {
iterator i,end;
set_range(i,end);
std::copy(i,end,std::ostream_iterator&lt;<B>int</B>&gt;(std::cout,<font color="#0000FF">","</font>));
std::cout.put(<font color="#0000FF">'\n'</font>);
<B>return</B> <font color="#0000A0">0</font>;
}
</PRE>
The output from this part is:
<pre>
0,1,2,3,4,5,
</pre>
<h3>Template Parameters</h3>
<Table border>
<TR>
<TH>Parameter</TH><TH>Description</TH>
</TR>
<TR>
<TD><a
href="http://www.sgi.com/tech/stl/Container.html"><tt>Container</tt></a></TD>
<TD>The type of the container that we wish to iterate over. It must be
a model of the
<a href="http://www.sgi.com/tech/stl/Container.html"><tt>Container</tt></a>
concept.
</TD>
</TR>
</Table>
<h3>Model of</h3>
The shared container iterator adaptor (the type
<tt>shared_container_iterator_generator<...>::type</tt>) models the
same iterator concept as the base iterator
(<tt>Container::iterator</tt>) up to
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access Iterator</a>.
<h3>Members</h3>
The shared container iterator type implements the member functions and
operators required of the <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterator</a>
concept, though only operations defined for the base iterator will be valid.
In addition it has the following constructor:
<pre>
shared_container_iterator_generator::type(Container::iterator const&amp; it,
boost::shared_ptr&lt;Container&gt; const&amp; container)
</pre>
<p>
<hr>
<p>
<h2><a name="make_iterator">The Shared Container Iterator Object Generator</a></h2>
<pre>
template &lt;typename Container&gt;
typename shared_container_iterator_generator&lt;AdaptableUnaryFunction,BaseIterator&gt;::type
make_shared_container_iterator(Container::iterator base,
boost::shared_ptr&lt;Container&gt; const&amp; container)
</pre>
This function provides an alternative to using the shared container
iterator type generator to create the iterator type before
construction. Using the object generator, a shared container iterator
can be created and passed to a function without explicitly specifying
its type.
<h3>Example</h3>
This example, similar to the previous, uses
<tt>make_shared_container_iterator()</tt> to create the iterators.
<p>
<a href="./shared_iterator_example2.cpp">shared_iterator_example2.cpp</a>:
<PRE>
<font color="#008040">#include "shared_container_iterator.hpp"</font>
<font color="#008040">#include "boost/shared_ptr.hpp"</font>
<font color="#008040">#include &lt;algorithm&gt;</font>
<font color="#008040">#include &lt;iterator&gt;</font>
<font color="#008040">#include &lt;iostream&gt;</font>
<font color="#008040">#include &lt;vector&gt;</font>
<B>template</B> &lt;<B>typename</B> Iterator&gt;
<B>void</B> print_range_nl (Iterator begin, Iterator end) {
<B>typedef</B> <B>typename</B> std::iterator_traits&lt;Iterator&gt;::value_type val;
std::copy(begin,end,std::ostream_iterator&lt;val&gt;(std::cout,<font color="#0000FF">","</font>));
std::cout.put(<font color="#0000FF">'\n'</font>);
}
<B>int</B> main() {
<B>typedef</B> boost::shared_ptr&lt; std::vector&lt;<B>int</B>&gt; &gt; ints_t;
{
ints_t ints(<B>new</B> std::vector&lt;<B>int</B>&gt;());
ints-&gt;push_back(<font color="#0000A0">0</font>);
ints-&gt;push_back(<font color="#0000A0">1</font>);
ints-&gt;push_back(<font color="#0000A0">2</font>);
ints-&gt;push_back(<font color="#0000A0">3</font>);
ints-&gt;push_back(<font color="#0000A0">4</font>);
ints-&gt;push_back(<font color="#0000A0">5</font>);
print_range_nl(boost::make_shared_container_iterator(ints-&gt;begin(),ints),
boost::make_shared_container_iterator(ints-&gt;end(),ints));
}
<B>return</B> <font color="#0000A0">0</font>;
}
</PRE>
Observe that the <tt>shared_container_iterator</tt> type is never
explicitly named. The output from this example is the same as the previous.
<h2><a name="make_range">The Shared Container Iterator Range Generator</a></h2>
<pre>
template &lt;typename Container&gt;
std::pair&lt
typename shared_container_iterator_generator&lt;Container&gt;::type,
typename shared_container_iterator_generator&lt;Container&gt;::type
&gt;
make_shared_container_range(boost::shared_ptr&lt;Container&gt; const&amp; container);
</pre>
Class <tt>shared_container_iterator</tt> is meant primarily to return
via iterators a range of values that we can guarantee will be alive as
long as the iterators are. This is a convenience
function to do just that. This function is equivalent to
<pre>
std::make_pair(make_shared_container_iterator(container-&gt;begin(),container),
make_shared_container_iterator(container-&gt;end(),container));
</pre>
<h3>Example</h3>
In the following example, a range of values is returned as a pair of
<tt>shared_container_iterator</tt>s.
<p>
<a href="./shared_iterator_example3.cpp">shared_iterator_example3.cpp</a>:
<PRE>
<font color="#008040">#include "shared_container_iterator.hpp"</font>
<font color="#008040">#include "boost/shared_ptr.hpp"</font>
<font color="#008040">#include "boost/tuple/tuple.hpp" // for boost::tie</font>
<font color="#008040">#include &lt;algorithm&gt; // for std::copy</font>
<font color="#008040">#include &lt;iostream&gt; </font>
<font color="#008040">#include &lt;vector&gt;</font>
<B>typedef</B> boost::shared_container_iterator_generator&lt; std::vector&lt;<B>int</B>&gt; &gt;::type
function_iterator;
std::pair&lt;function_iterator,function_iterator&gt;
return_range() {
boost::shared_ptr&lt; std::vector&lt;<B>int</B>&gt; &gt; range(<B>new</B> std::vector&lt;<B>int</B>&gt;());
range-&gt;push_back(<font color="#0000A0">0</font>);
range-&gt;push_back(<font color="#0000A0">1</font>);
range-&gt;push_back(<font color="#0000A0">2</font>);
range-&gt;push_back(<font color="#0000A0">3</font>);
range-&gt;push_back(<font color="#0000A0">4</font>);
range-&gt;push_back(<font color="#0000A0">5</font>);
<B>return</B> boost::make_shared_container_range(range);
}
<B>int</B> main() {
function_iterator i,end;
boost::tie(i,end) = return_range();
std::copy(i,end,std::ostream_iterator&lt;<B>int</B>&gt;(std::cout,<font color="#0000FF">","</font>));
std::cout.put(<font color="#0000FF">'\n'</font>);
<B>return</B> <font color="#0000A0">0</font>;
}
</PRE>
Though the <tt>range</tt> object only lives for the duration of the
<tt>return_range</tt> call, the reference counted
<tt>std::vector</tt> will live until <tt>i</tt> and <tt>end</tt>
are both destroyed. The output from this example is the same as
the previous two.
<hr>
<!-- hhmts start -->
Last modified: Wed Sep 4 15:52:17 EST 2002
<!-- hhmts end -->
<p><EFBFBD> Copyright Ronald Garcia 2002. Permission to copy, use,
modify, sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &quot;as is&quot;
without express or implied warranty, and with no claim as to its suitability for
any purpose.</p>
</body>
</html>

View File

@@ -0,0 +1,42 @@
// (C) Copyright Ronald Garcia 2002. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
#include "boost/shared_container_iterator.hpp"
#include "boost/shared_ptr.hpp"
#include <algorithm>
#include <iostream>
#include <vector>
typedef boost::shared_container_iterator_generator< std::vector<int> >::type
iterator;
void set_range(iterator& i, iterator& end) {
boost::shared_ptr< std::vector<int> > ints(new std::vector<int>());
ints->push_back(0);
ints->push_back(1);
ints->push_back(2);
ints->push_back(3);
ints->push_back(4);
ints->push_back(5);
i = iterator(ints->begin(),ints);
end = iterator(ints->end(),ints);
}
int main() {
iterator i,end;
set_range(i,end);
std::copy(i,end,std::ostream_iterator<int>(std::cout,","));
std::cout.put('\n');
return 0;
}

View File

@@ -0,0 +1,42 @@
// (C) Copyright Ronald Garcia 2002. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
#include "boost/shared_container_iterator.hpp"
#include "boost/shared_ptr.hpp"
#include <algorithm>
#include <iterator>
#include <iostream>
#include <vector>
template <typename Iterator>
void print_range_nl (Iterator begin, Iterator end) {
typedef typename std::iterator_traits<Iterator>::value_type val;
std::copy(begin,end,std::ostream_iterator<val>(std::cout,","));
std::cout.put('\n');
}
int main() {
typedef boost::shared_ptr< std::vector<int> > ints_t;
{
ints_t ints(new std::vector<int>());
ints->push_back(0);
ints->push_back(1);
ints->push_back(2);
ints->push_back(3);
ints->push_back(4);
ints->push_back(5);
print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints),
boost::make_shared_container_iterator(ints->end(),ints));
}
return 0;
}

View File

@@ -0,0 +1,41 @@
// (C) Copyright Ronald Garcia 2002. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
#include "boost/shared_container_iterator.hpp"
#include "boost/shared_ptr.hpp"
#include "boost/tuple/tuple.hpp" // for boost::tie
#include <algorithm> // for std::copy
#include <iostream>
#include <vector>
typedef boost::shared_container_iterator_generator< std::vector<int> >::type
function_iterator;
std::pair<function_iterator,function_iterator>
return_range() {
boost::shared_ptr< std::vector<int> > range(new std::vector<int>());
range->push_back(0);
range->push_back(1);
range->push_back(2);
range->push_back(3);
range->push_back(4);
range->push_back(5);
return boost::make_shared_container_range(range);
}
int main() {
function_iterator i,end;
boost::tie(i,end) = return_range();
std::copy(i,end,std::ostream_iterator<int>(std::cout,","));
std::cout.put('\n');
return 0;
}

60
throw_exception.html Normal file
View File

@@ -0,0 +1,60 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Boost: throw_exception.hpp documentation</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
<table border="0" width="100%">
<tr>
<td width="277">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277" height="86">
</td>
<td align="middle">
<h1>throw_exception.hpp</h1>
</td>
</tr>
<tr>
<td colspan="2" height="64">&nbsp;</td>
</tr>
</table>
<p>
The header <STRONG>&lt;boost/throw_exception.hpp&gt;</STRONG> defines the
helper function <STRONG>boost::throw_exception</STRONG>. It is intended to be
used in Boost libraries that need to throw exceptions, but support
configurations and platforms where exceptions aren't available, as indicated by
the presence of the <STRONG>BOOST_NO_EXCEPTIONS</STRONG> <A href="../config/config.htm#macro_ref">
configuration macro</A>.
</p>
<P>When <STRONG>BOOST_NO_EXCEPTIONS</STRONG> is not defined, <tt>boost::throw_exception(e)</tt>
is equivalent to <tt>throw e</tt>. Otherwise, the function is left undefined,
and the user is expected to supply an appropriate definition. Callers of <tt>throw_exception</tt>
are allowed to assume that the function never returns; therefore, if the
user-defined <tt>throw_exception</tt> returns, the behavior is undefined.</P>
<h3><a name="Synopsis">Synopsis</a></h3>
<pre>
namespace boost
{
#ifdef BOOST_NO_EXCEPTIONS
void throw_exception(std::exception const &amp; e); // user defined
#else
template&lt;class E&gt; void throw_exception(E const &amp; e)
{
throw e;
}
#endif
}
</pre>
<p><br>
<small>Copyright <20> 2002 by Peter Dimov. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears in
all copies. This document is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.</small></p>
</body>
</html>

View File

@@ -24,8 +24,12 @@
</H1> </H1>
<h3> <h3>
[tie has been deprecated.&nbsp; Its functionality is supplied by the Boost [This version of tie has been removed from the utility.hpp
Tuples Library.]</h3> header.&nbsp; There is a new, more general version of <a
href="../tuple/doc/tuple_users_guide.html#tiers">tie</a> in the Boost
Tuples Library. The more general version handles an (almost) arbitrary
number of arguments, instead of just two. The version in utility.hpp
had to be removed to avoid name clashes.]</h3>
<PRE> <PRE>
template &lt;class A, class B&gt; template &lt;class A, class B&gt;
tied&lt;A,B&gt; tie(A&amp; a, B&amp; b); tied&lt;A,B&gt; tie(A&amp; a, B&amp; b);
@@ -126,7 +130,7 @@ The output is:
<TABLE> <TABLE>
<TR valign=top> <TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD> <TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF=file:///c:/boost/site/people/jeremy_siek.htm>Jeremy Siek</A>, <a HREF="../../people/jeremy_siek.htm">Jeremy Siek</a>,
Univ.of Notre Dame (<A Univ.of Notre Dame (<A
HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)<br> HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)<br>
<A HREF=http://www.lsc.nd.edu/~llee1>Lie-Quan Lee</A>, Univ.of Notre Dame (<A HREF="mailto:llee1@lsc.nd.edu">llee1@lsc.nd.edu</A>)<br> <A HREF=http://www.lsc.nd.edu/~llee1>Lie-Quan Lee</A>, Univ.of Notre Dame (<A HREF="mailto:llee1@lsc.nd.edu">llee1@lsc.nd.edu</A>)<br>

View File

@@ -14,19 +14,22 @@
// //
// 3 successfully inserted. // 3 successfully inserted.
// 9 was already in the set. // 9 was already in the set.
// There were 2 occurances of 4. // There were 2 occurrences of 4.
#include <set> #include <set>
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <boost/utility.hpp> #include <iterator> // std::distance
// Note: tie() use to live in boost/utility.hpp, but
// not it is part of the more general Boost Tuple Library.
#include <boost/tuple/tuple.hpp>
int int
main(int, char*[]) main(int, char*[])
{ {
{ {
typedef std::set<int> SetT; typedef std::set<int> SetT;
SetT::iterator i, end; SetT::iterator i;
bool inserted; bool inserted;
int vals[5] = { 5, 2, 4, 9, 1 }; int vals[5] = { 5, 2, 4, 9, 1 };
@@ -53,7 +56,7 @@ main(int, char*[])
boost::tie(i,end) = std::equal_range(vals, vals + 6, 4); boost::tie(i,end) = std::equal_range(vals, vals + 6, 4);
std::cout << "There were " << std::distance(i,end) std::cout << "There were " << std::distance(i,end)
<< " occurances of " << *i << "." << std::endl; << " occurrences of " << *i << "." << std::endl;
// Footnote: of course one would normally just use std::count() // Footnote: of course one would normally just use std::count()
// to get this information, but that would spoil the example :) // to get this information, but that would spoil the example :)
} }

View File

@@ -19,7 +19,7 @@ Defined in header
<p> <p>
The transform iterator adaptor augments an iterator by applying some The transform iterator adaptor augments an iterator by applying some
function object to the result of dereferencing the iterator. Another function object to the result of dereferencing the iterator. In other
words, the <tt>operator*</tt> of the transform iterator first words, the <tt>operator*</tt> of the transform iterator first
dereferences the base iterator, passes the result of this to the dereferences the base iterator, passes the result of this to the
function object, and then returns the result. The following function object, and then returns the result. The following
@@ -211,7 +211,7 @@ iterator always returns by-value.
<hr> <hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->29 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14896" --></p> <p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" --></p>
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use, <p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
modify, sell and distribute this document is granted provided this copyright modify, sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &quot;as is&quot; notice appears in all copies. This document is provided &quot;as is&quot;

View File

@@ -1,146 +1,137 @@
<html> <html>
<head>
<head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <title>Header boost/utility.hpp Documentation</title>
<title>Header boost/utility.hpp Documentation</title> </head>
</head> <body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" WIDTH="277" HEIGHT="86">Header
<body bgcolor="#FFFFFF" text="#000000"> <a href="../../boost/utility.hpp">boost/utility.hpp</a></h1>
<p>The entire contents of the header <code><a href="../../boost/utility.hpp">&lt;boost/utility.hpp&gt;</a></code>
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" WIDTH="277" HEIGHT="86">Header
<a href="../../boost/utility.hpp">boost/utility.hpp</a></h1>
<p>The entire contents of the header <code><a href="../../boost/utility.hpp">&lt;boost/utility.hpp&gt;</a></code>
are in <code>namespace boost</code>.</p> are in <code>namespace boost</code>.</p>
<h2>Contents</h2>
<h2>Contents</h2> <ul>
<li>
<ul> Class templates supporting the <a href="base_from_member.html">base-from-member
<li>Function templates <a href="#checked_delete">checked_delete() and idiom</a></li>
<li>
Function templates <a href="#checked_delete">checked_delete() and
checked_array_delete()</a></li> checked_array_delete()</a></li>
<li>Function templates <a href="#functions next">next() and prior()</a></li> <li>
<li>Class <a href="#Class noncopyable">noncopyable</a></li> Function templates <a href="#functions_next_prior">next() and prior()</a></li>
<li>Function template <a href="tie.html">tie()</a> and supporting class tied.</li> <li>
</ul> Class <a href="#Class_noncopyable">noncopyable</a></li>
<h2> Function templates <a name="checked_delete">checked_delete</a>() and <li>
checked_array_delete()</h2> Function template <a href="#addressof">addressof()</a></li>
<li>
<p>Deletion of a pointer to an incomplete type is an unsafe programming practice Function template <a href="tie.html">tie()</a> and supporting class tied.</li>
because there is no way for the compiler to verify that the destructor is indeed </ul>
trivial.&nbsp; The checked_delete() and checked_array_delete() function <h2>
templates simply <b>delete</b> or <b>delete[]</b> their argument, but also Function templates <a name="checked_delete">checked_delete</a>() and
require that their argument be a complete type.&nbsp; They issue an appropriate checked_array_delete()</h2>
compiler error diagnostic if that requirement is not met.&nbsp; A typical <p>See <a href="checked_delete.html">separate documentation</a>.</p>
implementation is shown; other implementations may vary:</p> <h2>
<a name="functions_next_prior">Function</a> templates next() and prior()</h2>
<pre> template&lt; typename T &gt; <p>Certain data types, such as the C++ Standard Library's forward and bidirectional
inline void checked_delete(T const volatile * x) iterators, do not provide addition and subtraction via operator+() or
{ operator-().&nbsp; This means that non-modifying computation of the next or
BOOST_STATIC_ASSERT( sizeof(T) ); // assert type complete at point prior value requires a temporary, even though operator++() or operator--() is
// of instantiation provided.&nbsp; It also means that writing code like <code>itr+1</code> inside
delete x; a template restricts the iterator category to random access iterators.</p>
} <p>The next() and prior() functions provide a simple way around these problems:</p>
<blockquote>
template&lt; typename T &gt; <pre>template &lt;class T&gt;
inline void checked_array_delete(T const volatile * x)
{
BOOST_STATIC_ASSERT( sizeof(T) ); // assert type complete at point
// of instantiation
delete [] x;
}</pre>
<p>Contributed by Beman Dawes, based on a suggestion from Dave Abrahams,
generalizing an idea from Vladimir Prus, with comments from Rainer Deyke, John
Maddock, and others.</p>
<h3>Background</h3>
<p>The C++ Standard specifies that delete on a pointer to an incomplete types is
undefined behavior if the type has a non-trivial destructor in&nbsp; [expr.delete]
5.3.5 paragraph.&nbsp; No diagnostic is required.&nbsp; Some but not all
compilers issue warnings if the type is incomplete at point of deletion.</p>
<h2> <a name="functions next">Function</a> templates next() and prior()</h2>
<p>Certain data types, such as the C++ Standard Library's forward and
bidirectional iterators, do not provide addition and subtraction via operator+()
or operator-().&nbsp; This means that non-modifying computation of the next or
prior value requires a temporary, even though operator++() or operator--() is
provided.&nbsp; It also means that writing code like <code>itr+1</code> inside a
template restricts the iterator category to random access iterators.</p>
<p>The next() and prior() functions provide a simple way around these problems:</p>
<blockquote>
<pre>template &lt;class T&gt;
T next(T x) { return ++x; } T next(T x) { return ++x; }
template &lt;class X&gt; template &lt;class X&gt;
T prior(T x) { return --x; }</pre> T prior(T x) { return --x; }</pre>
</blockquote>
</blockquote> <p>Usage is simple:</p>
<blockquote>
<p>Usage is simple:</p> <pre>const std::list&lt;T&gt;::iterator p = get_some_iterator();
<blockquote>
<pre>const std::list&lt;T&gt;::iterator p = get_some_iterator();
const std::list&lt;T&gt;::iterator prev = boost::prior(p);</pre> const std::list&lt;T&gt;::iterator prev = boost::prior(p);</pre>
</blockquote>
</blockquote> <p>Contributed by <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>.</p>
<h2><a name="Class_noncopyable">Class noncopyable</a></h2>
<p>Contributed by <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>.</p> <p>Class <strong>noncopyable</strong> is a base class.&nbsp; Derive your own class
from <strong>noncopyable</strong> when you want to prohibit copy construction
<h2><a name="Class noncopyable">Class noncopyable</a></h2> and copy assignment.</p>
<p>Some objects, particularly those which hold complex resources like files or
<p>Class <strong>noncopyable</strong> is a base class.&nbsp; Derive your own class from <strong>noncopyable</strong> network connections, have no sensible copy semantics.&nbsp; Sometimes there are
when you want to prohibit copy construction and copy assignment.</p> possible copy semantics, but these would be of very limited usefulness and be
very difficult to implement correctly.&nbsp; Sometimes you're implementing a
<p>Some objects, particularly those which hold complex resources like files or class that doesn't need to be copied just yet and you don't want to take the
network connections, have no sensible copy semantics.&nbsp; Sometimes there are time to write the appropriate functions.&nbsp; Deriving from <b>noncopyable</b>
possible copy semantics, but these would be of very limited usefulness and be will prevent the otherwise implicitly-generated functions (which don't have the
very difficult to implement correctly.&nbsp; Sometimes you're implementing a class that doesn't need to be copied proper semantics) from becoming a trap for other programmers.</p>
just yet and you don't want to take the time to write the appropriate functions.&nbsp; <p>The traditional way to deal with these is to declare a private copy constructor
Deriving from <b> noncopyable</b> will prevent the otherwise implicitly-generated and copy assignment, and then document why this is done.&nbsp; But deriving
functions (which don't have the proper semantics) from becoming a trap for other programmers.</p> from <b>noncopyable</b> is simpler and clearer, and doesn't require additional
documentation.</p>
<p>The traditional way to deal with these is to declare a private copy constructor and copy assignment, and then <p>The program <a href="noncopyable_test.cpp">noncopyable_test.cpp</a> can be used
document why this is done.&nbsp; But deriving from <b>noncopyable</b> is simpler to verify class <b>noncopyable</b> works as expected. It has have been run
and clearer, and doesn't require additional documentation.</p> successfully under GCC 2.95, Metrowerks CodeWarrior 5.0, and Microsoft Visual
C++ 6.0 sp 3.</p>
<p>The program <a href="noncopyable_test.cpp">noncopyable_test.cpp</a> can be <p>Contributed by <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>.</p>
used to verify class <b>noncopyable</b> works as expected. It has have been run successfully under <h3>Example</h3>
GCC 2.95, Metrowerks <blockquote>
CodeWarrior 5.0, and Microsoft Visual C++ 6.0 sp 3.</p>
<p>Contributed by <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>.</p>
<h3>Example</h3>
<blockquote>
<pre>// inside one of your own headers ... <pre>// inside one of your own headers ...
#include &lt;boost/utility.hpp&gt; #include &lt;boost/utility.hpp&gt;
class ResourceLadenFileSystem : boost::noncopyable { class ResourceLadenFileSystem : boost::noncopyable {
...</pre> ...</pre>
</blockquote> </blockquote>
<h3>Rationale</h3>
<p>Class noncopyable has protected constructor and destructor members to emphasize
that it is to be used only as a base class.&nbsp; Dave Abrahams notes concern
about the effect on compiler optimization of adding (even trivial inline)
destructor declarations. He says &quot;Probably this concern is misplaced,
because noncopyable will be used mostly for classes which own resources and
thus have non-trivial destruction semantics.&quot;</p>
<h2><a name="addressof">Function template addressof()</a></h2>
<p>Function <strong>addressof()</strong> returns the address of an object.</p>
<blockquote>
<pre>template &lt;typename T&gt; inline T* addressof(T& v);
template &lt;typename T&gt; inline const T* addressof(const T& v);
template &lt;typename T&gt; inline volatile T* addressof(volatile T& v);
template &lt;typename T&gt; inline const volatile T* addressof(const volatile T& v);
</pre>
</blockquote>
<p>C++ allows programmers to replace the unary <strong>operator&()</strong> class
member used to get the address of an object. Getting the real address of an
object requires ugly casting tricks to avoid invoking the overloaded <strong>operator&()</strong>.
Function <strong>addressof()</strong> provides a wrapper around the necessary
code to make it easy to get an object's real address.
</p>
<p>The program <a href="addressof_test.cpp">addressof_test.cpp</a> can be used to
verify that <b>addressof()</b> works as expected.</p>
<p>Contributed by Brad King based on ideas from discussion with Doug Gregor.</p>
<h3>Example</h3>
<blockquote>
<pre>#include &lt;boost/utility.hpp&gt;
<h3>Rationale</h3> struct useless_type {};
<p>Class noncopyable has protected constructor and destructor members to class nonaddressable {
emphasize that it is to be used only as a base class.&nbsp; Dave Abrahams notes useless_type operator&() const;
concern about the effect on compiler optimization of adding (even trivial inline) };
destructor declarations. He says &quot;Probably this concern is misplaced, because
noncopyable will be used mostly for classes which own resources and thus have non-trivial destruction semantics.&quot;</p> void f() {
<h2>Function template tie()</h2> nonaddressable x;
<p>See <a href="tie.html">separate documentation</a>.</p> nonaddressable* xp = boost::addressof(x);
<hr> // nonaddressable* xpe = &amp;x; /* error */
<p>Revised&nbsp; <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan }</pre>
-->22 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13960" </blockquote>
<h2>Class templates for the Base-from-Member Idiom</h2>
<p>See <a href="base_from_member.html">separate documentation</a>.</p>
<h2>Function template tie()</h2>
<p>See <a href="tie.html">separate documentation</a>.</p>
<hr>
<p>Revised&nbsp; <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan
-->09 January, 2003<!--webbot bot="Timestamp" endspan i-checksum="38582"
--> -->
</p> </p>
<p><EFBFBD> Copyright boost.org 1999. Permission to copy, use, modify, sell and <p><EFBFBD> Copyright boost.org 1999-2002. Permission to copy, use, modify, sell and distribute
distribute this document is granted provided this copyright notice appears in this document is granted provided this copyright notice appears in all copies.
all copies. This document is provided &quot;as is&quot; without express or This document is provided &quot;as is&quot; without express or implied
implied warranty, and with no claim as to its suitability for any purpose.</p> warranty, and with no claim as to its suitability for any purpose.</p>
</body> </body>
</html> </html>

219
value_init.htm Normal file
View File

@@ -0,0 +1,219 @@
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<title>value_initialized</title>
</head>
<body vlink="#800080" link="#0000ff" text="#000000" bgcolor="#ffffff">
<h2><img src="../../c++boost.gif" width="276" height="86">
Header &lt;<a href="../../boost/utility/value_init.hpp">boost/utility/value_init.hpp</a>&gt;
</h2>
<h2>Contents</h2>
<dl>
<dt><a href="#intro">Rationale</a></dt>
<dt><a href="#rationale">Introduction</a></dt>
</dl>
<ul>
<li><a href="#valueinit">value-initialization</a></li>
<li><a href="#valueinitsyn">value-initialization syntax</a></li>
</ul>
<dl class="page-index">
<dt><a href="#types">Types</a></dt>
</dl>
<ul>
<li><a href="#val_init"><code>value_initialized&lt;&gt;</code></a></li>
</ul>
<a href="#acknowledgements">Acknowledgements</a><br>
<br>
<hr>
<h2><a name="rationale"></a>Rationale</h2>
<p>Constructing and initializing objects in a generic way is difficult in
C++. The problem is that there are several different rules that apply
for initialization. Depending on the type, the value of a newly constructed
object can be zero-initialized (logically 0), default-constructed (using
the default constructor), or indeterminate. When writing generic code,
this problem must be addressed. <code>value_initialized</code> provides
a solution with consistent syntax for value initialization of scalar,
union and class types. <br>
</p>
<h2><a name="into"></a>Introduction</h2>
<p>The C++ standard [<a href="#references">1</a>] contains the definitions
of <code>zero-initialization</code> and <code>default-initialization</code>.
Informally, zero-initialization means that the object is given the initial
value 0 (converted to the type) and default-initialization means that
POD [<a href="#references">2</a>] types are zero-initialized, while class
types are initialized with their corresponding default constructors. A
<i>declaration</i> can contain an <i>initializer</i>, which specifies the
object's initial value. The initializer can be just '()', which states that
the object shall be default-initialized (but see below). However, if a <i>declaration</i>
has no <i>initializer</i> and it is of a non-<code>const</code>, non-<code>static</code>
POD type, the initial value is indeterminate:<cite>(see &sect;8.5 for the
accurate definitions).</cite></p>
<pre>int x ; // no initializer. x value is indeterminate.<br>std::string s ; // no initializer, s is default-constructed.<br><br>int y = int() ; <br>// y is initialized using copy-initialization<br>// but the temporary uses an empty set of parentheses as the initializer,<br>// so it is default-constructed.<br>// A default constructed POD type is zero-initialized,<br>// therefore, y == 0.<br><br>void foo ( std::string ) ;<br>foo ( std::string() ) ; <br>// the temporary string is default constructed <br>// as indicated by the initializer () </pre>
<h3><a name="valueinit">value-initialization</a></h3>
<p>The first <a
href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/cwg_defects.html">Technical
Corrigendum for the C++ Standard</a> (TC1), whose draft was released to
the public in November 2001, introduced <a
href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/cwg_defects.html#178">Core
Issue 178</a> (among many other issues, of course).</p>
<p> That issue introduced the new concept of <code>value-initialization</code>
(it also fixed the wording for zero-initialization). Informally, value-initialization
is similar to default-initialization with the exception that in some cases
non-static data members and base class sub-objects are also value-initialized.
The difference is that an object that is value-initialized won't have
(or at least is less likely to have) indeterminate values for data members
and base class sub-objects; unlike the case of an object default constructed.
(see Core Issue 178 for a normative description).</p>
<p>In order to specify value-initialization of an object we need to use the
empty-set initializer: (). </p>
<p><i>(but recall that the current C++ Standard states that '()' invokes default-initialization,
not value-initialization)</i></p>
<p>As before, a declaration with no intializer specifies default-initialization,
and a declaration with a non-empty initializer specifies copy (=xxx) or
direct (xxx) initialization. </p>
<pre>template&lt;class T&gt; void eat(T);<br>int x ; // indeterminate initial value.<br>std::string s; // default-initialized.<br>eat ( int() ) ; // value-initialized<br>eat ( std::string() ) ; // value-initialied</pre>
<h4><a name="valueinitsyn">value-initialization</a> syntax</h4>
<p>Value initialization is specified using (). However, the empty set of
parentheses is not permitted by the syntax of initializers because it is
parsed as the declaration of a function taking no arguments: </p>
<pre>int x() ; // declares function int(*)()<br>int y ( int() ) ; // decalares function int(*)( int(*)() )</pre>
<p>Thus, the empty () must be put in some other initialization context.</p>
<p>One alternative is to use copy-initialization syntax:</p>
<pre>int x = int() ;</pre>
<p>This works perfectly fine for POD types. But for non-POD class types,
copy-initialization searches for a suitable constructor, which could be,
for instance, the copy-constructor (it also searches for a suitable conversion
sequence but this doesn't apply in this context). For an arbitrary unknown
type, using this syntax may not have the value-initialization effect intended
because we don't know if a copy from a default constructed object is exactly
the same as a default constructed object, and the compiler is allowed (in
some cases), but never required to, optimize the copy away.</p>
<p>One possible generic solution is to use value-initialization of a non static
data member:</p>
<pre>template&lt;class T&gt; <br>struct W <br>{<br> // value-initialization of 'data' here.<br> W() : data() {}<br> T data ;<br>} ;<br>W&lt;int&gt; w ;<br>// w.data is value-initialized for any type. </pre>
<p><code>This is the solution supplied by the value_initialized&lt;&gt; template
class.</code></p>
<h2><a name="types"></a>Types</h2>
<h2><a name="val_init"><code>template class value_initialized&lt;T&gt;</code></a></h2>
<pre>namespace boost {<br><br>template&lt;class T&gt;<br>class value_initialized<br>{<br> public :<br> value_initialized() : x() {}<br> operator T&amp;() const { return x ; }<br> T&amp; data() const { return x ; }<br><br> private :<br> <i>impll-defined</i> x ;<br>} ;<br><br>template&lt;class T&gt;<br>T const&amp; get ( value_initialized&lt;T&gt; const&amp; x )<br>{<br> return x.data() ;<br>}<br><br>template&lt;class T&gt;<br>T&amp; get ( value_initialized&lt;T&gt;&amp; x )<br>{<br> return x.data() ;<br>}<br><br>} // namespace boost<br></pre>
<p>An object of this template class is a <code>T</code>-wrapper convertible
to <code>'T&amp;'</code> whose wrapped object (data member of type <code>T</code>)
is <a href="#valueinit">value-initialized</a> upon default-initialization
of this wrapper class: </p>
<pre>int zero = 0 ;<br>value_initialized&lt;int&gt; x ;<br>assert ( x == zero ) ;<br><br>std::string def ;<br>value_initialized&lt; std::string &gt; y ;<br>assert ( y == def ) ;<br></pre>
<p>The purpose of this wrapper is to provide a consistent syntax for value
initialization of scalar, union and class types (POD and non-POD) since
the correct syntax for value initialization varies (see <a
href="#valueinitsyn">value-initialization syntax</a>)</p>
<p>The wrapped object can be accessed either through the conversion operator
<code>T&amp;</code>, the member function <code>data()</code>, or the
non-member function <code>get()</code>: </p>
<pre>void watch(int);<br>value_initialized&lt;int&gt; x;<br><br>watch(x) ; // operator T&amp; used.<br>watch(x.data());<br>watch( get(x) ) // function get() used</pre>
<p>Both <code>const</code> and non-<code>const</code> objects can be wrapped.
Mutable objects can be modified directly from within the wrapper but constant
objects cannot:</p>
<pre>value_initialized&lt;int&gt; x ; <br>static_cast&lt;int&amp;&gt;(x) = 1 ; // OK<br>get(x) = 1 ; // OK<br><br>value_initialized&lt;int const&gt; y ; <br>static_cast&lt;int&amp;&gt;(y) = 1 ; // ERROR: cannot cast to int&amp;<br>static_cast&lt;int const&amp;&gt;(y) = 1 ; // ERROR: cannot modify a const value<br>get(y) = 1 ; // ERROR: cannot modify a const value</pre>
<h3>Warning:</h3>
<p>Both the conversion operator and the <code>data()</code> member function
are <code>const</code> in order to allow access to the wrapped object
from a constant wrapper:</p>
<pre>void foo(int);<br>value_initialized&lt;int&gt; const x ;<br>foo(x);<br></pre>
<p>But notice that this conversion operator is to <code>T&amp;</code> although
it is itself <code>const</code>. As a consequence, if <code>T</code> is
a non-<code>const</code> type, you can modify the wrapped object even from
within a constant wrapper:</p>
<pre>value_initialized&lt;int&gt; const x_c ;<br>int&amp; xr = x_c ; // OK, conversion to int&amp; available even though x_c is itself const.<br>xr = 2 ; </pre>
<p>The reason for this obscure behavior is that some commonly used compilers
just don't accept the following valid code:</p>
<pre>struct X<br>{<br> operator int&amp;() ;<br> operator int const&amp;() const ; <br>};<br>X x ;<br>(x == 1 ) ; // ERROR HERE!</pre>
<p>These compilers complain about ambiguity between the conversion operators.
This complaint is incorrect, but the only workaround that I know of is
to provide only one of them, which leads to the obscure behavior just explained.<br>
</p>
<h3>Recommended practice: The non-member get() idiom</h3>
<p>The obscure behavior of being able to modify a non-<code>const</code>
wrapped object from within a constant wrapper can be avoided if access to
the wrapped object is always performed with the <code>get()</code> idiom:</p>
<pre>value_initialized&lt;int&gt; x ;<br>get(x) = 1 ; // OK<br><br>value_initialized&lt;int const&gt; cx ;<br>get(x) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized&lt;int&gt; const x_c ;<br>get(x_c) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized&lt;int const&gt; const cx_c ;<br>get(cx_c) = 1 ; // ERROR: Cannot modify a const object<br></pre>
<h3><a name="references">References</a></h3>
[1] The C++ Standard, ISO/IEC 14882:98 <br>
[2] Plain Old Data
<h3><a name="acknowledgements"></a>Acknowledgements</h3>
value_initialized was developed by Fernando Cacciola, with help and
suggestions from David Abrahams and Darin Adler.<br>
Special thanks to Bj<42>rn Karlsson who carefully edited and completed this documentation.
<pre>&nbsp;</pre>
<hr>
<p>Revised 19 September 2002</p>
<p>&copy; Copyright boost.org 2002. Permission to copy, use, modify, sell
and distribute this document is granted provided this copyright notice appears
in all copies. This document is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.</p>
<p>Developed by <a href="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</a>,
the latest version of this file can be found at <a
href="http://www.boost.org">www.boost.org</a>, and the boost discussion list
at <a href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.
</p>
<br>
<br>
</body>
</html>

119
value_init_test.cpp Normal file
View File

@@ -0,0 +1,119 @@
// (C) 2002, Fernando Luis Cacciola Carballal.
//
// This material is provided "as is", with absolutely no warranty expressed
// or implied. Any use is at your own risk.
//
// Permission to use or copy this software for any purpose is hereby granted
// without fee, provided the above notices are retained on all copies.
// Permission to modify the code and to distribute modified code is granted,
// provided the above notices are retained, and a notice that the code was
// modified is included with the above copyright notice.
//
// Test program for "boost/utility/value_init.hpp"
//
// Initial: 21 Agu 2002
#include <iostream>
#include <string>
#include "boost/utility/value_init.hpp"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#define BOOST_INCLUDE_MAIN
#include "boost/test/test_tools.hpp"
//
// Sample POD type
//
struct POD
{
POD () : c(0), i(0), f(0) {}
POD ( char c_, int i_, float f_ ) : c(c_), i(i_), f(f_) {}
friend std::ostream& operator << ( std::ostream& os, POD const& pod )
{ return os << '(' << pod.c << ',' << pod.i << ',' << pod.f << ')' ; }
friend bool operator == ( POD const& lhs, POD const& rhs )
{ return lhs.f == rhs.f && lhs.c == rhs.c && lhs.i == rhs.i ; }
float f;
char c;
int i;
} ;
//
// Sample non POD type
//
struct NonPODBase
{
virtual ~NonPODBase() {}
} ;
struct NonPOD : NonPODBase
{
NonPOD () : id() {}
NonPOD ( std::string const& id_) : id(id_) {}
friend std::ostream& operator << ( std::ostream& os, NonPOD const& npod )
{ return os << '(' << npod.id << ')' ; }
friend bool operator == ( NonPOD const& lhs, NonPOD const& rhs )
{ return lhs.id == rhs.id ; }
std::string id ;
} ;
template<class T>
void test ( T const& y, T const& z )
{
boost::value_initialized<T> x ;
BOOST_TEST ( y == x ) ;
BOOST_TEST ( y == get(x) ) ;
static_cast<T&>(x) = z ;
get(x) = z ;
BOOST_TEST ( x == z ) ;
boost::value_initialized<T> const x_c ;
BOOST_TEST ( y == x_c ) ;
BOOST_TEST ( y == get(x_c) ) ;
static_cast<T&>(x_c) = z ;
BOOST_TEST ( x_c == z ) ;
#ifdef PRODUCE_ERROR_1
get(x_c) = z ; // this should produce an ERROR
#endif
boost::value_initialized<T const> cx ;
BOOST_TEST ( y == cx ) ;
BOOST_TEST ( y == get(cx) ) ;
#ifdef PRODUCE_ERROR_2
get(cx) = z ; // this should produce an ERROR
#endif
boost::value_initialized<T const> const cx_c ;
BOOST_TEST ( y == cx_c ) ;
BOOST_TEST ( y == get(cx_c) ) ;
#ifdef PRODUCE_ERROR_3
get(cx_c) = z ; // this should produce an ERROR
#endif
}
int test_main(int, char **)
{
test( 0,1234 ) ;
test( 0.0,12.34 ) ;
test( POD(0,0,0.0), POD('a',1234,56.78) ) ;
test( NonPOD( std::string() ), NonPOD( std::string("something") ) ) ;
return 0;
}
unsigned int expected_failures = 0;