Compare commits

...

143 Commits

Author SHA1 Message Date
7779f95aa3 Release 1.55.0
[SVN r86621]
2013-11-11 19:45:21 +00:00
65d9a78735 Regnerated string_ref docs. Fixed incorrect example. Fixes #8002
[SVN r86488]
2013-10-27 21:05:17 +00:00
e33f8b0055 Merged new added components from trunk. Merged other sublibraries which tests are passing for a long time as well.
[SVN r85613]
2013-09-08 19:28:44 +00:00
b051dd665b [utility] Fixes to value_init docs.
[SVN r85335]
2013-08-13 21:39:57 +00:00
b813232bba Merged recent changes from trunk.
[SVN r85088]
2013-07-20 17:17:10 +00:00
e02523e286 Merged changes from trunk. Fixes operator<< handling of width specification.
[SVN r84674]
2013-06-07 17:33:25 +00:00
0d605befd4 Merge bug fix in test to release
[SVN r84449]
2013-05-23 18:38:20 +00:00
4080fe22e3 utility/noncopyable : fix #6578.
[SVN r83869]
2013-04-13 13:49:52 +00:00
2eda3f5299 Utility/address_off: fix #7079.
[SVN r83524]
2013-03-23 01:44:06 +00:00
1ab9131bca Utility: merge [68982] to fix #5213.
[SVN r83427]
2013-03-14 17:35:42 +00:00
d51799518b merge [82901], [82902], and [83147] from trunk
[SVN r83403]
2013-03-10 21:18:49 +00:00
f9540f360c merge [82960] to release, fixes #7663
[SVN r83381]
2013-03-09 22:55:05 +00:00
c1fdb477c1 Merged boost::algorithm::gather and updated tests for Utility, Algorithm and Utility libraries
[SVN r83154]
2013-02-25 18:43:26 +00:00
1b2cd6378b Merge doc typo; Fixes #8002
[SVN r82821]
2013-02-11 16:22:32 +00:00
9383bbc283 Merge typo in docs; Fixes 7974
[SVN r82819]
2013-02-11 16:10:24 +00:00
1730c1319b Merge string_ref doc changes to release
[SVN r82490]
2013-01-14 16:34:16 +00:00
856b01240a Merge string_ref to release
[SVN r82047]
2012-12-17 14:36:31 +00:00
611395441e Merge deprecated macro change for Boost.Utility to release; no functionality change
[SVN r81855]
2012-12-11 16:41:54 +00:00
b35ef27b35 add missing close tag
[SVN r80835]
2012-10-03 23:09:58 +00:00
124f4ea879 result_of: merge [80732] from trunk
[SVN r80746]
2012-09-28 22:21:32 +00:00
0f43c44e97 result_of: merge [80636],[80654],[80655],[80656],[80712] from trunk
[SVN r80713]
2012-09-26 18:52:08 +00:00
7d8353f46a result_of: merge [80445], [80452], [80535], [80550], [80605], [80608] from trunk
[SVN r80621]
2012-09-21 18:49:46 +00:00
1920623a4f merged [80550], allowing users to force result_of to use decltype
[SVN r80551]
2012-09-17 00:16:36 +00:00
c0cca9e8cc Merge changes from Trunk.
Fixes #5790.

[SVN r80433]
2012-09-07 08:49:11 +00:00
d63444f22e merge [77702] to release, fixes #6755
[SVN r80359]
2012-09-02 03:42:37 +00:00
1f23425baa result_of limit bumped to 16, merge [71769] from trunk
[SVN r80358]
2012-09-02 03:29:41 +00:00
a89b0101fc boost::result_of uses decltype on compilers that implement N3276, merges [77905], [78195], [80352] from trunk
[SVN r80355]
2012-09-01 23:12:32 +00:00
fb2d391928 Merge documentation build fix from trunk.
[SVN r78888]
2012-06-11 07:23:17 +00:00
ad5cf8cf08 Update Jamfiles and build scripts for PDF generation.
Set local_function image DPI's for better PDF builds.

[SVN r78849]
2012-06-07 16:47:33 +00:00
2fc827ad23 Utility/declval: update history.
[SVN r78730]
2012-05-28 19:00:53 +00:00
88e7d86270 Marked some expected failures for release regression test compilers. Renamed a local function internal template parameter from Bn to Bindn (because B0 is defined as a macro from a Linux header to represent a baudrate). Added itdentity_type.hpp to utility.hpp. Made reference data members of LocalFunction Addable static (because they are not set in the constructor).
[SVN r78659]
2012-05-26 21:17:03 +00:00
6b9f0103d5 Merged ScopeExit (improved), LocalFunction (new), Functional/OverloadedFunction (new), and Utility/IdentityType (new) from trunk into release branch.
[SVN r78564]
2012-05-24 01:35:04 +00:00
7aa68731b4 Utility: Fix #6570
[SVN r77699]
2012-04-01 20:16:57 +00:00
ef0f82f62b Added Utility/IdentityType docs, tests, and examples to libs/.
[SVN r77029]
2012-02-15 01:16:00 +00:00
9a16aaa2b9 Added LocalFunction and Utility/IdentityType source files.
[SVN r77024]
2012-02-15 00:41:33 +00:00
e763315b55 Updated boost::base_from_member for C++2011.
[SVN r76982]
2012-02-11 18:27:02 +00:00
87b3643647 Merged doc updates and fix for #5098 from trunk
[SVN r76804]
2012-01-31 02:30:03 +00:00
c9d56eed6e Merge Boost.Config changes from Trunk - numerous small bug fixes plus a new Cray C++ config.
Fixes #5607.
Fixes #5941.
Fixes #5878.

[SVN r74889]
2011-10-10 11:50:55 +00:00
e36315c151 Merged in BGL, enable_if, and related changes from trunk: r67035, r57559, r72837, r73010, r73026, r72960, r73425, r73424, r73009, r73998, r73997, r73006, r73630, r73631, r73999, r73422, r73423, r73996, r71221
[SVN r74023]
2011-08-23 18:26:46 +00:00
fe653d0a9a Change call_traits to pass enum's by value.
Fixes #5790.

[SVN r73953]
2011-08-20 16:03:58 +00:00
26b39384e3 Apply patch from #5607.
Refs #5607.

[SVN r72580]
2011-06-14 08:27:14 +00:00
9525d062b3 added clarification to result_of doc
[SVN r72377]
2011-06-03 14:45:59 +00:00
6d196c4244 added tr1_result_of info to result_of doc
[SVN r72337]
2011-06-01 20:02:40 +00:00
e83682c091 updated result_of doc with decltype info
[SVN r72336]
2011-06-01 19:29:57 +00:00
1d146d010a upped BOOST_RESULT_OF_NUM_ARGS for Phoenix
[SVN r71769]
2011-05-06 19:55:35 +00:00
5684a2f2b3 Applied doc patches from Matt Calabrese
[SVN r71221]
2011-04-13 02:30:39 +00:00
95d2c38379 Fix doc errors reported by Rob Stewart. Fixes #5421.
[SVN r71047]
2011-04-06 20:21:51 +00:00
1aa48ea698 Utility/operators: [67268] Limit warning suppression to old versions of VC++, fixes #4432.
[SVN r70522]
2011-03-24 21:01:36 +00:00
7d23c75eef Revised the assertion_failed_msg function to use std::exit(-1) instead of std::abort() for Windows CE (since Windows CE does not have an abort() function in the CRT library)
[SVN r68982]
2011-02-18 03:46:55 +00:00
d01eb82fb7 Repair failed merge
[SVN r68914]
2011-02-15 16:18:51 +00:00
86791caf0e Merge trunk BOOST_ASSERT_MSG additions
[SVN r68912]
2011-02-15 14:54:16 +00:00
3279399fe3 Remove BOOST_ENABLE_ASSERT_MSG_HANDLER; use BOOST_ENABLE_ASSERT_HANDLER in its stead
[SVN r68423]
2011-01-24 20:15:36 +00:00
87875cadda Add BOOST_ASSERT_MSG. Add macros to configure output stream.
[SVN r68414]
2011-01-24 15:37:13 +00:00
c58748cfd9 use declval to fix #5098
[SVN r68373]
2011-01-22 22:18:48 +00:00
58bb88d4bd Revert [67111] (addition of boost/detail/iomanip.hpp) and all the commits that depend on it. ([68137], [68140], [68141], [68154], and [68165]).
[SVN r68168]
2011-01-15 08:11:51 +00:00
11d50ecb9f Replacing the use of <iomanip> with <boost/detail/iomanip.hpp> across Boost.
On Linux, GNU's libstdc++, which is the default stdlib for icc and clang,
cannot parse the <iomanip> header in version 4.5+ (which thankfully neither
compiler advises the use of yet), as it's original C++98-friendly
implementation has been replaced with a gnu++0x implementation.
<boost/detail/iomanip.hpp> is a portable implementation of <iomanip>, providing
boost::detail::setfill, boost::detail::setbase, boost::detail::setw,
boost::detail::setprecision, boost::detail::setiosflags and
boost::detail::resetiosflags. 



[SVN r68140]
2011-01-14 02:35:58 +00:00
636283d7c2 Limit warning suppression to old versions of VC++, fixes #4432
[SVN r67278]
2010-12-16 17:30:46 +00:00
1df0bf80bc Stop inspect complaining that assert is used in BOOST_ASSERT.
[SVN r66574]
2010-11-14 18:37:37 +00:00
8176af84e1 Merges changes from Trunk: refer to history.qbk for the details.
[SVN r65708]
2010-10-01 11:11:16 +00:00
71e78a0081 Add declval and common type from Vicente J. Botet Escriba.
Regenerate docs.

[SVN r65443]
2010-09-17 12:12:03 +00:00
f7e4b0e399 Make sure that utility/index.html has a complete list of components. Fixes #4629.
[SVN r65437]
2010-09-16 15:40:47 +00:00
b7d4b6edae merged [64695] and [64696] result_of docs from trunk
[SVN r64745]
2010-08-11 18:15:46 +00:00
fb1d2effef correction to result_of documentation
[SVN r64696]
2010-08-09 16:23:50 +00:00
94b91e8c92 updated result_of documentation
[SVN r64695]
2010-08-09 16:07:20 +00:00
d7cf3628f7 Merge some link fixes.
[64006] and [64059].


[SVN r64061]
2010-07-15 21:19:14 +00:00
a4b8043e68 Fix some header links.
[SVN r64006]
2010-07-14 08:15:33 +00:00
b273cd3914 Merged value_init fixes (extra tests + documentation) from trunk, see #3472, #3869.
[SVN r63638]
2010-07-04 21:56:44 +00:00
ca7db1f361 Merged value_init fixes from trunk, ref #3472, #3869.
[SVN r63637]
2010-07-04 21:50:38 +00:00
b4a08fc80e Added test for private_int_array_pair, hoping to (possibly) fix a minion-clang/darwin-4.2.1 failure at boost.org/development/tests/trunk/developer/utility_.html
[SVN r63045]
2010-06-17 16:53:55 +00:00
9da96d9737 Added value_init_workaround_test, reviewed by Fernando Cacciola, see #3869
[SVN r63014]
2010-06-16 08:45:43 +00:00
2a7e81e07f Merged revisions 61248 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r61248 | eric_niebler | 2010-04-13 08:01:11 -0700 (Tue, 13 Apr 2010) | 1 line
  
  add tr1_result_of that always behaves as TR1 specifies, fix Boost.TR1's result_of to use tr1_result_of
........


[SVN r62137]
2010-05-22 05:35:51 +00:00
13da21e7b1 Revert changes to result_of. Reopens #862, #1310, #1535.
[SVN r61149]
2010-04-08 21:59:33 +00:00
b3ffef536d Merged std_bitset.cpp (boost::swap test) from trunk r60292 through r60334 and r61065 through r61076, including #3984 fix.
[SVN r61077]
2010-04-05 19:21:12 +00:00
e2c98762db Revert [60052] as it isn't as uncontroversial as I thought.
[SVN r60314]
2010-03-07 16:22:34 +00:00
8af4250c3c Suppress/fix some msvc and gcc compiler warnings ([57494]).
[SVN r60291]
2010-03-07 12:13:29 +00:00
e30889304c Merge some tests for unwrap ([47296], [47297])
[SVN r60290]
2010-03-07 12:11:44 +00:00
b4dee80e61 Merge various result_of changes.
- [42234] Reduce header dependencies, from Shunsuke Sogame. Fixes #1535
 - [45256] result_of implementation that makes use of C++0x decltype, from Daniel Walker. Fixes #862.
 - [48620] Fix result_of to work with const-qualified function pointers. Fixes #1310
 - [60052] Remove use of deprecated config macro in result_of.



[SVN r60289]
2010-03-07 12:08:00 +00:00
a47dce770c Fix some whitespace differences between trunk and release.
[SVN r58878]
2010-01-10 19:17:23 +00:00
dab1e8e522 Merging changes from trunk.
[SVN r58421]
2009-12-16 22:26:57 +00:00
583422cda2 Add swap to utility index page.
Merged revisions 47093 via svnmerge from 
https://svn.boost.org/svn/boost/trunk


[SVN r57482]
2009-11-08 11:45:20 +00:00
ee146a02a1 rm cmake from the release branch before it goes out broken. Policy dictates that you never commit to release, you commit to trunk and merge to release.
[SVN r56941]
2009-10-17 01:10:45 +00:00
c131cbd0b2 Merged value_init from the trunk, including fix of #2548, regarding "const value_initialized".
[SVN r56547]
2009-10-03 10:19:09 +00:00
f8bef7ba95 Merged value_init_test from trunk, inc. [51356], anticipating the fix of ticket #2548, which will remove implicit conversion from const value_initialized<T> to non-const T&.
[SVN r56543]
2009-10-03 09:08:10 +00:00
e54cbf3053 Merged Swap documentation from trunk, including revision [56107] and [56108].
[SVN r56541]
2009-10-03 08:15:14 +00:00
d5291d08b8 Merged 52463
[SVN r55485]
2009-08-09 13:45:03 +00:00
61755605af Add basic copyright/license to keep cmake out of the inspection report
[SVN r55095]
2009-07-22 21:51:01 +00:00
cd12e322bd Merging in changes trunk updates: adding standard error_info typedefs, updating the documentation.
[SVN r55094]
2009-07-22 20:55:50 +00:00
8cb975feb7 Merge [47295] to release.
[SVN r53602]
2009-06-03 14:45:12 +00:00
ffe151458e Use local copy of the valid HTML 4.01 icon, and make sure all the pages
that use it are valid.

Merged revisions 53047-53048 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r53047 | danieljames | 2009-05-16 15:17:20 +0100 (Sat, 16 May 2009) | 1 line
  
  Fix some validation errors.
........
  r53048 | danieljames | 2009-05-16 15:23:59 +0100 (Sat, 16 May 2009) | 1 line
  
  Use a local copy of the valid HTML 4.01 icon.
........


[SVN r53258]
2009-05-25 20:06:26 +00:00
4003a9f74a Merge [53060] from the trunk.
[SVN r53197]
2009-05-23 05:36:13 +00:00
211eb04f33 Merge [44151], [48025] to release. Closes #3064.
[SVN r53172]
2009-05-22 09:00:11 +00:00
e57213b298 Fixed almost all tab and min/max issues found by inspect tool
[SVN r53142]
2009-05-20 19:41:20 +00:00
51f9adbfa1 Merged revisions 52837 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r52837 | eric_niebler | 2009-05-07 10:47:08 -0700 (Thu, 07 May 2009) | 1 line
  
  eliminate noisy warning on msvc
........


[SVN r53054]
2009-05-16 18:15:17 +00:00
eaaf17a88f tuning up cmakefiles for unordered, utility
[SVN r53008]
2009-05-15 00:21:14 +00:00
48cfd42123 tune up ptr_container, utility tests in cmakeland
[SVN r53007]
2009-05-14 23:56:22 +00:00
76aa5d2f27 more cmakefile tweaks
[SVN r52999]
2009-05-14 19:58:42 +00:00
ce67dde4f0 Documentation update
[SVN r52091]
2009-03-31 22:16:49 +00:00
a69e872a91 Merge [51977], [51986], [52010] to release.
[SVN r52040]
2009-03-28 20:53:26 +00:00
e3640e45c2 Merge [51872], [51891] to release. Closes #2878.
[SVN r51907]
2009-03-22 20:05:02 +00:00
b7cd171b2b Merge [51512] to release. Closes #2128.
[SVN r51534]
2009-03-02 16:32:03 +00:00
b2e6a82adb This html was outdated; changed to forward to throw_exception.html documentation from Boost Exception
[SVN r50880]
2009-01-29 19:14:05 +00:00
390372294a merge of cmake build files from trunk per beman
[SVN r50756]
2009-01-24 18:57:20 +00:00
ffbbf38e12 Merged new array-of-array tests of swap utility from trunk to release branch, following changeset [49954].
[SVN r50227]
2008-12-09 18:21:25 +00:00
9e73b2c6ae Merged value_initialized::swap from trunk [48424] and [48425], according to ticket #2243, as was agreed with Fernando Cacciola.
[SVN r49967]
2008-11-27 19:37:39 +00:00
633832e872 Merged libs/utility/swap.html from trunk to release (r47094 through r49914)
[SVN r49915]
2008-11-24 16:50:22 +00:00
862cb2a4e0 Merged revisions 49661-49662,49666,49669,49735,49756,49770,49811 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r49661 | danieljames | 2008-11-09 12:03:45 +0000 (Sun, 09 Nov 2008) | 1 line
  
  Move hash detail headers out of boost/functional/detail.
........
  r49662 | danieljames | 2008-11-09 12:11:50 +0000 (Sun, 09 Nov 2008) | 1 line
  
  Add a forwarding header for container_fwd.hpp
........
  r49666 | danieljames | 2008-11-09 19:12:05 +0000 (Sun, 09 Nov 2008) | 1 line
  
  Avoid comparing default initialised iterators in position_iterator.
........
  r49669 | danieljames | 2008-11-09 21:57:38 +0000 (Sun, 09 Nov 2008) | 2 lines
  
  Add link to the header to the synopsis in reference documentation.
  Refs #2214
........
  r49735 | danieljames | 2008-11-14 12:51:00 +0000 (Fri, 14 Nov 2008) | 1 line
  
  Explicitly specify the template parameters in the unordered container friend, in order to avoid some warnings.
........
  r49756 | danieljames | 2008-11-14 16:11:16 +0000 (Fri, 14 Nov 2008) | 1 line
  
  Use pragmas to suppress a Visual C++ warning.
........
  r49770 | danieljames | 2008-11-15 13:07:29 +0000 (Sat, 15 Nov 2008) | 1 line
  
  Use the new swap library.
........
  r49811 | danieljames | 2008-11-16 23:10:00 +0000 (Sun, 16 Nov 2008) | 1 line
  
  Fix a typo.
........


[SVN r49855]
2008-11-20 22:53:20 +00:00
b012f16ee5 Merged utility/swap documentation to release branch.
[SVN r49763]
2008-11-15 01:15:54 +00:00
3d96ab26d4 Merged utility/swap tests to release branch.
[SVN r49762]
2008-11-15 01:13:01 +00:00
8652bf51ec Merged utility/swap to release branch.
[SVN r49761]
2008-11-15 01:11:24 +00:00
9168cb9c61 CodeGear patch. Fixes #2341
[SVN r49319]
2008-10-13 19:21:03 +00:00
e1991374ae Merge quickbook workaround and fix some links.
Merged revisions 48987,49230-49231 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r48987 | danieljames | 2008-09-28 13:21:39 +0100 (Sun, 28 Sep 2008) | 1 line
  
  Clean up some link errors.
........
  r49230 | danieljames | 2008-10-09 23:13:48 +0100 (Thu, 09 Oct 2008) | 1 line
  
  position_iterator is meant to be a forward iterator, so avoid using operator+ with it.
........
  r49231 | danieljames | 2008-10-09 23:14:14 +0100 (Thu, 09 Oct 2008) | 4 lines
  
  Work around the problems with window newlines in position_iterator. (I'm
  about to fix them, but this will get quickbook working immediately).
  
  Fixes #2155
........


[SVN r49242]
2008-10-10 09:29:21 +00:00
d0ee9a7c28 Boost Exception major refactoring: works with or without RTTI, vastly improved boost::throw_exception integration.
[SVN r48905]
2008-09-19 20:29:26 +00:00
10e83b490b Merged BOOST_BINARY utility macro.
[SVN r48879]
2008-09-19 08:19:02 +00:00
4b24dba257 Replaced copyright symbols with (c) to match trunk
[SVN r48842]
2008-09-18 02:54:03 +00:00
7a036f6f3a Merge some small fixes from trunk.
Merged revisions 46740,46742,47002,47040 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r46740 | danieljames | 2008-06-26 20:20:56 +0100 (Thu, 26 Jun 2008) | 1 line
  
  Fix a character encoding error.
........
  r46742 | danieljames | 2008-06-26 20:25:38 +0100 (Thu, 26 Jun 2008) | 6 lines
  
  Give the asio documentation its own target.
  
  The asio documentation is built with the rest of the combined documentation but
  is really separate. So give it its own target so that separate parts can be
  built separately.
........
  r47040 | danieljames | 2008-07-03 15:34:56 +0100 (Thu, 03 Jul 2008) | 1 line
  
  Workaround for some template syntax not supported in old versions of Visual C++ 6.5
........


[SVN r47078]
2008-07-04 17:04:47 +00:00
e632b0fb1f Boost Exception
In other libraries, watch for compile error referring to throw_exception_assert_compatibility in boost::throw_exception. Resolve by throwing an exception that derives from std::exception. This is not a new requirement but it is being enforced now.

[SVN r46818]
2008-06-28 18:29:40 +00:00
17bee9d43f With his kind permission, change Jaakko "Järvi" to "Jarvi"
[SVN r46809]
2008-06-28 13:57:20 +00:00
492a8ad213 Merge of new boost.thread code along with required changes from boost.bind
[SVN r46474]
2008-06-18 13:01:08 +00:00
8827b8ed8b Merged value_init doc + test from trunk, including doc and test for boost::initialized_value, that was added with changeset [46464]
[SVN r46465]
2008-06-17 22:17:14 +00:00
8849fbc52d Merged value_init.hpp from trunk, including new boost::initialized_value object. (Was discussed beforehand with Fernando Cacciola.)
[SVN r46464]
2008-06-17 22:14:09 +00:00
50bc75a802 Add minor documentation fixes to the release branch.
(I left out the changes to the hash library).

Merged via svnmerge from 
https://svn.boost.org/svn/boost/trunk

................
  r44807 | danieljames | 2008-04-27 08:39:49 +0100 (Sun, 27 Apr 2008) | 78 lines
  
  Merge in documentation fixes.  Apart from the change to optional's documenation
  Jamfile, which I included by mistake.
  
  I wrote about this at:
  
  http://lists.boost.org/Archives/boost/2008/04/136405.php
  
  Merged revisions 44585-44806 via svnmerge from 
  https://svn.boost.org/svn/boost/branches/doc
  
  ........
    r44585 | danieljames | 2008-04-19 16:25:27 +0100 (Sat, 19 Apr 2008) | 2 lines
    
    Fix broken link to vacpp in bjam docs.
  ........
    r44586 | danieljames | 2008-04-19 16:27:36 +0100 (Sat, 19 Apr 2008) | 2 lines
    
    Fix broken link to bcpp in bjam docs.
  ........
    r44587 | danieljames | 2008-04-19 16:33:58 +0100 (Sat, 19 Apr 2008) | 2 lines
    
    DateTime documentation - Fix a link to the serialization library.
  ........
    r44588 | danieljames | 2008-04-19 16:35:36 +0100 (Sat, 19 Apr 2008) | 2 lines
    
    Fix some links in interprocess & intrusive.
  ........
    r44589 | danieljames | 2008-04-19 16:37:39 +0100 (Sat, 19 Apr 2008) | 2 lines
    
    Fix some links in the python docs.
  ........
    r44590 | danieljames | 2008-04-19 16:38:29 +0100 (Sat, 19 Apr 2008) | 2 lines
    
    Work around a quickbook bug which is affecting the python docs.
  ........
    r44591 | danieljames | 2008-04-19 16:39:34 +0100 (Sat, 19 Apr 2008) | 2 lines
    
    Fix a broken link in the numeric conversion docs.
  ........
    r44592 | danieljames | 2008-04-19 16:40:45 +0100 (Sat, 19 Apr 2008) | 2 lines
    
    Fix some links in the optional docs.
  ........
    r44593 | danieljames | 2008-04-19 16:42:09 +0100 (Sat, 19 Apr 2008) | 2 lines
    
    Fix link to the hash documentation from bimap.
  ........
    r44599 | danieljames | 2008-04-19 18:07:33 +0100 (Sat, 19 Apr 2008) | 2 lines
    
    Fix a typo in the format library.
  ........
    r44600 | danieljames | 2008-04-19 19:20:59 +0100 (Sat, 19 Apr 2008) | 1 line
    
    Initialise svnmerge.
  ........
    r44641 | danieljames | 2008-04-20 18:59:47 +0100 (Sun, 20 Apr 2008) | 2 lines
    
    Fix the lincense url in shared container iterator documentation.
  ........
    r44642 | danieljames | 2008-04-20 19:00:00 +0100 (Sun, 20 Apr 2008) | 2 lines
    
    Fix image link in the mpi documentation.
  ........
    r44643 | danieljames | 2008-04-20 19:00:11 +0100 (Sun, 20 Apr 2008) | 2 lines
    
    Fix a typo in the spirit docs.
  ........
    r44644 | danieljames | 2008-04-20 19:00:23 +0100 (Sun, 20 Apr 2008) | 2 lines
    
    Escape the slash so that quickbook doesn't think it the start of an italic section, and mess up the link. Refs #1844
  ........
    r44647 | danieljames | 2008-04-20 19:39:47 +0100 (Sun, 20 Apr 2008) | 2 lines
    
    Fix another typo in spirit docs.
  ........
................
  r45232 | danieljames | 2008-05-08 22:50:19 +0100 (Thu, 08 May 2008) | 1 line
  
  Fix some invalid xml by replacing ampersands with character entities.
................
  r45576 | danieljames | 2008-05-20 16:39:25 +0100 (Tue, 20 May 2008) | 20 lines
  
  Merge some small documentation fixes from the doc branch, and mark some
  previously merged changes as merged.
  
  Merged revisions 44811,45129,45142,45154,45281-45282,45365 via svnmerge from 
  https://svn.boost.org/svn/boost/branches/doc
  
  ........
    r45129 | danieljames | 2008-05-05 12:36:50 +0100 (Mon, 05 May 2008) | 2 lines
    
    Update navbar links in boostbook.
  ........
    r45282 | danieljames | 2008-05-11 14:15:31 +0100 (Sun, 11 May 2008) | 2 lines
    
    Group functions in the hash header - requires Frank's free-function-group fix.
    (not included in release branch).
  ........
    r45365 | danieljames | 2008-05-14 21:39:00 +0100 (Wed, 14 May 2008) | 2 lines
    
    Add boost.root to standalone hash documentation.
    (not included in release branch).
  ........
................


[SVN r45622]
2008-05-21 20:57:05 +00:00
9b52e49fda Merge inspection failure fixes from Trunk.
[SVN r43634]
2008-03-15 18:45:28 +00:00
ab479794f3 Merged revisions 43206,43208-43213 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r43206 | danieljames | 2008-02-10 09:55:03 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Fix some broken links.
........
  r43209 | danieljames | 2008-02-10 14:56:22 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Link to people pages on the website, as they've been removed from the download.
........
  r43210 | danieljames | 2008-02-10 15:02:17 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Point links to the pages that used to be in 'more' to the site.
........
  r43212 | danieljames | 2008-02-10 16:10:16 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Fix links on the home page as well.
........
  r43213 | danieljames | 2008-02-10 16:21:22 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Generated documentation which is no longer generated.
........


[SVN r43214]
2008-02-10 16:39:38 +00:00
97b8966337 value_init doc + test: Merged from trunk changeset [42798] to release.
[SVN r42799]
2008-01-15 19:55:28 +00:00
88099a882f Merged value_init.hpp from trunk [42277] to release branch, thereby resolving ticket #1459 and #1491. Fernando Cacciola (owner of value_init) encouraged me to do the commit.
[SVN r42501]
2008-01-05 22:38:50 +00:00
d5554eb6d7 Pick up missing smart_ptr, utility, and type_traits files from full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41386]
2007-11-25 22:34:55 +00:00
13bdfb8bbd Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41370]
2007-11-25 18:38:02 +00:00
74462349c2 Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41369]
2007-11-25 18:07:19 +00:00
6aa648d315 Starting point for releases
[SVN r39706]
2007-10-05 14:25:06 +00:00
9ff18c2c96 This commit was manufactured by cvs2svn to create tag
'Version_1_34_1'.

[SVN r38286]
2007-07-24 19:28:14 +00:00
d5ea07c737 Merged changes for ticket #979 from HEAD
[SVN r37920]
2007-06-06 20:57:40 +00:00
aa0096bf42 Testsuite for none_t added.
[SVN r37421]
2007-04-12 14:32:38 +00:00
005c2f3cc8 Fix a couple of links.
[SVN r36656]
2007-01-07 22:58:41 +00:00
09f7aab52d Merged L & C issue fixes & HTML conversions from trunk to branch.
[SVN r36281]
2006-12-05 22:33:21 +00:00
30a40f9f76 Linked to current_function.html
[SVN r36268]
2006-12-04 20:31:38 +00:00
d9f8bae673 Merge from HEAD.
Allow building of shared versions of some Boost.Test libraries.
Adjust tests to use always use static linking to Boost.Test, since
linking to the shared version requires test changes.

Patch from Juergen Hunold.


[SVN r35990]
2006-11-10 19:59:52 +00:00
3c7b409460 License/copyright edits
[SVN r35958]
2006-11-09 20:34:33 +00:00
ee3551e8dc Merged copyright and license addition
[SVN r35907]
2006-11-07 19:27:00 +00:00
95da2e90de Remove obsolete Boost.Build v1 files.
[SVN r35880]
2006-11-06 17:10:46 +00:00
6dd93ab916 Removed unneeded semicolon.
[SVN r35636]
2006-10-16 18:01:40 +00:00
505d419a1b Resolved an ambiguity.
[SVN r35039]
2006-09-08 00:16:31 +00:00
d968b5f5b9 boost guidelines (mainly from inspect tool: tabs, license reference text, etc.); more to do...
[SVN r34753]
2006-07-27 11:48:49 +00:00
d809d4e832 This commit was manufactured by cvs2svn to create branch 'RC_1_34_0'.
[SVN r33417]
2006-03-21 02:26:31 +00:00
59 changed files with 4706 additions and 188 deletions

View File

@ -17,36 +17,89 @@
<td colspan="2" height="64">&nbsp;</td>
</tr>
</table>
<p>
<a href="#BOOST_ASSERT">BOOST_ASSERT</a><br>
<a href="#BOOST_ASSERT_MSG">BOOST_ASSERT_MSG</a><br>
<a href="#BOOST_VERIFY">BOOST_VERIFY</a></p>
<h2><a name="BOOST_ASSERT">BOOST_ASSERT</a></h2>
<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.
The macro is intended to be used in both Boost libraries and user
code.
</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>
<P>If 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>
<P>If 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>
<blockquote>
<P><tt>::boost::assertion_failed(#expr, <a href="current_function.html">BOOST_CURRENT_FUNCTION</a>,
__FILE__, __LINE__)</tt></P>
</blockquote>
<P><STRONG>assertion_failed</STRONG> is declared in <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
as</P>
<pre>
namespace boost
<blockquote>
<pre>namespace boost
{
void assertion_failed(char const * expr, char const * function, char const * file, long line);
void assertion_failed(char const * expr, char const * function, char const * file, long line);
}
</pre>
</blockquote>
<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>
<h2><a name="BOOST_ASSERT_MSG">BOOST_ASSERT_MSG</a></h2>
<p>
The header <STRONG>&lt;boost/assert.hpp&gt;</STRONG> defines the macro <b>BOOST_ASSERT_MSG</b>,
which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG>&lt;cassert&gt;</STRONG>,
but with an additional macro parameter supplying an error message. The macro is intended to be used in both Boost libraries
and user code.
</p>
<P> <tt>BOOST_ASSERT_MSG(expr, msg)</tt> is equivalent to <code>
((void)0)</code> if <b>BOOST_DISABLE_ASSERTS</b> or <b>NDEBUG</b> are
defined or <code>expr</code> evaluates to <code>true</code>. If those
macros and <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> are not
defined, and <code>expr</code> evaluates to <code>false</code>, an error
message that includes <tt>#expr</tt>, <tt>msg</tt>, <tt> <a href="current_function.html">BOOST_CURRENT_FUNCTION</a></tt>, <tt>
__FILE__</tt>, and <tt>__LINE__</tt> is sent to output stream <b>
BOOST_ASSERT_MSG_OSTREAM</b>
and <code>std::abort()</code> is called.</P>
<P> <b>BOOST_ASSERT_MSG_OSTREAM</b> defines the output stream. It defaults to <code>std::cerr</code>.
Integrated development environments (IDE's) like Microsoft Visual Studio
may produce easier to understand output if messages go to a different
stream, such as <code>std::cout</code>. Users may define <b>BOOST_ASSERT_MSG_OSTREAM</b> before including <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
to specify a different output stream.&nbsp; </P>
<P>If the macro <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> is defined when <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
is included, instead of sending a error message to an output
stream, this expression is evaluated</P>
<blockquote>
<P><tt>::boost::assertion_failed_msg(#expr, msg, <a href="current_function.html">BOOST_CURRENT_FUNCTION</a>,
__FILE__, __LINE__)</tt></P>
</blockquote>
<P><STRONG>assertion_failed_msg</STRONG> is declared in <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
as</P>
<blockquote>
<pre>namespace boost
{
void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line);
}
</pre>
</blockquote>
<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_MSG</STRONG>
will be redefined each time as specified above.</P>
<h2><a name="BOOST_VERIFY">BOOST_VERIFY</a></h2>
<p><STRONG>&lt;boost/assert.hpp&gt;</STRONG> also defines the macro <STRONG>BOOST_VERIFY</STRONG>.
It has exactly the same behavior as <STRONG>BOOST_ASSERT</STRONG>, except that
the expression that is passed to <STRONG>BOOST_VERIFY</STRONG> is always
@ -54,8 +107,9 @@ void assertion_failed(char const * expr, char const * function, char const * fil
effects; it can also help suppress warnings about unused variables when the
only use of the variable is inside an assertion.</p>
<p><br>
<small>Copyright <20> 2002, 2007 by Peter Dimov. Distributed under the Boost Software
<small>Copyright <20> 2002, 2007 by Peter Dimov.&nbsp; Copyright <20> 2011
by Beman Dawes. Distributed under the Boost Software
License, Version 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A>
or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html>
</html>

View File

@ -2,6 +2,7 @@
// assert_test.cpp - a test for boost/assert.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
// Copyright (2) Beman Dawes 2011
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@ -20,6 +21,11 @@ void test_default()
BOOST_ASSERT(x);
BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x);
BOOST_ASSERT_MSG(1, "msg");
BOOST_ASSERT_MSG(x, "msg");
BOOST_ASSERT_MSG(x == 1, "msg");
BOOST_ASSERT_MSG(&x, "msg");
}
#define BOOST_DISABLE_ASSERTS
@ -34,13 +40,23 @@ void test_disabled()
BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x);
BOOST_ASSERT_MSG(1, "msg");
BOOST_ASSERT_MSG(x, "msg");
BOOST_ASSERT_MSG(x == 1, "msg");
BOOST_ASSERT_MSG(&x, "msg");
BOOST_ASSERT(0);
BOOST_ASSERT(!x);
BOOST_ASSERT(x == 0);
BOOST_ASSERT_MSG(0, "msg");
BOOST_ASSERT_MSG(!x, "msg");
BOOST_ASSERT_MSG(x == 0, "msg");
void * p = 0;
BOOST_ASSERT(p);
BOOST_ASSERT_MSG(p, "msg");
// supress warnings
p = &x;
@ -55,6 +71,7 @@ void test_disabled()
#include <cstdio>
int handler_invoked = 0;
int msg_handler_invoked = 0;
void boost::assertion_failed(char const * expr, char const * function, char const * file, long line)
{
@ -66,11 +83,24 @@ void boost::assertion_failed(char const * expr, char const * function, char cons
++handler_invoked;
}
void boost::assertion_failed_msg(char const * expr, char const * msg, char const * function,
char const * file, long line)
{
#if !defined(BOOST_NO_STDC_NAMESPACE)
using std::printf;
#endif
printf("Expression: %s Message: %s\nFunction: %s\nFile: %s\nLine: %ld\n\n",
expr, msg, function, file, line);
++msg_handler_invoked;
}
struct X
{
static void f()
{
BOOST_ASSERT(0);
BOOST_ASSERT_MSG(0, "msg f()");
}
};
@ -83,21 +113,35 @@ void test_handler()
BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x);
BOOST_ASSERT_MSG(1, "msg2");
BOOST_ASSERT_MSG(x, "msg3");
BOOST_ASSERT_MSG(x == 1, "msg4");
BOOST_ASSERT_MSG(&x, "msg5");
BOOST_ASSERT(0);
BOOST_ASSERT(!x);
BOOST_ASSERT(x == 0);
BOOST_ASSERT_MSG(0,"msg 0");
BOOST_ASSERT_MSG(!x, "msg !x");
BOOST_ASSERT_MSG(x == 0, "msg x == 0");
void * p = 0;
BOOST_ASSERT(p);
BOOST_ASSERT_MSG(p, "msg p");
X::f();
BOOST_ASSERT(handler_invoked == 5);
BOOST_TEST(handler_invoked == 5);
BOOST_ASSERT_MSG(msg_handler_invoked == 5, "msg_handler_invoked count is wrong");
BOOST_TEST(msg_handler_invoked == 5);
}
#undef BOOST_ENABLE_ASSERT_HANDLER
#undef BOOST_ENABLE_ASSERT_MSG_HANDLER
int main()
{

View File

@ -129,6 +129,8 @@ particular member type does not need to concern itself with the integer.</p>
<h2><a name="synopsis">Synopsis</a></h2>
<blockquote><pre>
#include &lt;type_traits&gt; <i>// exposition only</i>
#ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY
#define BOOST_BASE_FROM_MEMBER_MAX_ARITY 10
#endif
@ -139,6 +141,11 @@ class boost::base_from_member
protected:
MemberType member;
#if <i>C++2011 is in use</i>
template&lt; typename ...T &gt;
explicit constexpr base_from_member( T&amp;&amp; ...x )
noexcept( std::is_nothrow_constructible&lt;MemberType, T...&gt;::value );
#else
base_from_member();
template&lt; typename T1 &gt;
@ -154,6 +161,7 @@ protected:
typename T10 &gt;
base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7,
T8 x8, T9 x9, T10 x10 );
#endif
};
</pre></blockquote>
@ -166,13 +174,29 @@ 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 ten) as possible and pass them to a constructor of
the data member. Since C++ does not allow any way to explicitly state
<p>If the appropriate features of C++2011 are present, there will be a single
constructor template. It implements &quot;perfect forwarding&quot; to the best
constructor call of <code>member</code> (if any). The constructor template is
marked both <code>constexpr</code> and <code>explicit</code>. The former will
be ignored if the corresponding inner constructor call (of <code>member</code>)
does not have the marker. The latter binds the other way; always taking
effect, even when the inner constructor call does not have the marker. The
constructor template propagates the <code>noexcept</code> status of the inner
constructor call. (The constructor template has a trailing parameter with a
default value that disables the template when its signature is too close to the
signatures of the automatically-defined non-template copy- and/or
move-constructors of <code>base_from_member</code>.)</p>
<p>On earlier-standard compilers, there is a default constructor and several
constructor member templates. These constructor templates can take as many
arguments (currently up to ten) as possible and pass them to a constructor of
the data member.</p>
<p>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>
the data member's desired constructor. Explicit conversions may be
necessary.</p>
<p>The <var>BOOST_BASE_FROM_MEMBER_MAX_ARITY</var> macro constant specifies
the maximum argument length for the constructor templates. The constant
@ -180,7 +204,7 @@ may be overridden if more (or less) argument configurations are needed. The
constant may be read for code that is expandable like the class template and
needs to maintain the same maximum size. (Example code would be a class that
uses this class template as a base class for a member with a flexible set of
constructors.)</p>
constructors.) This constant is ignored when C++2011 features are present.</p>
<h2><a name="usage">Usage</a></h2>
@ -323,11 +347,14 @@ constructor argument for <code>pbase0_type</code> is converted from
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>
forms of the null-pointer literal in C++ (except <code>nullptr</code> from
C++2011) 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. (If C++2011's <code>nullptr</code> is
used, it still needs a conversion if multiple pointer types can be accepted in
a constructor call but <code>std::nullptr_t</code> cannot.)</p>
<h2><a name="credits">Credits</a></h2>
@ -360,9 +387,9 @@ with the exact pointer type used in <code>switcher</code>'s constructor.</p>
<hr>
<p>Revised: 28 August 2004</p>
<p>Revised: 16 February 2012</p>
<p>Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and distribution
<p>Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and distribution
are subject to the Boost Software License, Version 1.0. (See accompanying
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a copy at &lt;<a
href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>&gt;.)</p>

View File

@ -210,8 +210,10 @@ int main()
comparible_UDT u;
c1(u);
call_traits_checker<int> c2;
call_traits_checker<enum_UDT> c2b;
int i = 2;
c2(i);
c2b(one);
int* pi = &i;
int a[2] = {1,2};
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) && !defined(__ICL)
@ -292,7 +294,11 @@ int main()
BOOST_CHECK_TYPE(incomplete_type&, boost::call_traits<incomplete_type>::reference);
BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits<incomplete_type>::const_reference);
BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits<incomplete_type>::param_type);
// test enum:
BOOST_CHECK_TYPE(enum_UDT, boost::call_traits<enum_UDT>::value_type);
BOOST_CHECK_TYPE(enum_UDT&, boost::call_traits<enum_UDT>::reference);
BOOST_CHECK_TYPE(const enum_UDT&, boost::call_traits<enum_UDT>::const_reference);
BOOST_CHECK_TYPE(const enum_UDT, boost::call_traits<enum_UDT>::param_type);
return 0;
}

100
doc/Jamfile.v2 Normal file
View File

@ -0,0 +1,100 @@
# Copyright John Maddock 2005. Use, modification, and distribution are
# subject to the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
project : requirements
# Path for links to Boost:
<xsl:param>boost.root=../../../..
# Some general style settings:
<xsl:param>table.footnote.number.format=1
<xsl:param>footnote.number.format=1
# HTML options first:
# Use graphics not text for navigation:
<xsl:param>navig.graphics=1
# PDF Options:
# TOC Generation: this is needed for FOP-0.9 and later:
<xsl:param>fop1.extensions=0
<xsl:param>xep.extensions=1
# TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9!
<xsl:param>fop.extensions=0
# No indent on body text:
<xsl:param>body.start.indent=0pt
# Margin size:
<xsl:param>page.margin.inner=0.5in
# Margin size:
<xsl:param>page.margin.outer=0.5in
# Paper type = A4
<xsl:param>paper.type=A4
# Yes, we want graphics for admonishments:
<xsl:param>admon.graphics=1
# Set this one for PDF generation *only*:
# default pnd graphics are awful in PDF form,
# better use SVG's instead:
<format>pdf:<xsl:param>admon.graphics.extension=".svg"
<format>pdf:<xsl:param>admon.graphics.path=$(boost-images)/
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/utility/doc/html
;
using quickbook ;
path-constant boost-images : ../../../doc/src/images ;
xml declval : declval.qbk ;
boostbook standalone_declval
:
declval
:
# File name of HTML output:
<xsl:param>root.filename=declval
# How far down we chunk nested sections, basically all of them:
<xsl:param>chunk.section.depth=0
# Don't put the first section on the same page as the TOC:
<xsl:param>chunk.first.sections=0
# How far down sections get TOC's
<xsl:param>toc.section.depth=1
# Max depth in each TOC:
<xsl:param>toc.max.depth=1
# How far down we go with TOC's
<xsl:param>generate.section.toc.level=1
;
xml string_ref : string_ref.qbk ;
boostbook standalone_string_ref
:
string_ref
:
# File name of HTML output:
<xsl:param>root.filename=string_ref
# How far down we chunk nested sections, basically all of them:
<xsl:param>chunk.section.depth=0
# Don't put the first section on the same page as the TOC:
<xsl:param>chunk.first.sections=0
# How far down sections get TOC's
<xsl:param>toc.section.depth=1
# Max depth in each TOC:
<xsl:param>toc.max.depth=1
# How far down we go with TOC's
<xsl:param>generate.section.toc.level=1
;
xml explicit_operator_bool : explicit_operator_bool.qbk ;
boostbook standalone_explicit_operator_bool
:
explicit_operator_bool
:
# File name of HTML output:
<xsl:param>root.filename=explicit_operator_bool
# How far down we chunk nested sections, basically all of them:
<xsl:param>chunk.section.depth=0
# Don't put the first section on the same page as the TOC:
<xsl:param>chunk.first.sections=0
# How far down sections get TOC's
<xsl:param>toc.section.depth=1
# Max depth in each TOC:
<xsl:param>toc.max.depth=1
# How far down we go with TOC's
<xsl:param>generate.section.toc.level=1
;

115
doc/declval.qbk Normal file
View File

@ -0,0 +1,115 @@
[/
/ Copyright (c) 2008 Howard Hinnant
/ Copyright (c) 2009-20012 Vicente J. Botet Escriba
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[article Declval
[quickbook 1.5]
[authors [Hinnant, Howard]]
[authors [Botet Escriba, Vicente J.]]
[copyright 2008 Howard Hinnant]
[copyright 2009-2012 Vicente J. Botet Escriba]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
[@http://www.boost.org/LICENSE_1_0.txt])
]
]
[/===============]
[section Overview]
[/===============]
The motivation for `declval` was introduced in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2958.html#Value N2958:
Moving Swap Forward]. Here follows a rewording of this chapter.
With the provision of decltype, late-specified return types, and default template-arguments for function templates a
new generation of SFINAE patterns will emerge to at least partially compensate the lack of concepts on the C++0x timescale.
Using this technique, it is sometimes necessary to obtain an object of a known type in a non-using context, e.g. given the declaration
template<class T>
T&& declval(); // not used
as part of the function template declaration
template<class To, class From>
decltype(static_cast<To>(declval<From>())) convert(From&&);
or as part of a class template definition
template<class> class result_of;
template<class Fn, class... ArgTypes>
struct result_of<Fn(ArgTypes...)>
{
typedef decltype(declval<Fn>()(declval<ArgTypes>()...)) type;
};
The role of the function template declval() is a transformation of a type T into a value without using or evaluating this function.
The name is supposed to direct the reader's attention to the fact that the expression `declval<T>()` is an lvalue if and only if
T is an lvalue-reference, otherwise an rvalue. To extend the domain of this function we can do a bit better by changing its declaration to
template<class T>
typename std::add_rvalue_reference<T>::type declval(); // not used
which ensures that we can also use cv void as template parameter. The careful reader might have noticed that `declval()`
already exists under the name create() as part of the definition of the semantics of the type trait is_convertible in the C++0x standard.
The provision of a new library component that allows the production of values in unevaluated expressions is considered
important to realize constrained templates in C++0x where concepts are not available.
This extremely light-weight function is expected to be part of the daily tool-box of the C++0x programmer.
[endsect]
[/=================]
[section:reference Reference ]
[/=================]
`#include <boost/utility/declval.hpp>`
namespace boost {
template <typename T>
typename add_rvalue_reference<T>::type declval() noexcept; // as unevaluated operand
} // namespace boost
The library provides the function template declval to simplify the definition of expressions which occur as unevaluated operands.
template <typename T>
typename add_rvalue_reference<T>::type declval();
[*Remarks:] If this function is used, the program is ill-formed.
[*Remarks:] The template parameter T of declval may be an incomplete type.
[*Example:]
template <class To, class From>
decltype(static_cast<To>(declval<From>())) convert(From&&);
Declares a function template convert which only participates in overloading if the type From can be explicitly converted to type To.
[endsect]
[/===============]
[section History]
[/===============]
[heading boost 1.50]
Fixes:
* [@http://svn.boost.org/trac/boost/ticket/6570 #6570] Adding noexcept to boost::declval.
[endsect]

View File

@ -0,0 +1,68 @@
[/
/ Copyright (c) 2013 Andrey Semashev
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[article BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL
[quickbook 1.5]
[authors [Semashev, Andrey]]
[copyright 2013 Andrey Semashev]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
[@http://www.boost.org/LICENSE_1_0.txt])
]
]
[/===============]
[section Overview]
[/===============]
`BOOST_EXPLICIT_OPERATOR_BOOL()` and `BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()` are compatibility helper macros that expand to an explicit conversion operator to `bool`. For compilers not supporting explicit conversion operators introduced in C++11 the macros expand to a conversion operator that implements the [@http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool safe bool idiom]. In case if the compiler is not able to handle safe bool idiom well the macros expand to a regular conversion operator to `bool`.
[endsect]
[/===============]
[section Examples]
[/===============]
Both macros are intended to be placed within a user's class definition. The generated conversion operators will be implemented in terms of `operator!()` that should be defined by user in this class. In case of `BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()` the generated conversion operator will be declared `constexpr` which requires the corresponding `operator!()` to also be `constexpr`.
template< typename T >
class my_ptr
{
T* m_p;
public:
BOOST_EXPLICIT_OPERATOR_BOOL()
bool operator!() const
{
return !m_p;
}
};
Now `my_ptr` can be used in conditional expressions, similarly to a regular pointer:
my_ptr< int > p;
if (p)
std::cout << "true" << std::endl;
[endsect]
[/===============]
[section History]
[/===============]
[heading boost 1.55]
* The macro was extracted from Boost.Log.
[endsect]

176
doc/html/declval.html Normal file
View File

@ -0,0 +1,176 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Declval</title>
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.76.0">
<link rel="home" href="declval.html" title="Declval">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
<td align="center"><a href="../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav"></div>
<div class="article">
<div class="titlepage">
<div>
<div><h2 class="title">
<a name="declval"></a>Declval</h2></div>
<div><div class="authorgroup">
<div class="author"><h3 class="author">
<span class="firstname">Howard</span> <span class="surname">Hinnant</span>
</h3></div>
<div class="author"><h3 class="author">
<span class="firstname">Vicente J.</span> <span class="surname">Botet Escriba</span>
</h3></div>
</div></div>
<div><p class="copyright">Copyright &#169; 2008 Howard Hinnant</p></div>
<div><p class="copyright">Copyright &#169; 2009 -2012 Vicente J. Botet Escriba</p></div>
<div><div class="legalnotice">
<a name="idp13449552"></a><p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></div>
</div>
<hr>
</div>
<div class="toc">
<p><b>Table of Contents</b></p>
<dl>
<dt><span class="section"><a href="declval.html#declval.overview">Overview</a></span></dt>
<dt><span class="section"><a href="declval.html#declval.reference">Reference </a></span></dt>
<dt><span class="section"><a href="declval.html#declval.history">History</a></span></dt>
</dl>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="declval.overview"></a><a class="link" href="declval.html#declval.overview" title="Overview">Overview</a>
</h2></div></div></div>
<p>
The motivation for <code class="computeroutput"><span class="identifier">declval</span></code>
was introduced in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2958.html#Value" target="_top">N2958:
Moving Swap Forward</a>. Here follows a rewording of this chapter.
</p>
<p>
With the provision of decltype, late-specified return types, and default template-arguments
for function templates a new generation of SFINAE patterns will emerge to at
least partially compensate the lack of concepts on the C++0x timescale. Using
this technique, it is sometimes necessary to obtain an object of a known type
in a non-using context, e.g. given the declaration
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="identifier">T</span><span class="special">&amp;&amp;</span> <span class="identifier">declval</span><span class="special">();</span> <span class="comment">// not used
</span></pre>
<p>
as part of the function template declaration
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">To</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">From</span><span class="special">&gt;</span>
<span class="identifier">decltype</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">To</span><span class="special">&gt;(</span><span class="identifier">declval</span><span class="special">&lt;</span><span class="identifier">From</span><span class="special">&gt;()))</span> <span class="identifier">convert</span><span class="special">(</span><span class="identifier">From</span><span class="special">&amp;&amp;);</span>
</pre>
<p>
or as part of a class template definition
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span><span class="special">&gt;</span> <span class="keyword">class</span> <span class="identifier">result_of</span><span class="special">;</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">ArgTypes</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">result_of</span><span class="special">&lt;</span><span class="identifier">Fn</span><span class="special">(</span><span class="identifier">ArgTypes</span><span class="special">...)&gt;</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="identifier">decltype</span><span class="special">(</span><span class="identifier">declval</span><span class="special">&lt;</span><span class="identifier">Fn</span><span class="special">&gt;()(</span><span class="identifier">declval</span><span class="special">&lt;</span><span class="identifier">ArgTypes</span><span class="special">&gt;()...))</span> <span class="identifier">type</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
The role of the function template declval() is a transformation of a type T
into a value without using or evaluating this function. The name is supposed
to direct the reader's attention to the fact that the expression <code class="computeroutput"><span class="identifier">declval</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;()</span></code> is
an lvalue if and only if T is an lvalue-reference, otherwise an rvalue. To
extend the domain of this function we can do a bit better by changing its declaration
to
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">add_rvalue_reference</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">type</span> <span class="identifier">declval</span><span class="special">();</span> <span class="comment">// not used
</span></pre>
<p>
which ensures that we can also use cv void as template parameter. The careful
reader might have noticed that <code class="computeroutput"><span class="identifier">declval</span><span class="special">()</span></code> already exists under the name create() as
part of the definition of the semantics of the type trait is_convertible in
the C++0x standard.
</p>
<p>
The provision of a new library component that allows the production of values
in unevaluated expressions is considered important to realize constrained templates
in C++0x where concepts are not available. This extremely light-weight function
is expected to be part of the daily tool-box of the C++0x programmer.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="declval.reference"></a><a class="link" href="declval.html#declval.reference" title="Reference">Reference </a>
</h2></div></div></div>
<p>
<code class="computeroutput"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">utility</span><span class="special">/</span><span class="identifier">declval</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span></code>
</p>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">typename</span> <span class="identifier">add_rvalue_reference</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">type</span> <span class="identifier">declval</span><span class="special">()</span> <span class="identifier">noexcept</span><span class="special">;</span> <span class="comment">// as unevaluated operand
</span>
<span class="special">}</span> <span class="comment">// namespace boost
</span></pre>
<p>
The library provides the function template declval to simplify the definition
of expressions which occur as unevaluated operands.
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">typename</span> <span class="identifier">add_rvalue_reference</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">type</span> <span class="identifier">declval</span><span class="special">();</span>
</pre>
<p>
<span class="bold"><strong>Remarks:</strong></span> If this function is used, the program
is ill-formed.
</p>
<p>
<span class="bold"><strong>Remarks:</strong></span> The template parameter T of declval
may be an incomplete type.
</p>
<p>
<span class="bold"><strong>Example:</strong></span>
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">To</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">From</span><span class="special">&gt;</span>
<span class="identifier">decltype</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">To</span><span class="special">&gt;(</span><span class="identifier">declval</span><span class="special">&lt;</span><span class="identifier">From</span><span class="special">&gt;()))</span> <span class="identifier">convert</span><span class="special">(</span><span class="identifier">From</span><span class="special">&amp;&amp;);</span>
</pre>
<p>
Declares a function template convert which only participates in overloading
if the type From can be explicitly converted to type To.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="declval.history"></a><a class="link" href="declval.html#declval.history" title="History">History</a>
</h2></div></div></div>
<a name="declval.history.boost_1_50"></a><h4>
<a name="idp13553216"></a>
<a class="link" href="declval.html#declval.history.boost_1_50">boost 1.50</a>
</h4>
<p>
Fixes:
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
<a href="http://svn.boost.org/trac/boost/ticket/6570" target="_top">#6570</a>
Adding noexcept to boost::declval.
</li></ul></div>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><p><small>Last revised: May 28, 2012 at 18:59:06 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td>
</tr></table>
<hr>
<div class="spirit-nav"></div>
</body>
</html>

280
doc/html/string_ref.html Normal file
View File

@ -0,0 +1,280 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>String_Ref</title>
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
<link rel="home" href="string_ref.html" title="String_Ref">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
<td align="center"><a href="../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav"></div>
<div class="article">
<div class="titlepage">
<div>
<div><h2 class="title">
<a name="string_ref"></a>String_Ref</h2></div>
<div><div class="authorgroup"><div class="author"><h3 class="author">
<span class="firstname">Marshall</span> <span class="surname">Clow</span>
</h3></div></div></div>
<div><p class="copyright">Copyright &#169; 2012 Marshall Clow</p></div>
<div><div class="legalnotice">
<a name="string_ref.legal"></a><p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></div>
</div>
<hr>
</div>
<div class="toc">
<p><b>Table of Contents</b></p>
<dl>
<dt><span class="section"><a href="string_ref.html#string_ref.overview">Overview</a></span></dt>
<dt><span class="section"><a href="string_ref.html#string_ref.examples">Examples</a></span></dt>
<dt><span class="section"><a href="string_ref.html#string_ref.reference">Reference </a></span></dt>
<dt><span class="section"><a href="string_ref.html#string_ref.history">History</a></span></dt>
</dl>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="string_ref.overview"></a><a class="link" href="string_ref.html#string_ref.overview" title="Overview">Overview</a>
</h2></div></div></div>
<p>
Boost.StringRef is an implementation of Jeffrey Yaskin's <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html" target="_top">N3442:
string_ref: a non-owning reference to a string</a>.
</p>
<p>
When you are parsing/processing strings from some external source, frequently
you want to pass a piece of text to a procedure for specialized processing.
The canonical way to do this is as a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>,
but that has certain drawbacks:
</p>
<p>
1) If you are processing a buffer of text (say a HTTP response or the contents
of a file), then you have to create the string from the text you want to pass,
which involves memory allocation and copying of data.
</p>
<p>
2) if a routine receives a constant <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
and wants to pass a portion of that string to another routine, then it must
create a new string of that substring.
</p>
<p>
3) A routine receives a constant <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
and wants to return a portion of the string, then it must create a new string
to return.
</p>
<p>
<code class="computeroutput"><span class="identifier">string_ref</span></code> is designed to solve
these efficiency problems. A <code class="computeroutput"><span class="identifier">string_ref</span></code>
is a read-only reference to a contiguous sequence of characters, and provides
much of the functionality of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>.
A <code class="computeroutput"><span class="identifier">string_ref</span></code> is cheap to create,
copy and pass by value, because it does not actually own the storage that it
points to.
</p>
<p>
A <code class="computeroutput"><span class="identifier">string_ref</span></code> is implemented
as a small struct that contains a pointer to the start of the character data
and a count. A <code class="computeroutput"><span class="identifier">string_ref</span></code> is
cheap to create and cheap to copy.
</p>
<p>
<code class="computeroutput"><span class="identifier">string_ref</span></code> acts as a container;
it includes all the methods that you would expect in a container, including
iteration support, <code class="computeroutput"><span class="keyword">operator</span> <span class="special">[]</span></code>,
<code class="computeroutput"><span class="identifier">at</span></code> and <code class="computeroutput"><span class="identifier">size</span></code>.
It can be used with any of the iterator-based algorithms in the STL - as long
as you don't need to change the underlying data (<code class="computeroutput"><span class="identifier">sort</span></code>
and <code class="computeroutput"><span class="identifier">remove</span></code>, for example, will
not work)
</p>
<p>
Besides generic container functionality, <code class="computeroutput"><span class="identifier">string_ref</span></code>
provides a subset of the interface of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>.
This makes it easy to replace parameters of type <code class="computeroutput"><span class="keyword">const</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span></code>
with <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span></code>. Like <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>,
<code class="computeroutput"><span class="identifier">string_ref</span></code> has a static member
variable named <code class="computeroutput"><span class="identifier">npos</span></code> to denote
the result of failed searches, and to mean "the end".
</p>
<p>
Because a <code class="computeroutput"><span class="identifier">string_ref</span></code> does not
own the data that it "points to", it introduces lifetime issues into
code that uses it. The programmer must ensure that the data that a <code class="computeroutput"><span class="identifier">string_ref</span></code> refers to exists as long as the
<code class="computeroutput"><span class="identifier">string_ref</span></code> does.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="string_ref.examples"></a><a class="link" href="string_ref.html#string_ref.examples" title="Examples">Examples</a>
</h2></div></div></div>
<p>
Integrating <code class="computeroutput"><span class="identifier">string_ref</span></code> into
your code is fairly simple. Wherever you pass a <code class="computeroutput"><span class="keyword">const</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span></code>
or <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> as a parameter, that's a candidate
for passing a <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span></code>.
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span><span class="identifier">bar</span> <span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">bar</span><span class="special">.</span><span class="identifier">substr</span> <span class="special">(</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span> <span class="special">);</span>
<span class="special">}</span>
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="string">"ABCDEFG"</span> <span class="special">).</span><span class="identifier">front</span><span class="special">()</span> <span class="special">==</span> <span class="char">'C'</span> <span class="special">)</span> <span class="special">{</span> <span class="comment">/* do something */</span> <span class="special">}</span>
</pre>
<p>
Let's figure out what happens in this (contrived) example.
</p>
<p>
First, a temporary string is created from the string literal <code class="computeroutput"><span class="string">"ABCDEFG"</span></code>, and it is passed (by reference)
to the routine <code class="computeroutput"><span class="identifier">extract_part</span></code>.
Then a second string is created in the call <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">::</span><span class="identifier">substr</span></code>
and returned to <code class="computeroutput"><span class="identifier">extract_part</span></code>
(this copy may be elided by RVO). Then <code class="computeroutput"><span class="identifier">extract_part</span></code>
returns that string back to the caller (again this copy may be elided). The
first temporary string is deallocated, and <code class="computeroutput"><span class="identifier">front</span></code>
is called on the second string, and then it is deallocated as well.
</p>
<p>
Two <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>s are created, and two copy operations.
That's (potentially) four memory allocations and deallocations, and the associated
copying of data.
</p>
<p>
Now let's look at the same code with <code class="computeroutput"><span class="identifier">string_ref</span></code>:
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span> <span class="identifier">bar</span> <span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">bar</span><span class="special">.</span><span class="identifier">substr</span> <span class="special">(</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span> <span class="special">);</span>
<span class="special">}</span>
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="string">"ABCDEFG"</span> <span class="special">).</span><span class="identifier">front</span><span class="special">()</span> <span class="special">==</span> <span class="string">"C"</span> <span class="special">)</span> <span class="special">{</span> <span class="comment">/* do something */</span> <span class="special">}</span>
</pre>
<p>
No memory allocations. No copying of character data. No changes to the code
other than the types. There are two <code class="computeroutput"><span class="identifier">string_ref</span></code>s
created, and two <code class="computeroutput"><span class="identifier">string_ref</span></code>s
copied, but those are cheap operations.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="string_ref.reference"></a><a class="link" href="string_ref.html#string_ref.reference" title="Reference">Reference </a>
</h2></div></div></div>
<p>
The header file "string_ref.hpp" defines a template <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">basic_string_ref</span></code>,
and four specializations - for <code class="computeroutput"><span class="keyword">char</span></code>
/ <code class="computeroutput"><span class="keyword">wchar_t</span></code> / <code class="computeroutput"><span class="keyword">char16_t</span></code>
/ <code class="computeroutput"><span class="keyword">char32_t</span></code> .
</p>
<p>
<code class="computeroutput"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">utility</span><span class="special">/</span><span class="identifier">string_ref</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span></code>
</p>
<p>
Construction and copying:
</p>
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span> <span class="special">();</span> <span class="comment">// Constructs an empty string_ref</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">str</span><span class="special">);</span> <span class="comment">// Constructs from a NULL-terminated string</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">str</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">len</span><span class="special">);</span> <span class="comment">// Constructs from a pointer, length pair</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Allocator</span><span class="special">&gt;</span>
<span class="identifier">basic_string_ref</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special">&lt;</span><span class="identifier">charT</span><span class="special">,</span> <span class="identifier">traits</span><span class="special">,</span> <span class="identifier">Allocator</span><span class="special">&gt;&amp;</span> <span class="identifier">str</span><span class="special">);</span> <span class="comment">// Constructs from a std::string</span>
<span class="identifier">basic_string_ref</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">basic_string_ref</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">);</span>
<span class="identifier">basic_string_ref</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="keyword">const</span> <span class="identifier">basic_string_ref</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">);</span>
</pre>
<p>
<code class="computeroutput"><span class="identifier">string_ref</span></code> does not define
a move constructor nor a move-assignment operator because copying a <code class="computeroutput"><span class="identifier">string_ref</span></code> is just a cheap as moving one.
</p>
<p>
Basic container-like functions:
</p>
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">size</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">length</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">max_size</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">bool</span> <span class="identifier">empty</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="comment">// All iterators are const_iterators</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">begin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">cbegin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">end</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">cend</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">const_reverse_iterator</span> <span class="identifier">rbegin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">const_reverse_iterator</span> <span class="identifier">crbegin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">const_reverse_iterator</span> <span class="identifier">rend</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">const_reverse_iterator</span> <span class="identifier">crend</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
</pre>
<p>
Access to the individual elements (all of which are const):
</p>
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">[](</span><span class="identifier">size_type</span> <span class="identifier">pos</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&amp;</span> <span class="identifier">at</span><span class="special">(</span><span class="identifier">size_t</span> <span class="identifier">pos</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&amp;</span> <span class="identifier">front</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&amp;</span> <span class="identifier">back</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">data</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
</pre>
<p>
Modifying the <code class="computeroutput"><span class="identifier">string_ref</span></code> (but
not the underlying data):
</p>
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">clear</span><span class="special">();</span>
<span class="keyword">void</span> <span class="identifier">remove_prefix</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">n</span><span class="special">);</span>
<span class="keyword">void</span> <span class="identifier">remove_suffix</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">n</span><span class="special">);</span>
</pre>
<p>
Searching:
</p>
<pre class="programlisting"><span class="identifier">size_type</span> <span class="identifier">find</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">rfind</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">rfind</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_first_of</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_last_of</span> <span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_first_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_last_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_first_not_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_first_not_of</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_last_not_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_last_not_of</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
</pre>
<p>
String-like operations:
</p>
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span> <span class="identifier">substr</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">pos</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">n</span><span class="special">=</span><span class="identifier">npos</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span> <span class="comment">// Creates a new string_ref</span>
<span class="keyword">bool</span> <span class="identifier">starts_with</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="keyword">bool</span> <span class="identifier">starts_with</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">x</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="keyword">bool</span> <span class="identifier">ends_with</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="keyword">bool</span> <span class="identifier">ends_with</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">x</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
</pre>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="string_ref.history"></a><a class="link" href="string_ref.html#string_ref.history" title="History">History</a>
</h2></div></div></div>
<h4>
<a name="string_ref.history.h0"></a>
<span><a name="string_ref.history.boost_1_53"></a></span><a class="link" href="string_ref.html#string_ref.history.boost_1_53">boost
1.53</a>
</h4>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
Introduced
</li></ul></div>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><p><small>Last revised: October 27, 2013 at 21:01:34 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td>
</tr></table>
<hr>
<div class="spirit-nav"></div>
</body>
</html>

167
doc/string_ref.qbk Normal file
View File

@ -0,0 +1,167 @@
[/
/ Copyright (c) 2012 Marshall Clow
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[article String_Ref
[quickbook 1.5]
[authors [Clow, Marshall]]
[copyright 2012 Marshall Clow]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
[@http://www.boost.org/LICENSE_1_0.txt])
]
]
[/===============]
[section Overview]
[/===============]
Boost.StringRef is an implementation of Jeffrey Yaskin's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html N3442:
string_ref: a non-owning reference to a string].
When you are parsing/processing strings from some external source, frequently you want to pass a piece of text to a procedure for specialized processing. The canonical way to do this is as a `std::string`, but that has certain drawbacks:
1) If you are processing a buffer of text (say a HTTP response or the contents of a file), then you have to create the string from the text you want to pass, which involves memory allocation and copying of data.
2) if a routine receives a constant `std::string` and wants to pass a portion of that string to another routine, then it must create a new string of that substring.
3) A routine receives a constant `std::string` and wants to return a portion of the string, then it must create a new string to return.
`string_ref` is designed to solve these efficiency problems. A `string_ref` is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of `std::string`. A `string_ref` is cheap to create, copy and pass by value, because it does not actually own the storage that it points to.
A `string_ref` is implemented as a small struct that contains a pointer to the start of the character data and a count. A `string_ref` is cheap to create and cheap to copy.
`string_ref` acts as a container; it includes all the methods that you would expect in a container, including iteration support, `operator []`, `at` and `size`. It can be used with any of the iterator-based algorithms in the STL - as long as you don't need to change the underlying data (`sort` and `remove`, for example, will not work)
Besides generic container functionality, `string_ref` provides a subset of the interface of `std::string`. This makes it easy to replace parameters of type `const std::string &` with `boost::string_ref`. Like `std::string`, `string_ref` has a static member variable named `npos` to denote the result of failed searches, and to mean "the end".
Because a `string_ref` does not own the data that it "points to", it introduces lifetime issues into code that uses it. The programmer must ensure that the data that a `string_ref` refers to exists as long as the `string_ref` does.
[endsect]
[/===============]
[section Examples]
[/===============]
Integrating `string_ref` into your code is fairly simple. Wherever you pass a `const std::string &` or `std::string` as a parameter, that's a candidate for passing a `boost::string_ref`.
std::string extract_part ( const std::string &bar ) {
return bar.substr ( 2, 3 );
}
if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { /* do something */ }
Let's figure out what happens in this (contrived) example.
First, a temporary string is created from the string literal `"ABCDEFG"`, and it is passed (by reference) to the routine `extract_part`. Then a second string is created in the call `std::string::substr` and returned to `extract_part` (this copy may be elided by RVO). Then `extract_part` returns that string back to the caller (again this copy may be elided). The first temporary string is deallocated, and `front` is called on the second string, and then it is deallocated as well.
Two `std::string`s are created, and two copy operations. That's (potentially) four memory allocations and deallocations, and the associated copying of data.
Now let's look at the same code with `string_ref`:
boost::string_ref extract_part ( boost::string_ref bar ) {
return bar.substr ( 2, 3 );
}
if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ }
No memory allocations. No copying of character data. No changes to the code other than the types. There are two `string_ref`s created, and two `string_ref`s copied, but those are cheap operations.
[endsect]
[/=================]
[section:reference Reference ]
[/=================]
The header file "string_ref.hpp" defines a template `boost::basic_string_ref`, and four specializations - for `char` / `wchar_t` / `char16_t` / `char32_t` .
`#include <boost/utility/string_ref.hpp>`
Construction and copying:
BOOST_CONSTEXPR basic_string_ref (); // Constructs an empty string_ref
BOOST_CONSTEXPR basic_string_ref(const charT* str); // Constructs from a NULL-terminated string
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len); // Constructs from a pointer, length pair
template<typename Allocator>
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str); // Constructs from a std::string
basic_string_ref (const basic_string_ref &rhs);
basic_string_ref& operator=(const basic_string_ref &rhs);
`string_ref` does not define a move constructor nor a move-assignment operator because copying a `string_ref` is just a cheap as moving one.
Basic container-like functions:
BOOST_CONSTEXPR size_type size() const ;
BOOST_CONSTEXPR size_type length() const ;
BOOST_CONSTEXPR size_type max_size() const ;
BOOST_CONSTEXPR bool empty() const ;
// All iterators are const_iterators
BOOST_CONSTEXPR const_iterator begin() const ;
BOOST_CONSTEXPR const_iterator cbegin() const ;
BOOST_CONSTEXPR const_iterator end() const ;
BOOST_CONSTEXPR const_iterator cend() const ;
const_reverse_iterator rbegin() const ;
const_reverse_iterator crbegin() const ;
const_reverse_iterator rend() const ;
const_reverse_iterator crend() const ;
Access to the individual elements (all of which are const):
BOOST_CONSTEXPR const charT& operator[](size_type pos) const ;
const charT& at(size_t pos) const ;
BOOST_CONSTEXPR const charT& front() const ;
BOOST_CONSTEXPR const charT& back() const ;
BOOST_CONSTEXPR const charT* data() const ;
Modifying the `string_ref` (but not the underlying data):
void clear();
void remove_prefix(size_type n);
void remove_suffix(size_type n);
Searching:
size_type find(basic_string_ref s) const ;
size_type find(charT c) const ;
size_type rfind(basic_string_ref s) const ;
size_type rfind(charT c) const ;
size_type find_first_of(charT c) const ;
size_type find_last_of (charT c) const ;
size_type find_first_of(basic_string_ref s) const ;
size_type find_last_of(basic_string_ref s) const ;
size_type find_first_not_of(basic_string_ref s) const ;
size_type find_first_not_of(charT c) const ;
size_type find_last_not_of(basic_string_ref s) const ;
size_type find_last_not_of(charT c) const ;
String-like operations:
BOOST_CONSTEXPR basic_string_ref substr(size_type pos, size_type n=npos) const ; // Creates a new string_ref
bool starts_with(charT c) const ;
bool starts_with(basic_string_ref x) const ;
bool ends_with(charT c) const ;
bool ends_with(basic_string_ref x) const ;
[endsect]
[/===============]
[section History]
[/===============]
[heading boost 1.53]
* Introduced
[endsect]

View File

@ -21,6 +21,7 @@
<BR>
<BR>
Copyright 2003 Jaakko J&auml;rvi, Jeremiah Willcock, Andrew Lumsdaine.<BR>
Copyright 2011 Matt Calabrese.<BR>
<BR>
<!--TOC section Introduction-->
@ -81,7 +82,7 @@ definitions to find this out. Instantiating the latter definition with
<PRE>int::result_type negate(const int&amp;);
</PRE>
where the return type is invalid. If this was an error, adding an unrelated function template
where the return type is invalid. If this were an error, adding an unrelated function template
(that was never called) could break otherwise valid code.
Due to the SFINAE principle the above example is not, however, erroneous.
The latter definition of <TT>negate</TT> is simply removed from the overload resolution set.<BR>
@ -154,6 +155,7 @@ typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t) { return t; }
</PRE>
<!--TOC section Using <TT>enable_if</TT>-->
<H2><A NAME="htoc5">3</A>&nbsp;&nbsp;Using <TT>enable_if</TT></H2><!--SEC END -->
@ -162,8 +164,19 @@ foo(T t) { return t; }
The <TT>enable_if</TT> templates are defined in
<TT>boost/utility/enable_if.hpp</TT>, which is included by <TT>boost/utility.hpp</TT>.<BR>
<BR>
The <TT>enable_if</TT> template can be used either as the return type, or as an
extra argument. For example, the <TT>foo</TT> function in the previous section could also be written
With respect to function templates, <TT>enable_if</TT> can be used in multiple different ways:
<UL>
<LI>As the return type of an instantiatied function
<LI>As an extra parameter of an instantiated function
<LI>As an extra template parameter (useful only in a compiler that supports C++0x default
arguments for function template parameters, see <A href="#sec:enable_if_0x">Enabling function
templates in C++0x</a> for details)
</UL>
In the previous section, the return type form of <TT>enable_if</TT> was shown. As an example
of using the form of <TT>enable_if</TT> that works via an extra function parameter, the
<TT>foo</TT> function in the previous section could also be written
as:
<PRE>template &lt;class T&gt;
T foo(T t, typename enable_if&lt;boost::is_arithmetic&lt;T&gt; &gt;::type* dummy = 0);
@ -173,18 +186,80 @@ a default value to keep the parameter hidden from client code.
Note that the second template argument was not given to <TT>enable_if</TT>, as the default
<TT>void</TT> gives the desired behavior.<BR>
<BR>
Whether to write the enabler as an argument or within the return type is
largely a matter of taste, but for certain functions, only one
alternative is possible:
Which way to write the enabler is largely a matter of taste, but for certain functions, only a
subset of the options is possible:
<UL><LI>
Operators have a fixed number of arguments, thus <TT>enable_if</TT> must be used in the return type.
<LI>Constructors and destructors do not have a return type; an extra argument is the only option.
<LI>There does not seem to be a way to specify an enabler for a conversion operator. Converting constructors,
however, can have enablers as extra default arguments.
Many operators have a fixed number of arguments, thus <TT>enable_if</TT> must be used either in the
return type or in an extra template parameter.
<LI>Functions that have a variadic parameter list must use either the return type form or an extra
template parameter.
<LI>Constructors do not have a return type so you must use either an extra function parameter or an
extra template parameter.
<LI>Constructors that have a variadic parameter list must an extra template parameter.
<LI>Conversion operators can only be written with an extra template parameter.
</UL>
<!--TOC subsection Enabling function templates in C++0x-->
<A NAME="sec:enable_if_0x"></A>
<H3><A NAME="htoc7">3.1</A>&nbsp;&nbsp;Enabling function templates in C++0x</H3><!--SEC END -->
In a compiler which supports C++0x default arguments for function template parameters, you can
enable and disable function templates by adding an additional template parameter. This approach
works in all situations where you would use either the return type form of <TT>enable_if</TT> or
the function parameter form, including operators, constructors, variadic function templates, and
even overloaded conversion operations.
As an example:
<PRE>#include &lt;boost/type_traits/is_arithmetic.hpp&gt;
#include &lt;boost/type_traits/is_pointer.hpp&gt;
#include &lt;boost/utility/enable_if.hpp&gt;
class test
{
public:
// A constructor that works for any argument list of size 10
template&lt; class... T
, typename boost::enable_if_c&lt; sizeof...( T ) == 10, int &gt;::type = 0
&gt;
test( T&amp;&amp;... );
// A conversion operation that can convert to any arithmetic type
template&lt; class T
, typename boost::enable_if&lt; boost::is_arithmetic&lt; T &gt;, int &gt;::type = 0
&gt;
operator T() const;
// A conversion operation that can convert to any pointer type
template&lt; class T
, typename boost::enable_if&lt; boost::is_pointer&lt; T &gt;, int &gt;::type = 0
&gt;
operator T() const;
};
int main()
{
// Works
test test_( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );
// Fails as expected
test fail_construction( 1, 2, 3, 4, 5 );
// Works by calling the conversion operator enabled for arithmetic types
int arithmetic_object = test_;
// Works by calling the conversion operator enabled for pointer types
int* pointer_object = test_;
// Fails as expected
struct {} fail_conversion = test_;
}
</PRE>
<!--TOC subsection Enabling template class specializations-->
<H3><A NAME="htoc6">3.1</A>&nbsp;&nbsp;Enabling template class specializations</H3><!--SEC END -->
<H3><A NAME="htoc7">3.2</A>&nbsp;&nbsp;Enabling template class specializations</H3><!--SEC END -->
<A NAME="sec:enable_if_classes"></A>
Class template specializations can be enabled or disabled with <TT>enable_if</TT>.
@ -210,7 +285,7 @@ is the correct value.<BR>
<BR>
<!--TOC subsection Overlapping enabler conditions-->
<H3><A NAME="htoc7">3.2</A>&nbsp;&nbsp;Overlapping enabler conditions</H3><!--SEC END -->
<H3><A NAME="htoc8">3.3</A>&nbsp;&nbsp;Overlapping enabler conditions</H3><!--SEC END -->
<A NAME="sec:overlapping_conditions"></A>
Once the compiler has examined the enabling conditions and included the
@ -239,7 +314,7 @@ partial specializations as well.<BR>
<BR>
<!--TOC subsection Lazy <TT>enable_if</TT>-->
<H3><A NAME="htoc8">3.3</A>&nbsp;&nbsp;Lazy <TT>enable_if</TT></H3><!--SEC END -->
<H3><A NAME="htoc9">3.4</A>&nbsp;&nbsp;Lazy <TT>enable_if</TT></H3><!--SEC END -->
<A NAME="sec:enable_if_lazy"></A>
In some cases it is necessary to avoid instantiating part of a
@ -285,7 +360,7 @@ above example, <TT>is_multipliable&lt;T, U&gt;::value</TT> defines when
<BR>
<!--TOC subsection Compiler workarounds-->
<H3><A NAME="htoc9">3.4</A>&nbsp;&nbsp;Compiler workarounds</H3><!--SEC END -->
<H3><A NAME="htoc10">3.5</A>&nbsp;&nbsp;Compiler workarounds</H3><!--SEC END -->
<A NAME="sec:workarounds"></A>
Some compilers flag functions as ambiguous if the only distinguishing factor is a different
@ -367,9 +442,9 @@ David Vandevoorde and Nicolai&nbsp;M. Josuttis.
Addison-Wesley, 2002.</DL>
<hr/>
<p>Copyright Jaakko J&auml;rvi, Jeremiah Willcock and Andrew Lumsdaine<BR>
<EM>{jajarvi|jewillco|lums}@osl.iu.edu</EM><BR>
Indiana University<BR>
<p>Copyright Jaakko J&auml;rvi<sup>*</sup>, Jeremiah Willcock<sup>*</sup>, Andrew Lumsdaine<sup>*</sup>, Matt Calabrese<BR>
<EM>{jajarvi|jewillco|lums}@osl.iu.edu, rivorus@gmail.com</EM><BR>
<sup>*</sup>Indiana University<BR>
Open Systems Lab<br/>
Use, modification and distribution are subject to the
Boost Software License, Version 1.0.
@ -386,4 +461,4 @@ or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
</EM><A HREF="http://pauillac.inria.fr/~maranget/hevea/index.html"><EM>H<FONT SIZE=2><sup>E</sup></FONT>V<FONT SIZE=2><sup>E</sup></FONT>A</EM></A><EM>.
</EM></BLOCKQUOTE>
</BODY>
</HTML>
</HTML>

View File

@ -0,0 +1,44 @@
# Copyright (C) 2009-2012 Lorenzo Caminiti
# Distributed under the Boost Software License, Version 1.0
# (see accompanying file LICENSE_1_0.txt or a copy at
# http://www.boost.org/LICENSE_1_0.txt)
# Home at http://www.boost.org/libs/utility/identity_type
import quickbook ;
using boostbook ;
doxygen reference : ../../../../boost/utility/identity_type.hpp
: <reftitle>"Reference"
<doxygen:param>PREDEFINED="DOXYGEN"
<doxygen:param>QUIET=YES
<doxygen:param>WARN_IF_UNDOCUMENTED=NO
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
<doxygen:param>HIDE_UNDOC_CLASSES=YES
<doxygen:param>ALIASES=" Params=\"<b>Parameters:</b> <table border="0">\" Param{2}=\"<tr><td><b><tt>\\1</tt></b></td><td>\\2</td></tr>\" EndParams=\"</table>\" Returns=\"<b>Returns:</b>\" Note=\"<b>Note:</b>\" Warning=\"<b>Warning:</b>\" See=\"<b>See:</b>\" RefSect{2}=\"\\xmlonly<link linkend='boost_utility_identitytype.\\1'>\\2</link>\\endxmlonly\" RefClass{1}=\"\\xmlonly<computeroutput><classname alt='\\1'>\\1</classname></computeroutput>\\endxmlonly\" RefFunc{1}=\"\\xmlonly<computeroutput><functionname alt='\\1'>\\1</functionname></computeroutput>\\endxmlonly\" RefMacro{1}=\"\\xmlonly<computeroutput><macroname alt='\\1'>\\1</macroname></computeroutput>\\endxmlonly\" "
;
# This target must be called "index" so to generate "index.html" file.
xml index : identity_type.qbk : <dependency>reference ;
boostbook doc : index
: <location>html
<format>onehtml
<xsl:param>toc.section.depth=0
<xsl:param>html.stylesheet=../../../../../doc/src/boostbook.css
<xsl:param>boost.root=../../../../..
;
#
# This is very imperfect - it results in both html and pdf docs being built,
# for some reason I can't get the "onehtml" format specified above to play nice
# with the usual incantations for mixed pdf/html builds. JM 06/2012.
#
boostbook pdf_doc : index
:
<format>pdf
<format>html:<build>no
;
install pdf_doc_install : pdf_doc : <location>. <name>identity_type.pdf <install-type>PDF ;
explicit pdf_doc_install ;

View File

@ -0,0 +1,252 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Boost.Utility/IdentityType 1.0.0</title><link rel="stylesheet" type="text/css" href="../../../../../doc/src/boostbook.css"><meta name="generator" content="DocBook XSL Stylesheets V1.76.1"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="chapter" title="Boost.Utility/IdentityType 1.0.0"><div class="titlepage"><div><div><h2 class="title"><a name="boost_utility_identitytype"></a>Boost.Utility/IdentityType 1.0.0</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Lorenzo</span> <span class="surname">Caminiti <code class="email">&lt;<a class="email" href="mailto:lorcaminiti@gmail.com">lorcaminiti@gmail.com</a>&gt;</code></span></h3></div></div><div><p class="copyright">Copyright © 2009-2012 Lorenzo
Caminiti</p></div><div><div class="legalnotice" title="Legal Notice"><a name="boost_utility_identitytype.legal"></a><p>
Distributed under the Boost Software License, Version 1.0 (see accompanying
file LICENSE_1_0.txt or a copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p></div></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#boost_utility_identitytype.motivation">Motivation</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.solution">Solution</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.templates">Templates</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.abstract_types">Abstract Types</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.annex__usage">Annex: Usage</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.annex__implementation">Annex:
Implementation</a></span></dt><dt><span class="section"><a href="#reference">Reference</a></span></dt></dl></div><p>
This library allows to wrap types within round parenthesis so they can always
be passed as macro parameters.
</p><div class="section boost_utility_identitytype_motivation" title="Motivation"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.motivation"></a><a class="link" href="#boost_utility_identitytype.motivation" title="Motivation">Motivation</a></h2></div></div></div><p>
Consider the following macro which declares a variable named <code class="computeroutput"><span class="identifier">var</span></code><code class="literal"><span class="emphasis"><em>n</em></span></code>
with the specified <code class="literal"><span class="emphasis"><em>type</em></span></code> (see also
<a href="../../test/var_error.cpp" target="_top"><code class="literal">var_error.cpp</code></a>):
</p><p>
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">VAR</span><span class="special">(</span><span class="identifier">type</span><span class="special">,</span> <span class="identifier">n</span><span class="special">)</span> <span class="identifier">type</span> <span class="identifier">var</span> <span class="error">#</span><span class="preprocessor"># n</span>
<span class="identifier">VAR</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="number">1</span><span class="special">);</span> <span class="comment">// OK.</span>
<span class="identifier">VAR</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">&gt;,</span> <span class="number">2</span><span class="special">);</span> <span class="comment">// Error.</span>
</pre><p>
</p><p>
The first macro invocation works correctly declaring a variable named <code class="computeroutput"><span class="identifier">var1</span></code> of type <code class="computeroutput"><span class="keyword">int</span></code>.
However, the second macro invocation fails generating a preprocessor error
similar to the following:
</p><pre class="programlisting">error: macro "VAR" passed 3 arguments, but takes just 2
</pre><p>
That is because the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span></code> type passed as the first macro parameter
contains a comma <code class="computeroutput"><span class="special">,</span></code> not wrapped
by round parenthesis <code class="computeroutput"><span class="special">()</span></code>. The preprocessor
interprets that unwrapped comma as a separation between macro parameters concluding
that a total of three (and not two) parameters are passed to the macro in the
following order:
</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span></code>
</li><li class="listitem">
<code class="computeroutput"><span class="keyword">char</span><span class="special">&gt;</span></code>
</li><li class="listitem">
<code class="computeroutput"><span class="number">2</span></code>
</li></ol></div><p>
Note that, differently from the compiler, the preprocessor only recognizes
round parenthesis <code class="computeroutput"><span class="special">()</span></code>. Angular
<code class="computeroutput"><span class="special">&lt;&gt;</span></code> and squared <code class="computeroutput"><span class="special">[]</span></code> parenthesis are not recognized by the preprocessor
when parsing macro parameters.
</p></div><div class="section boost_utility_identitytype_solution" title="Solution"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.solution"></a><a class="link" href="#boost_utility_identitytype.solution" title="Solution">Solution</a></h2></div></div></div><p>
In some cases, it might be possible to workaround this issue by avoiding to
pass the type expression to the macro all together. For example, in the case
above a <code class="computeroutput"><span class="keyword">typedef</span></code> could have been
used to specify the type expression with the commas outside the macro (see
also <a href="../../test/var.cpp" target="_top"><code class="literal">var.cpp</code></a>):
</p><p>
</p><pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">&gt;</span> <span class="identifier">map_type</span><span class="special">;</span>
<span class="identifier">VAR</span><span class="special">(</span><span class="identifier">map_type</span><span class="special">,</span> <span class="number">3</span><span class="special">);</span> <span class="comment">// OK.</span>
</pre><p>
</p><p>
When this is neither possible nor desired (e.g., see the function template
<code class="computeroutput"><span class="identifier">f</span></code> in the section below), this
library header <code class="computeroutput"><a class="link" href="#header.boost.utility.identity_type_hpp" title="Header &lt;boost/utility/identity_type.hpp&gt;">boost/utility/identity_type.hpp</a></code>
defines a macro <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
which can be used to workaround the issue while keeping the type expression
as one of the macro parameters (see also <a href="../../test/var.cpp" target="_top"><code class="literal">var.cpp</code></a>).
</p><p>
</p><pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">utility</span><span class="special">/</span><span class="identifier">identity_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">VAR</span><span class="special">(</span><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">&gt;)),</span> <span class="number">4</span><span class="special">);</span> <span class="comment">// OK.</span>
</pre><p>
</p><p>
The <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> macro
expands to an expression that evaluates (at compile-time) to the specified
type. The specified type is never split into multiple macro parameters because
it is always wrapped by a set of extra round parenthesis <code class="computeroutput"><span class="special">()</span></code>.
In fact, a total of two sets of round parenthesis must be used: The parenthesis
to invoke the macro <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(...)</span></code> plus the inner parenthesis to wrap the
type passed to the macro <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((...))</span></code>.
</p><p>
This macro works on any <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/standards" target="_top">C++03</a>
compiler (and it does not use <a href="http://en.wikipedia.org/wiki/Variadic_macro" target="_top">variadic
macros</a>). <sup>[<a name="boost_utility_identitytype.solution.f0" href="#ftn.boost_utility_identitytype.solution.f0" class="footnote">1</a>]</sup> The authors originally developed and tested this library using
GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features enabled
<code class="computeroutput"><span class="special">-</span><span class="identifier">std</span><span class="special">=</span><span class="identifier">c</span><span class="special">++</span><span class="number">0</span><span class="identifier">x</span></code>) on Cygwin
and Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7. See the library <a href="http://www.boost.org/development/tests/release/developer/utility-identity_type.html" target="_top">regressions
test results</a> for more information on supported compilers and platforms.
</p></div><div class="section boost_utility_identitytype_templates" title="Templates"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.templates"></a><a class="link" href="#boost_utility_identitytype.templates" title="Templates">Templates</a></h2></div></div></div><p>
This macro must be prefixed by <code class="computeroutput"><span class="keyword">typename</span></code>
when used within templates. For example, let's program a macro that declares
a function parameter named <code class="computeroutput"><span class="identifier">arg</span></code><code class="literal"><span class="emphasis"><em>n</em></span></code>
with the specified <code class="literal"><span class="emphasis"><em>type</em></span></code> (see also
<a href="../../test/template.cpp" target="_top"><code class="literal">template.cpp</code></a>):
</p><p>
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">ARG</span><span class="special">(</span><span class="identifier">type</span><span class="special">,</span> <span class="identifier">n</span><span class="special">)</span> <span class="identifier">type</span> <span class="identifier">arg</span> <span class="error">#</span><span class="preprocessor"># n</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span> <span class="comment">// Prefix macro with `typename` in templates.</span>
<span class="identifier">ARG</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&gt;)),</span> <span class="number">1</span><span class="special">)</span>
<span class="special">)</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">arg1</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="special">}</span>
</pre><p>
</p><p>
</p><pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">&gt;</span> <span class="identifier">a</span><span class="special">;</span>
<span class="identifier">a</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special">=</span> <span class="char">'a'</span><span class="special">;</span>
<span class="identifier">f</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">&gt;(</span><span class="identifier">a</span><span class="special">);</span> <span class="comment">// OK...</span>
<span class="comment">// f(a); // ... but error.</span>
</pre><p>
</p><p>
However, note that the template parameter <code class="computeroutput"><span class="keyword">char</span></code>
must be manually specified when invoking the function as in <code class="computeroutput"><span class="identifier">f</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">&gt;(</span><span class="identifier">a</span><span class="special">)</span></code>. In fact,
when the <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
macro is used to wrap a function template parameter, the template parameter
can no longer be automatically deduced by the compiler form the function call
as <code class="computeroutput"><span class="identifier">f</span><span class="special">(</span><span class="identifier">a</span><span class="special">)</span></code> would
have done. <sup>[<a name="boost_utility_identitytype.templates.f0" href="#ftn.boost_utility_identitytype.templates.f0" class="footnote">2</a>]</sup> (This limitation does not apply to class templates because class
template parameters must always be explicitly specified.) In other words, without
using the <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
macro, C++ would normally be able to automatically deduce the function template
parameter as shown below:
</p><p>
</p><pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">void</span> <span class="identifier">g</span><span class="special">(</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">arg1</span>
<span class="special">)</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">arg1</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="special">}</span>
</pre><p>
</p><p>
</p><pre class="programlisting"><span class="identifier">g</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">&gt;(</span><span class="identifier">a</span><span class="special">);</span> <span class="comment">// OK...</span>
<span class="identifier">g</span><span class="special">(</span><span class="identifier">a</span><span class="special">);</span> <span class="comment">// ... and also OK.</span>
</pre><p>
</p></div><div class="section boost_utility_identitytype_abstract_types" title="Abstract Types"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.abstract_types"></a><a class="link" href="#boost_utility_identitytype.abstract_types" title="Abstract Types">Abstract Types</a></h2></div></div></div><p>
On some compilers (e.g., GCC), using this macro on abstract types (i.e., classes
with one or more pure virtual functions) generates a compiler error. This can
be avoided by manipulating the type adding and removing a reference to it.
</p><p>
Let's program a macro that performs a static assertion on a <a href="http://en.wikipedia.org/wiki/Template_metaprogramming" target="_top">Template
Meta-Programming</a> (TMP) meta-function (similarly to Boost.MPL <a href="http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/assert.html" target="_top"><code class="computeroutput"><span class="identifier">BOOST_MPL_ASSERT</span></code></a>). The <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> macro can be used
to pass a meta-function with multiple template parameters to the assert macro
(so to handle the commas separating the template parameters). In this case,
if the meta-function is an abstract type, it needs to be manipulated adding
and removing a reference to it (see also <a href="../../test/abstract.cpp" target="_top"><code class="literal">abstract.cpp</code></a>):
</p><p>
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TMP_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_STATIC_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">::</span><span class="identifier">value</span><span class="special">)</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">bool</span> <span class="identifier">b</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">abstract</span> <span class="special">{</span>
<span class="keyword">static</span> <span class="keyword">const</span> <span class="keyword">bool</span> <span class="identifier">value</span> <span class="special">=</span> <span class="identifier">b</span><span class="special">;</span>
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="comment">// Pure virtual function.</span>
<span class="special">};</span>
<span class="identifier">TMP_ASSERT</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">remove_reference</span><span class="special">&lt;</span> <span class="comment">// Add and remove</span>
<span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span> <span class="comment">// reference for</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">add_reference</span><span class="special">&lt;</span> <span class="comment">// abstract type.</span>
<span class="identifier">abstract</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">true</span><span class="special">&gt;</span>
<span class="special">&gt;::</span><span class="identifier">type</span>
<span class="special">))</span>
<span class="special">&gt;::</span><span class="identifier">type</span>
<span class="special">);</span>
</pre><p>
</p></div><div class="section boost_utility_identitytype_annex__usage" title="Annex: Usage"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.annex__usage"></a><a class="link" href="#boost_utility_identitytype.annex__usage" title="Annex: Usage">Annex: Usage</a></h2></div></div></div><p>
The <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> macro
can be used either when calling a user-defined macro (as shown by the examples
so far), or internally when implementing a user-defined macro (as shown below).
When <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> is
used in the implementation of the user-defined macro, the caller of the user
macro will have to specify the extra parenthesis (see also <a href="../../test/paren.cpp" target="_top"><code class="literal">paren.cpp</code></a>):
</p><p>
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TMP_ASSERT_PAREN</span><span class="special">(</span><span class="identifier">parenthesized_metafunction</span><span class="special">)</span> <span class="special">\</span>
<span class="comment">/* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */</span> <span class="special">\</span>
<span class="identifier">BOOST_STATIC_ASSERT</span><span class="special">(</span><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(</span><span class="identifier">parenthesized_metafunction</span><span class="special">)::</span><span class="identifier">value</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">TMP_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_STATIC_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">::</span><span class="identifier">value</span><span class="special">)</span>
<span class="comment">// Specify only extra parenthesis `((...))`.</span>
<span class="identifier">TMP_ASSERT_PAREN</span><span class="special">((</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&gt;));</span>
<span class="comment">// Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro.</span>
<span class="identifier">TMP_ASSERT</span><span class="special">(</span><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&gt;)));</span>
</pre><p>
</p><p>
However, note that the caller will <span class="emphasis"><em>always</em></span> have to specify
the extra parenthesis even when the macro parameters contain no comma:
</p><p>
</p><pre class="programlisting"><span class="identifier">TMP_ASSERT_PAREN</span><span class="special">((</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special">&lt;</span><span class="keyword">int</span> <span class="keyword">const</span><span class="special">&gt;));</span> <span class="comment">// Always extra `((...))`.</span>
<span class="identifier">TMP_ASSERT</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special">&lt;</span><span class="keyword">int</span> <span class="keyword">const</span><span class="special">&gt;);</span> <span class="comment">// No extra `((...))` and no macro.</span>
</pre><p>
</p><p>
In some cases, using <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
in the implementation of the user-defined macro might provide the best syntax
for the caller. For example, this is the case for <code class="computeroutput"><span class="identifier">BOOST_MPL_ASSERT</span></code>
because the majority of template meta-programming expressions contain unwrapped
commas so it is less confusing for the user to always specify the extra parenthesis
<code class="computeroutput"><span class="special">((...))</span></code> instead of using <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>:
</p><pre class="programlisting"><span class="identifier">BOOST_MPL_ASSERT</span><span class="special">((</span> <span class="comment">// Natural syntax.</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">and_</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span>
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_reference</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span>
<span class="special">&gt;</span>
<span class="special">));</span>
</pre><p>
However, in other situations it might be preferable to not require the extra
parenthesis in the common cases and handle commas as special cases using <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>. For example, this
is the case for <a href="http://www.boost.org/libs/local_function" target="_top"><code class="computeroutput"><span class="identifier">BOOST_LOCAL_FUNCTION</span></code></a> for which always
requiring the extra parenthesis <code class="computeroutput"><span class="special">((...))</span></code>
around the types would lead to an unnatural syntax for the local function signature:
</p><pre class="programlisting"><span class="keyword">int</span> <span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span> <span class="special">((</span><span class="keyword">int</span><span class="special">&amp;))</span> <span class="identifier">x</span><span class="special">,</span> <span class="special">((</span><span class="keyword">int</span><span class="special">&amp;))</span> <span class="identifier">y</span> <span class="special">)</span> <span class="special">{</span> <span class="comment">// Unnatural syntax.</span>
<span class="keyword">return</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">;</span>
<span class="special">}</span> <span class="identifier">BOOST_LOCAL_FUNCTION_NAME</span><span class="special">(</span><span class="identifier">add</span><span class="special">)</span>
</pre><p>
Instead requiring the user to specify <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
only when needed allows for the more natural syntax <code class="computeroutput"><span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span><span class="keyword">int</span><span class="special">&amp;</span>
<span class="identifier">x</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&amp;</span> <span class="identifier">y</span><span class="special">)</span></code> in the common cases when the parameter types
contain no comma (while still allowing to specify parameter types with commas
as special cases using <code class="computeroutput"><span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">&gt;))&amp;</span>
<span class="identifier">x</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&amp;</span> <span class="identifier">y</span><span class="special">)</span></code>).
</p></div><div class="section boost_utility_identitytype_annex__implementation" title="Annex: Implementation"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.annex__implementation"></a><a class="link" href="#boost_utility_identitytype.annex__implementation" title="Annex: Implementation">Annex:
Implementation</a></h2></div></div></div><p>
The implementation of this library macro is equivalent to the following: <sup>[<a name="boost_utility_identitytype.annex__implementation.f0" href="#ftn.boost_utility_identitytype.annex__implementation.f0" class="footnote">3</a>]</sup>
</p><pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">function_traits</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(</span><span class="identifier">parenthesized_type</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">function_traits</span><span class="special">&lt;</span><span class="keyword">void</span> <span class="identifier">parenthesized_type</span><span class="special">&gt;::</span><span class="identifier">arg1_type</span>
</pre><p>
Essentially, the type is wrapped between round parenthesis <code class="computeroutput"><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span>
<span class="keyword">char</span><span class="special">&gt;)</span></code>
so it can be passed as a single macro parameter even if it contains commas.
Then the parenthesized type is transformed into the type of a function returning
<code class="computeroutput"><span class="keyword">void</span></code> and with the specified type
as the type of the first and only argument <code class="computeroutput"><span class="keyword">void</span>
<span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">&gt;)</span></code>. Finally, the type of the first argument
<code class="computeroutput"><span class="identifier">arg1_type</span></code> is extracted at compile-time
using the <code class="computeroutput"><span class="identifier">function_traits</span></code> meta-function
therefore obtaining the original type from the parenthesized type (effectively
stripping the extra parenthesis from around the specified type).
</p></div><div class="section reference" title="Reference"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="reference"></a>Reference</h2></div></div></div><div class="section header_boost_utility_identity_type_hpp" title="Header &lt;boost/utility/identity_type.hpp&gt;"><div class="titlepage"><div><div><h3 class="title"><a name="header.boost.utility.identity_type_hpp"></a>Header &lt;<a href="../../../../../boost/utility/identity_type.hpp" target="_top">boost/utility/identity_type.hpp</a>&gt;</h3></div></div></div><p>Wrap type expressions with round parenthesis so they can be passed to macros even if they contain commas. </p><pre class="synopsis">
<a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a>(parenthesized_type)</pre><div class="refentry" title="Macro BOOST_IDENTITY_TYPE"><a name="BOOST_IDENTITY_TYPE"></a><div class="titlepage"></div><div class="refnamediv"><h2><span class="refentrytitle">Macro BOOST_IDENTITY_TYPE</span></h2><p>BOOST_IDENTITY_TYPE — This macro allows to wrap the specified type expression within extra round parenthesis so the type can be passed as a single macro parameter even if it contains commas (not already wrapped within round parenthesis). </p></div><h2 class="refsynopsisdiv-title">Synopsis</h2><div class="refsynopsisdiv"><pre class="synopsis"><span class="comment">// In header: &lt;<a class="link" href="#header.boost.utility.identity_type_hpp" title="Header &lt;boost/utility/identity_type.hpp&gt;">boost/utility/identity_type.hpp</a>&gt;
</span>BOOST_IDENTITY_TYPE(parenthesized_type)</pre></div><div class="refsect1" title="Description"><a name="id554262"></a><h2>Description</h2><p><span class="bold"><strong>Parameters:</strong></span> </p><div class="informaltable"><table class="table"><colgroup><col><col></colgroup><tbody><tr><td><span class="bold"><strong><code class="computeroutput">parenthesized_type</code></strong></span></td><td>The type expression to be passed as macro parameter wrapped by a single set of round parenthesis <code class="computeroutput">(...)</code>. This type expression can contain an arbitrary number of commas. </td></tr></tbody></table></div><p>
</p><p>This macro works on any C++03 compiler (it does not use variadic macros).</p><p>This macro must be prefixed by <code class="computeroutput">typename</code> when used within templates. Note that the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to be explicitly specified when calling the function template).</p><p>On some compilers (like GCC), using this macro on abstract types requires to add and remove a reference to the specified type. </p></div></div></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a id="ftn.boost_utility_identitytype.solution.f0" href="#boost_utility_identitytype.solution.f0" class="para">1</a>] </sup>
Using variadic macros, it would be possible to require a single set of extra
parenthesis <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(</span></code><code class="literal"><span class="emphasis"><em>type</em></span></code><code class="computeroutput"><span class="special">)</span></code> instead of two <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span></code><code class="literal"><span class="emphasis"><em>type</em></span></code><code class="computeroutput"><span class="special">))</span></code> but variadic macros are not part of C++03
(even if nowadays they are supported by most modern compilers and they are
also part of C++11).
</p></div><div class="footnote"><p><sup>[<a id="ftn.boost_utility_identitytype.templates.f0" href="#boost_utility_identitytype.templates.f0" class="para">2</a>] </sup>
This is because the implementation of <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
wraps the specified type within a meta-function.
</p></div><div class="footnote"><p><sup>[<a id="ftn.boost_utility_identitytype.annex__implementation.f0" href="#boost_utility_identitytype.annex__implementation.f0" class="para">3</a>] </sup>
There is absolutely no guarantee that the macro is actually implemented using
the code listed in this documentation. The listed code is for explanatory
purposes only.
</p></div></div></div></body></html>

View File

@ -0,0 +1,165 @@
[/ Copyright (C) 2009-2012 Lorenzo Caminiti ]
[/ Distributed under the Boost Software License, Version 1.0 ]
[/ (see accompanying file LICENSE_1_0.txt or a copy at ]
[/ http://www.boost.org/LICENSE_1_0.txt) ]
[/ Home at http://www.boost.org/libs/utility/identity_type ]
[library Boost.Utility/IdentityType
[quickbook 1.5]
[version 1.0.0]
[copyright 2009-2012 Lorenzo Caminiti]
[purpose wraps types with round parenthesis]
[license
Distributed under the Boost Software License, Version 1.0
(see accompanying file LICENSE_1_0.txt or a copy at
[@http://www.boost.org/LICENSE_1_0.txt])
]
[authors [Caminiti <email>lorcaminiti@gmail.com</email>, Lorenzo]]
[category Utilities]
]
This library allows to wrap types within round parenthesis so they can always be passed as macro parameters.
[import ../test/var_error.cpp]
[import ../test/var.cpp]
[import ../test/template.cpp]
[import ../test/abstract.cpp]
[import ../test/paren.cpp]
[section Motivation]
Consider the following macro which declares a variable named `var`[^['n]] with the specified [^['type]] (see also [@../../test/var_error.cpp =var_error.cpp=]):
[var_error]
The first macro invocation works correctly declaring a variable named `var1` of type `int`.
However, the second macro invocation fails generating a preprocessor error similar to the following:
[pre
error: macro "VAR" passed 3 arguments, but takes just 2
]
That is because the `std::map` type passed as the first macro parameter contains a comma `,` not wrapped by round parenthesis `()`.
The preprocessor interprets that unwrapped comma as a separation between macro parameters concluding that a total of three (and not two) parameters are passed to the macro in the following order:
# `std::map<int`
# `char>`
# `2`
Note that, differently from the compiler, the preprocessor only recognizes round parenthesis `()`.
Angular `<>` and squared `[]` parenthesis are not recognized by the preprocessor when parsing macro parameters.
[endsect]
[section Solution]
In some cases, it might be possible to workaround this issue by avoiding to pass the type expression to the macro all together.
For example, in the case above a `typedef` could have been used to specify the type expression with the commas outside the macro (see also [@../../test/var.cpp =var.cpp=]):
[var_typedef]
When this is neither possible nor desired (e.g., see the function template `f` in the section below), this library header [headerref boost/utility/identity_type.hpp] defines a macro [macroref BOOST_IDENTITY_TYPE] which can be used to workaround the issue while keeping the type expression as one of the macro parameters (see also [@../../test/var.cpp =var.cpp=]).
[var_ok]
The [macroref BOOST_IDENTITY_TYPE] macro expands to an expression that evaluates (at compile-time) to the specified type.
The specified type is never split into multiple macro parameters because it is always wrapped by a set of extra round parenthesis `()`.
In fact, a total of two sets of round parenthesis must be used: The parenthesis to invoke the macro `BOOST_IDENTITY_TYPE(...)` plus the inner parenthesis to wrap the type passed to the macro `BOOST_IDENTITY_TYPE((...))`.
This macro works on any [@http://www.open-std.org/JTC1/SC22/WG21/docs/standards C++03] compiler (and it does not use [@http://en.wikipedia.org/wiki/Variadic_macro variadic macros]).
[footnote
Using variadic macros, it would be possible to require a single set of extra parenthesis `BOOST_IDENTITY_TYPE(`[^['type]]`)` instead of two `BOOST_IDENTITY_TYPE((`[^['type]]`))` but variadic macros are not part of C++03 (even if nowadays they are supported by most modern compilers and they are also part of C++11).
]
The authors originally developed and tested this library using GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features enabled `-std=c++0x`) on Cygwin and Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7.
See the library [@http://www.boost.org/development/tests/release/developer/utility-identity_type.html regressions test results] for more information on supported compilers and platforms.
[endsect]
[section Templates]
This macro must be prefixed by `typename` when used within templates.
For example, let's program a macro that declares a function parameter named `arg`[^['n]] with the specified [^['type]] (see also [@../../test/template.cpp =template.cpp=]):
[template_f_decl]
[template_f_call]
However, note that the template parameter `char` must be manually specified when invoking the function as in `f<char>(a)`.
In fact, when the [macroref BOOST_IDENTITY_TYPE] macro is used to wrap a function template parameter, the template parameter can no longer be automatically deduced by the compiler form the function call as `f(a)` would have done.
[footnote
This is because the implementation of [macroref BOOST_IDENTITY_TYPE] wraps the specified type within a meta-function.
]
(This limitation does not apply to class templates because class template parameters must always be explicitly specified.)
In other words, without using the [macroref BOOST_IDENTITY_TYPE] macro, C++ would normally be able to automatically deduce the function template parameter as shown below:
[template_g_decl]
[template_g_call]
[endsect]
[section Abstract Types]
On some compilers (e.g., GCC), using this macro on abstract types (i.e., classes with one or more pure virtual functions) generates a compiler error.
This can be avoided by manipulating the type adding and removing a reference to it.
Let's program a macro that performs a static assertion on a [@http://en.wikipedia.org/wiki/Template_metaprogramming Template Meta-Programming] (TMP) meta-function (similarly to Boost.MPL [@http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/assert.html `BOOST_MPL_ASSERT`]).
The [macroref BOOST_IDENTITY_TYPE] macro can be used to pass a meta-function with multiple template parameters to the assert macro (so to handle the commas separating the template parameters).
In this case, if the meta-function is an abstract type, it needs to be manipulated adding and removing a reference to it (see also [@../../test/abstract.cpp =abstract.cpp=]):
[abstract]
[endsect]
[section Annex: Usage]
The [macroref BOOST_IDENTITY_TYPE] macro can be used either when calling a user-defined macro (as shown by the examples so far), or internally when implementing a user-defined macro (as shown below).
When [macroref BOOST_IDENTITY_TYPE] is used in the implementation of the user-defined macro, the caller of the user macro will have to specify the extra parenthesis (see also [@../../test/paren.cpp =paren.cpp=]):
[paren]
However, note that the caller will /always/ have to specify the extra parenthesis even when the macro parameters contain no comma:
[paren_always]
In some cases, using [macroref BOOST_IDENTITY_TYPE] in the implementation of the user-defined macro might provide the best syntax for the caller.
For example, this is the case for `BOOST_MPL_ASSERT` because the majority of template meta-programming expressions contain unwrapped commas so it is less confusing for the user to always specify the extra parenthesis `((...))` instead of using [macroref BOOST_IDENTITY_TYPE]:
BOOST_MPL_ASSERT(( // Natural syntax.
boost::mpl::and_<
boost::is_const<T>
, boost::is_reference<T>
>
));
However, in other situations it might be preferable to not require the extra parenthesis in the common cases and handle commas as special cases using [macroref BOOST_IDENTITY_TYPE].
For example, this is the case for [@http://www.boost.org/libs/local_function `BOOST_LOCAL_FUNCTION`] for which always requiring the extra parenthesis `((...))` around the types would lead to an unnatural syntax for the local function signature:
int BOOST_LOCAL_FUNCTION( ((int&)) x, ((int&)) y ) { // Unnatural syntax.
return x + y;
} BOOST_LOCAL_FUNCTION_NAME(add)
Instead requiring the user to specify [macroref BOOST_IDENTITY_TYPE] only when needed allows for the more natural syntax `BOOST_LOCAL_FUNCTION(int& x, int& y)` in the common cases when the parameter types contain no comma (while still allowing to specify parameter types with commas as special cases using `BOOST_LOCAL_FUNCTION(BOOST_IDENTITY_TYPE((std::map<int, char>))& x, int& y)`).
[endsect]
[section Annex: Implementation]
The implementation of this library macro is equivalent to the following:
[footnote
There is absolutely no guarantee that the macro is actually implemented using the code listed in this documentation.
The listed code is for explanatory purposes only.
]
#include <boost/type_traits/function_traits.hpp>
#define BOOST_IDENTITY_TYPE(parenthesized_type) \
boost::function_traits<void parenthesized_type>::arg1_type
Essentially, the type is wrapped between round parenthesis `(std::map<int, char>)` so it can be passed as a single macro parameter even if it contains commas.
Then the parenthesized type is transformed into the type of a function returning `void` and with the specified type as the type of the first and only argument `void (std::map<int, char>)`.
Finally, the type of the first argument `arg1_type` is extracted at compile-time using the `function_traits` meta-function therefore obtaining the original type from the parenthesized type (effectively stripping the extra parenthesis from around the specified type).
[endsect]
[xinclude reference.xml]

15
identity_type/index.html Normal file
View File

@ -0,0 +1,15 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
</head>
<body>
Automatic redirection failed, click this
<a href="doc/html/index.html">link</a> &nbsp;<hr>
<p><EFBFBD> Copyright Lorenzo Caminiti, 2009-2012</p>
<p>Distributed under the Boost Software License, Version 1.0 (see
accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or a copy at
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
</body>
</html>

View File

@ -0,0 +1,16 @@
# Copyright (C) 2009-2012 Lorenzo Caminiti
# Distributed under the Boost Software License, Version 1.0
# (see accompanying file LICENSE_1_0.txt or a copy at
# http://www.boost.org/LICENSE_1_0.txt)
# Home at http://www.boost.org/libs/utility/identity_type
import testing ;
compile-fail var_error.cpp ;
run var.cpp ;
run template.cpp ;
run abstract.cpp ;
run noncopyable.cpp ;
run paren.cpp ;

View File

@ -0,0 +1,35 @@
// Copyright (C) 2009-2012 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0
// (see accompanying file LICENSE_1_0.txt or a copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Home at http://www.boost.org/libs/utility/identity_type
#include <boost/utility/identity_type.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/remove_reference.hpp>
//[abstract
#define TMP_ASSERT(metafunction) \
BOOST_STATIC_ASSERT(metafunction::value)
template<typename T, bool b>
struct abstract {
static const bool value = b;
virtual void f(T const& x) = 0; // Pure virtual function.
};
TMP_ASSERT(
boost::remove_reference< // Add and remove
BOOST_IDENTITY_TYPE(( // reference for
boost::add_reference< // abstract type.
abstract<int, true>
>::type
))
>::type
);
//]
int main() { return 0; }

View File

@ -0,0 +1,25 @@
// Copyright (C) 2009-2012 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0
// (see accompanying file LICENSE_1_0.txt or a copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Home at http://www.boost.org/libs/utility/identity_type
#include <boost/utility/identity_type.hpp>
#include <boost/static_assert.hpp>
#include <boost/noncopyable.hpp>
//[noncopyable
#define TMP_ASSERT(metafunction) \
BOOST_STATIC_ASSERT(metafunction::value)
template<typename T, T init>
struct noncopyable : boost::noncopyable {
static const T value = init;
};
TMP_ASSERT(BOOST_IDENTITY_TYPE((noncopyable<bool, true>)));
//]
int main() { return 0; }

View File

@ -0,0 +1,35 @@
// Copyright (C) 2009-2012 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0
// (see accompanying file LICENSE_1_0.txt or a copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Home at http://www.boost.org/libs/utility/identity_type
#include <boost/utility/identity_type.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_const.hpp>
#include <map>
//[paren
#define TMP_ASSERT_PAREN(parenthesized_metafunction) \
/* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \
BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value)
#define TMP_ASSERT(metafunction) \
BOOST_STATIC_ASSERT(metafunction::value)
// Specify only extra parenthesis `((...))`.
TMP_ASSERT_PAREN((boost::is_const<std::map<int, char> const>));
// Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro.
TMP_ASSERT(BOOST_IDENTITY_TYPE((boost::is_const<std::map<int, char> const>)));
//]
//[paren_always
TMP_ASSERT_PAREN((boost::is_const<int const>)); // Always extra `((...))`.
TMP_ASSERT(boost::is_const<int const>); // No extra `((...))` and no macro.
//]
int main() { return 0; }

View File

@ -0,0 +1,48 @@
// Copyright (C) 2009-2012 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0
// (see accompanying file LICENSE_1_0.txt or a copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Home at http://www.boost.org/libs/utility/identity_type
#include <boost/utility/identity_type.hpp>
#include <map>
#include <iostream>
//[template_f_decl
#define ARG(type, n) type arg ## n
template<typename T>
void f( // Prefix macro with `typename` in templates.
ARG(typename BOOST_IDENTITY_TYPE((std::map<int, T>)), 1)
) {
std::cout << arg1[0] << std::endl;
}
//]
//[template_g_decl
template<typename T>
void g(
std::map<int, T> arg1
) {
std::cout << arg1[0] << std::endl;
}
//]
int main() {
//[template_f_call
std::map<int, char> a;
a[0] = 'a';
f<char>(a); // OK...
// f(a); // ... but error.
//]
//[template_g_call
g<char>(a); // OK...
g(a); // ... and also OK.
//]
return 0;
}

View File

@ -0,0 +1,26 @@
// Copyright (C) 2009-2012 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0
// (see accompanying file LICENSE_1_0.txt or a copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Home at http://www.boost.org/libs/utility/identity_type
#include <map>
#define VAR(type, n) type var ## n
VAR(int, 1); // OK.
//[var_typedef
typedef std::map<int, char> map_type;
VAR(map_type, 3); // OK.
//]
//[var_ok
#include <boost/utility/identity_type.hpp>
VAR(BOOST_IDENTITY_TYPE((std::map<int, char>)), 4); // OK.
//]
int main() { return 0; }

View File

@ -0,0 +1,18 @@
// Copyright (C) 2009-2012 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0
// (see accompanying file LICENSE_1_0.txt or a copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Home at http://www.boost.org/libs/utility/identity_type
#include <map>
//[var_error
#define VAR(type, n) type var ## n
VAR(int, 1); // OK.
VAR(std::map<int, char>, 2); // Error.
//]
int main() { return 0; }

View File

@ -46,7 +46,7 @@ HREF="../../boost/utility/typed_in_place_factory.hpp">boost/utility/typed_in_pla
<p>Suppose we have a class</p>
<pre>struct X
{
X ( int, std:::string ) ;
X ( int, std::string ) ;
} ;</pre>
<p>And a container for it which supports an empty state (that is, which can contain zero objects):</p>
<pre>struct C

View File

@ -1,8 +1,11 @@
//
// boost/assert.hpp - BOOST_ASSERT(expr)
// BOOST_ASSERT_MSG(expr, msg)
// BOOST_VERIFY(expr)
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2007 Peter Dimov
// Copyright (c) Beman Dawes 2011
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@ -13,6 +16,16 @@
// See http://www.boost.org/libs/utility/assert.html for documentation.
//
//
// Stop inspect complaining about use of 'assert':
//
// boostinspect:naassert_macro
//
//--------------------------------------------------------------------------------------//
// BOOST_ASSERT //
//--------------------------------------------------------------------------------------//
#undef BOOST_ASSERT
#if defined(BOOST_DISABLE_ASSERTS)
@ -21,22 +34,100 @@
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
#include <boost/config.hpp>
#include <boost/current_function.hpp>
namespace boost
{
void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined
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__))
#define BOOST_ASSERT(expr) (BOOST_LIKELY(!!(expr)) \
? ((void)0) \
: ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
#else
# include <assert.h> // .h to support old libraries w/o <cassert> - effect is the same
# define BOOST_ASSERT(expr) assert(expr)
#endif
//--------------------------------------------------------------------------------------//
// BOOST_ASSERT_MSG //
//--------------------------------------------------------------------------------------//
# undef BOOST_ASSERT_MSG
#if defined(BOOST_DISABLE_ASSERTS) || defined(NDEBUG)
#define BOOST_ASSERT_MSG(expr, msg) ((void)0)
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
#include <boost/config.hpp>
#include <boost/current_function.hpp>
namespace boost
{
void assertion_failed_msg(char const * expr, char const * msg,
char const * function, char const * file, long line); // user defined
} // namespace boost
#define BOOST_ASSERT_MSG(expr, msg) (BOOST_LIKELY(!!(expr)) \
? ((void)0) \
: ::boost::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
#else
#ifndef BOOST_ASSERT_HPP
#define BOOST_ASSERT_HPP
#include <cstdlib>
#include <iostream>
#include <boost/config.hpp>
#include <boost/current_function.hpp>
// IDE's like Visual Studio perform better if output goes to std::cout or
// some other stream, so allow user to configure output stream:
#ifndef BOOST_ASSERT_MSG_OSTREAM
# define BOOST_ASSERT_MSG_OSTREAM std::cerr
#endif
namespace boost
{
namespace assertion
{
namespace detail
{
// Note: The template is needed to make the function non-inline and avoid linking errors
template< typename CharT >
BOOST_NOINLINE void assertion_failed_msg(CharT const * expr, char const * msg, char const * function,
char const * file, long line)
{
BOOST_ASSERT_MSG_OSTREAM
<< "***** Internal Program Error - assertion (" << expr << ") failed in "
<< function << ":\n"
<< file << '(' << line << "): " << msg << std::endl;
#ifdef UNDER_CE
// The Windows CE CRT library does not have abort() so use exit(-1) instead.
std::exit(-1);
#else
std::abort();
#endif
}
} // detail
} // assertion
} // detail
#endif
#define BOOST_ASSERT_MSG(expr, msg) (BOOST_LIKELY(!!(expr)) \
? ((void)0) \
: ::boost::assertion::detail::assertion_failed_msg(#expr, msg, \
BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
#endif
//--------------------------------------------------------------------------------------//
// BOOST_VERIFY //
//--------------------------------------------------------------------------------------//
#undef BOOST_VERIFY
#if defined(BOOST_DISABLE_ASSERTS) || ( !defined(BOOST_ENABLE_ASSERT_HANDLER) && defined(NDEBUG) )

View File

@ -28,7 +28,7 @@ namespace detail
inline void current_function_helper()
{
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600))
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__)
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
@ -65,3 +65,4 @@ inline void current_function_helper()
} // namespace boost
#endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED

View File

@ -24,6 +24,7 @@
#include <cstddef>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/detail/workaround.hpp>
@ -43,20 +44,26 @@ struct ct_imp2<T, true>
typedef const T param_type;
};
template <typename T, bool isp, bool b1>
template <typename T, bool isp, bool b1, bool b2>
struct ct_imp
{
typedef const T& param_type;
};
template <typename T, bool isp>
struct ct_imp<T, isp, true>
template <typename T, bool isp, bool b2>
struct ct_imp<T, isp, true, b2>
{
typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
};
template <typename T, bool b1>
struct ct_imp<T, true, b1>
template <typename T, bool isp, bool b1>
struct ct_imp<T, isp, b1, true>
{
typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
};
template <typename T, bool b1, bool b2>
struct ct_imp<T, true, b1, b2>
{
typedef const T param_type;
};
@ -79,7 +86,8 @@ public:
typedef typename boost::detail::ct_imp<
T,
::boost::is_pointer<T>::value,
::boost::is_arithmetic<T>::value
::boost::is_arithmetic<T>::value,
::boost::is_enum<T>::value
>::param_type param_type;
};

View File

@ -9,6 +9,8 @@
#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
#define BOOST_NONCOPYABLE_HPP_INCLUDED
#include <boost/config.hpp>
namespace boost {
// Private copy constructor and copy assignment ensure classes derived from
@ -21,11 +23,21 @@ namespace noncopyable_ // protection from unintended ADL
class noncopyable
{
protected:
noncopyable() {}
#ifndef BOOST_NO_DEFAULTED_FUNCTIONS
BOOST_CONSTEXPR noncopyable() = default;
~noncopyable() = default;
#else
noncopyable() {}
~noncopyable() {}
private: // emphasize the following members are private
#endif
#ifndef BOOST_NO_DELETED_FUNCTIONS
noncopyable( const noncopyable& ) = delete;
noncopyable& operator=( const noncopyable& ) = delete;
#else
private: // emphasize the following members are private
noncopyable( const noncopyable& );
const noncopyable& operator=( const noncopyable& );
noncopyable& operator=( const noncopyable& );
#endif
};
}

View File

@ -8,6 +8,8 @@
// See http://www.boost.org/libs/utility/operators.htm for documentation.
// Revision History
// 16 Dec 10 Limit warning suppression for 4284 to older versions of VC++
// (Matthew Bradbury, fixes #4432)
// 07 Aug 08 Added "euclidean" spelling. (Daniel Frey)
// 03 Apr 08 Make sure "convertible to bool" is sufficient
// for T::operator<, etc. (Daniel Frey)
@ -88,7 +90,7 @@
# pragma set woff 1234
#endif
#if defined(BOOST_MSVC)
#if BOOST_WORKAROUND(BOOST_MSVC, < 1600)
# pragma warning( disable : 4284 ) // complaint about return type of
#endif // operator-> not begin a UDT

View File

@ -13,6 +13,7 @@
#include <boost/utility/base_from_member.hpp>
#include <boost/utility/binary.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/utility/identity_type.hpp>
#include <boost/checked_delete.hpp>
#include <boost/next_prior.hpp>
#include <boost/noncopyable.hpp>

View File

@ -1,4 +1,4 @@
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
// Douglas Gregor (gregod@cs.rpi.edu)
//
// Copyright (C) 2002, 2008 Peter Dimov
@ -50,7 +50,7 @@ template<class T> struct addressof_impl
template<class T> T * addressof( T & v )
{
#if defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) )
#if (defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) ) ) || defined( __SUNPRO_CC )
return boost::detail::addressof_impl<T>::f( v, 0 );

View File

@ -1,6 +1,6 @@
// boost utility/base_from_member.hpp header file --------------------------//
// Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and
// Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and
// distribution are subject to the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or a copy at
// <http://www.boost.org/LICENSE_1_0.txt>.)
@ -10,10 +10,15 @@
#ifndef BOOST_UTILITY_BASE_FROM_MEMBER_HPP
#define BOOST_UTILITY_BASE_FROM_MEMBER_HPP
#include <boost/config.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/enable_if.hpp>
// Base-from-member arity configuration macro ------------------------------//
@ -53,6 +58,59 @@
namespace boost
{
namespace detail
{
// Type-unmarking class template -------------------------------------------//
// Type-trait to get the raw type, i.e. the type without top-level reference nor
// cv-qualification, from a type expression. Mainly for function arguments, any
// reference part is stripped first.
// Contributed by Daryle Walker
template < typename T >
struct remove_cv_ref
{
typedef typename ::boost::remove_cv<typename
::boost::remove_reference<T>::type>::type type;
}; // boost::detail::remove_cv_ref
// Unmarked-type comparison class template ---------------------------------//
// Type-trait to check if two type expressions have the same raw type.
// Contributed by Daryle Walker, based on a work-around by Luc Danton
template < typename T, typename U >
struct is_related
: public ::boost::is_same<
typename ::boost::detail::remove_cv_ref<T>::type,
typename ::boost::detail::remove_cv_ref<U>::type >
{};
// Enable-if-on-unidentical-unmarked-type class template -------------------//
// Enable-if on the first two type expressions NOT having the same raw type.
// Contributed by Daryle Walker, based on a work-around by Luc Danton
#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
template<typename ...T>
struct enable_if_unrelated
: public ::boost::enable_if_c<true>
{};
template<typename T, typename U, typename ...U2>
struct enable_if_unrelated<T, U, U2...>
: public ::boost::disable_if< ::boost::detail::is_related<T, U> >
{};
#endif
} // namespace boost::detail
// Base-from-member class template -----------------------------------------//
// Helper to initialize a base object so a derived class can use this
@ -68,12 +126,25 @@ class base_from_member
protected:
MemberType member;
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && \
!(defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 4))
template <typename ...T, typename EnableIf = typename
::boost::detail::enable_if_unrelated<base_from_member, T...>::type>
explicit BOOST_CONSTEXPR base_from_member( T&& ...x )
BOOST_NOEXCEPT_IF( BOOST_NOEXCEPT_EXPR(::new ((void*) 0) MemberType(
static_cast<T&&>(x)... )) ) // no std::is_nothrow_constructible...
: member( static_cast<T&&>(x)... ) // ...nor std::forward needed
{}
#else
base_from_member()
: member()
{}
BOOST_PP_REPEAT_FROM_TO( 1, BOOST_PP_INC(BOOST_BASE_FROM_MEMBER_MAX_ARITY),
BOOST_PRIVATE_CTR_DEF, _ )
#endif
}; // boost::base_from_member

View File

@ -4,7 +4,7 @@
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com

View File

@ -0,0 +1,44 @@
// declval.hpp -------------------------------------------------------------//
// Copyright 2010 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_UTILITY_DECLVAL_HPP
#define BOOST_UTILITY_DECLVAL_HPP
#include <boost/config.hpp>
//----------------------------------------------------------------------------//
#include <boost/type_traits/add_rvalue_reference.hpp>
//----------------------------------------------------------------------------//
// //
// C++03 implementation of //
// 20.2.4 Function template declval [declval] //
// Written by Vicente J. Botet Escriba //
// //
// 1 The library provides the function template declval to simplify the
// definition of expressions which occur as unevaluated operands.
// 2 Remarks: If this function is used, the program is ill-formed.
// 3 Remarks: The template parameter T of declval may be an incomplete type.
// [ Example:
//
// template <class To, class From>
// decltype(static_cast<To>(declval<From>())) convert(From&&);
//
// declares a function template convert which only participates in overloading
// if the type From can be explicitly converted to type To. For another example
// see class template common_type (20.9.7.6). -end example ]
//----------------------------------------------------------------------------//
namespace boost {
template <typename T>
typename add_rvalue_reference<T>::type declval() BOOST_NOEXCEPT; // as unevaluated operand
} // namespace boost
#endif // BOOST_UTILITY_DECLVAL_HPP

View File

@ -5,7 +5,7 @@
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com

View File

@ -5,7 +5,7 @@
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com

View File

@ -5,6 +5,11 @@
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Daniel Walker, Eric Niebler, Michel Morin 2008-2012.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or
// copy at http://www.boost.org/LICENSE_1_0.txt)
// For more information, see http://www.boost.org/libs/utility
#if !defined(BOOST_PP_IS_ITERATING)
# error Boost result_of - do not include this file!
@ -18,34 +23,44 @@
#endif
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct tr1_result_of<F(BOOST_RESULT_OF_ARGS)>
: mpl::if_<
mpl::or_< is_pointer<F>, is_member_function_pointer<F> >
, boost::detail::tr1_result_of_impl<
typename remove_cv<F>::type,
typename remove_cv<F>::type(BOOST_RESULT_OF_ARGS),
typename remove_cv<F>::type,
typename remove_cv<F>::type(BOOST_RESULT_OF_ARGS),
(boost::detail::has_result_type<F>::value)>
, boost::detail::tr1_result_of_impl<
F,
F(BOOST_RESULT_OF_ARGS),
F(BOOST_RESULT_OF_ARGS),
(boost::detail::has_result_type<F>::value)> >::type { };
#endif
#if !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE)
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<F(BOOST_RESULT_OF_ARGS)>
: detail::cpp0x_result_of<F(BOOST_RESULT_OF_ARGS)> { };
#endif // BOOST_RESULT_OF_USE_DECLTYPE
// As of N2588, C++0x result_of only supports function call
// expressions of the form f(x). This precludes support for member
// function pointers, which are invoked with expressions of the form
// o->*f(x). This implementation supports both.
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<F(BOOST_RESULT_OF_ARGS)>
: mpl::if_<mpl::or_<detail::has_result_type<F>, detail::has_result<F> >,
tr1_result_of<F(BOOST_RESULT_OF_ARGS)>,
detail::cpp0x_result_of<F(BOOST_RESULT_OF_ARGS)> >::type { };
#endif // BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
namespace detail {
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct cpp0x_result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
: mpl::if_<
mpl::or_< is_pointer<F>, is_member_function_pointer<F> >
is_member_function_pointer<F>
, detail::tr1_result_of_impl<
typename remove_cv<F>::type,
typename remove_cv<F>::type,
typename remove_cv<F>::type(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false
>
, detail::cpp0x_result_of_impl<
@ -54,58 +69,119 @@ struct result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
>::type
{};
namespace detail {
#ifdef BOOST_NO_SFINAE_EXPR
# define BOOST_RESULT_OF_STATIC_MEMBERS(z, n, _) \
static T ## n t ## n; \
/**/
template<typename F>
struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION());
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
class cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
{
static F f;
BOOST_PP_REPEAT(BOOST_PP_ITERATION(), BOOST_RESULT_OF_STATIC_MEMBERS, _)
public:
typedef decltype(f(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),t))) type;
template<typename R BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<R(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T))> {
R operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T)) const;
typedef result_of_private_type const &(*pfn_t)(...);
operator pfn_t() const volatile;
};
} // namespace detail
template<typename F>
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION());
#else // defined(BOOST_NO_DECLTYPE)
template<typename F>
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<F *>
: BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<F>
{};
template<typename F>
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<F &>
: BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<F>
{};
template<typename F>
struct BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())
: mpl::eval_if<
is_class<typename remove_reference<F>::type>,
result_of_wrap_callable_class<F>,
mpl::identity<BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<typename remove_cv<F>::type> >
>
{};
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
struct BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) {
typedef typename BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())<F>::type wrapper_t;
static const bool value = (
sizeof(result_of_no_type) == sizeof(detail::result_of_is_private_type(
(boost::declval<wrapper_t>()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)), result_of_weird_type())
))
);
typedef mpl::bool_<value> type;
};
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), true>
: lazy_enable_if<
BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION())<F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), T)>
, cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
>
{};
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
{
typedef decltype(
boost::declval<F>()(
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
)
) type;
};
#else // BOOST_NO_SFINAE_EXPR
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)),
typename result_of_always_void<decltype(
boost::declval<F>()(
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
)
)>::type> {
typedef decltype(
boost::declval<F>()(
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
)
) type;
};
#endif // BOOST_NO_SFINAE_EXPR
} // namespace detail
#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<F(BOOST_RESULT_OF_ARGS)>
: tr1_result_of<F(BOOST_RESULT_OF_ARGS)> { };
#endif
#endif // defined(BOOST_NO_DECLTYPE)
#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE)
#undef BOOST_RESULT_OF_ARGS
#if BOOST_PP_ITERATION() >= 1
#if BOOST_PP_ITERATION() >= 1
namespace detail {
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct tr1_result_of_impl<R (*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
{
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct tr1_result_of_impl<R (&)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
{
typedef R type;
};
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct tr1_result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T)),
FArgs, false>
@ -113,8 +189,7 @@ struct tr1_result_of_impl<R (T0::*)
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct tr1_result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
const,
@ -123,8 +198,7 @@ struct tr1_result_of_impl<R (T0::*)
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct tr1_result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
volatile,
@ -133,8 +207,7 @@ struct tr1_result_of_impl<R (T0::*)
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct tr1_result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
const volatile,

View File

@ -0,0 +1,43 @@
/*
* Copyright Andrey Semashev 2007 - 2013.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file empty_deleter.hpp
* \author Andrey Semashev
* \date 22.04.2007
*
* This header contains an \c empty_deleter implementation. This is an empty
* function object that receives a pointer and does nothing with it.
* Such empty deletion strategy may be convenient, for example, when
* constructing <tt>shared_ptr</tt>s that point to some object that should not be
* deleted (i.e. a variable on the stack or some global singleton, like <tt>std::cout</tt>).
*/
#ifndef BOOST_UTILITY_EMPTY_DELETER_HPP_INCLUDED_
#define BOOST_UTILITY_EMPTY_DELETER_HPP_INCLUDED_
#include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
//! A function object that does nothing and can be used as an empty deleter for \c shared_ptr
struct empty_deleter
{
//! Function object result type
typedef void result_type;
/*!
* Does nothing
*/
void operator() (const volatile void*) const BOOST_NOEXCEPT {}
};
} // namespace boost
#endif // BOOST_UTILITY_EMPTY_DELETER_HPP_INCLUDED_

View File

@ -0,0 +1,128 @@
/*
* Copyright Andrey Semashev 2007 - 2013.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file explicit_operator_bool.hpp
* \author Andrey Semashev
* \date 08.03.2009
*
* This header defines a compatibility macro that implements an unspecified
* \c bool operator idiom, which is superseded with explicit conversion operators in
* C++11.
*/
#ifndef BOOST_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_
#define BOOST_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_
#include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
/*!
* \brief The macro defines an explicit operator of conversion to \c bool
*
* The macro should be used inside the definition of a class that has to
* support the conversion. The class should also implement <tt>operator!</tt>,
* in terms of which the conversion operator will be implemented.
*/
#define BOOST_EXPLICIT_OPERATOR_BOOL()\
BOOST_FORCEINLINE explicit operator bool () const\
{\
return !this->operator! ();\
}
/*!
* \brief The macro defines a constexpr explicit operator of conversion to \c bool
*
* The macro should be used inside the definition of a class that has to
* support the conversion. The class should also implement <tt>operator!</tt>,
* in terms of which the conversion operator will be implemented.
*/
#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\
BOOST_FORCEINLINE BOOST_CONSTEXPR explicit operator bool () const\
{\
return !this->operator! ();\
}
#else // !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
#if (defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) && !defined(BOOST_NO_COMPILER_CONFIG)
// Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
#define BOOST_NO_UNSPECIFIED_BOOL
#endif // (defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) && !defined(BOOST_NO_COMPILER_CONFIG)
#if !defined(BOOST_NO_UNSPECIFIED_BOOL)
namespace boost {
namespace detail {
#if !defined(_MSC_VER) && !defined(__IBMCPP__)
struct unspecified_bool
{
// NOTE TO THE USER: If you see this in error messages then you tried
// to apply an unsupported operator on the object that supports
// explicit conversion to bool.
struct OPERATORS_NOT_ALLOWED;
static void true_value(OPERATORS_NOT_ALLOWED*) {}
};
typedef void (*unspecified_bool_type)(unspecified_bool::OPERATORS_NOT_ALLOWED*);
#else
// MSVC and VACPP are too eager to convert pointer to function to void* even though they shouldn't
struct unspecified_bool
{
// NOTE TO THE USER: If you see this in error messages then you tried
// to apply an unsupported operator on the object that supports
// explicit conversion to bool.
struct OPERATORS_NOT_ALLOWED;
void true_value(OPERATORS_NOT_ALLOWED*) {}
};
typedef void (unspecified_bool::*unspecified_bool_type)(unspecified_bool::OPERATORS_NOT_ALLOWED*);
#endif
} // namespace detail
} // namespace boost
#define BOOST_EXPLICIT_OPERATOR_BOOL()\
BOOST_FORCEINLINE operator boost::detail::unspecified_bool_type () const\
{\
return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\
}
#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\
BOOST_FORCEINLINE BOOST_CONSTEXPR operator boost::detail::unspecified_bool_type () const\
{\
return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\
}
#else // !defined(BOOST_NO_UNSPECIFIED_BOOL)
#define BOOST_EXPLICIT_OPERATOR_BOOL()\
BOOST_FORCEINLINE operator bool () const\
{\
return !this->operator! ();\
}
#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\
BOOST_FORCEINLINE BOOST_CONSTEXPR operator bool () const\
{\
return !this->operator! ();\
}
#endif // !defined(BOOST_NO_UNSPECIFIED_BOOL)
#endif // !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
#endif // BOOST_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_

View File

@ -0,0 +1,46 @@
// Copyright (C) 2009-2012 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0
// (see accompanying file LICENSE_1_0.txt or a copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Home at http://www.boost.org/libs/utility/identity_type
/** @file
Wrap type expressions with round parenthesis so they can be passed to macros
even if they contain commas.
*/
#ifndef BOOST_IDENTITY_TYPE_HPP_
#define BOOST_IDENTITY_TYPE_HPP_
#include <boost/type_traits/function_traits.hpp>
/**
@brief This macro allows to wrap the specified type expression within extra
round parenthesis so the type can be passed as a single macro parameter even if
it contains commas (not already wrapped within round parenthesis).
@Params
@Param{parenthesized_type,
The type expression to be passed as macro parameter wrapped by a single set
of round parenthesis <c>(...)</c>.
This type expression can contain an arbitrary number of commas.
}
@EndParams
This macro works on any C++03 compiler (it does not use variadic macros).
This macro must be prefixed by <c>typename</c> when used within templates.
Note that the compiler will not be able to automatically determine function
template parameters when they are wrapped with this macro (these parameters
need to be explicitly specified when calling the function template).
On some compilers (like GCC), using this macro on abstract types requires to
add and remove a reference to the specified type.
*/
#define BOOST_IDENTITY_TYPE(parenthesized_type) \
/* must NOT prefix this with `::` to work with parenthesized syntax */ \
boost::function_traits< void parenthesized_type >::arg1_type
#endif // #include guard

View File

@ -5,7 +5,7 @@
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com

View File

@ -10,21 +10,57 @@
#define BOOST_RESULT_OF_HPP
#include <boost/config.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#include <boost/preprocessor/facilities/intercept.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/or.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_member_function_pointer.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/declval.hpp>
#include <boost/utility/enable_if.hpp>
#ifndef BOOST_RESULT_OF_NUM_ARGS
# define BOOST_RESULT_OF_NUM_ARGS 10
# define BOOST_RESULT_OF_NUM_ARGS 16
#endif
// Use the decltype-based version of result_of by default if the compiler
// supports N3276 <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2011/n3276.pdf>.
// The user can force the choice by defining BOOST_RESULT_OF_USE_DECLTYPE,
// BOOST_RESULT_OF_USE_TR1, or BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK but not more than one!
#if (defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1)) || \
(defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)) || \
(defined(BOOST_RESULT_OF_USE_TR1) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK))
# error More than one of BOOST_RESULT_OF_USE_DECLTYPE, BOOST_RESULT_OF_USE_TR1 and \
BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK cannot be defined at the same time.
#endif
#if defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) && defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE)
# error Cannot fallback to decltype if BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE is not defined.
#endif
#ifndef BOOST_RESULT_OF_USE_TR1
# ifndef BOOST_RESULT_OF_USE_DECLTYPE
# ifndef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
# ifndef BOOST_NO_CXX11_DECLTYPE_N3276 // this implies !defined(BOOST_NO_CXX11_DECLTYPE)
# define BOOST_RESULT_OF_USE_DECLTYPE
# else
# define BOOST_RESULT_OF_USE_TR1
# endif
# endif
# endif
#endif
namespace boost {
@ -37,8 +73,79 @@ namespace detail {
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
BOOST_MPL_HAS_XXX_TEMPLATE_DEF(result)
template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_impl;
template<typename F> struct cpp0x_result_of_impl;
template<typename F> struct cpp0x_result_of;
#ifdef BOOST_NO_SFINAE_EXPR
// There doesn't seem to be any other way to turn this off such that the presence of
// the user-defined operator,() below doesn't cause spurious warning all over the place,
// so unconditionally turn it off.
#if BOOST_MSVC
# pragma warning(disable: 4913) // user defined binary operator ',' exists but no overload could convert all operands, default built-in binary operator ',' used
#endif
struct result_of_private_type {};
struct result_of_weird_type {
friend result_of_private_type operator,(result_of_private_type, result_of_weird_type);
};
typedef char result_of_yes_type; // sizeof(result_of_yes_type) == 1
typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type) == 2
template<typename T>
result_of_no_type result_of_is_private_type(T const &);
result_of_yes_type result_of_is_private_type(result_of_private_type);
template<typename C>
struct result_of_callable_class : C {
result_of_callable_class();
typedef result_of_private_type const &(*pfn_t)(...);
operator pfn_t() const volatile;
};
template<typename C>
struct result_of_wrap_callable_class {
typedef result_of_callable_class<C> type;
};
template<typename C>
struct result_of_wrap_callable_class<C const> {
typedef result_of_callable_class<C> const type;
};
template<typename C>
struct result_of_wrap_callable_class<C volatile> {
typedef result_of_callable_class<C> volatile type;
};
template<typename C>
struct result_of_wrap_callable_class<C const volatile> {
typedef result_of_callable_class<C> const volatile type;
};
template<typename C>
struct result_of_wrap_callable_class<C &> {
typedef typename result_of_wrap_callable_class<C>::type &type;
};
template<typename F, bool TestCallability = true> struct cpp0x_result_of_impl;
#else // BOOST_NO_SFINAE_EXPR
template<typename T>
struct result_of_always_void
{
typedef void type;
};
template<typename F, typename Enable = void> struct cpp0x_result_of_impl {};
#endif // BOOST_NO_SFINAE_EXPR
template<typename F>
struct result_of_void_impl

View File

@ -0,0 +1,536 @@
/*
Copyright (c) Marshall Clow 2012-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
For more information, see http://www.boost.org
Based on the StringRef implementation in LLVM (http://llvm.org) and
N3422 by Jeffrey Yasskin
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
*/
#ifndef BOOST_STRING_REF_HPP
#define BOOST_STRING_REF_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/utility/string_ref_fwd.hpp>
#include <boost/throw_exception.hpp>
#include <cstddef>
#include <stdexcept>
#include <algorithm>
#include <iterator>
#include <string>
#include <iosfwd>
namespace boost {
namespace detail {
// A helper functor because sometimes we don't have lambdas
template <typename charT, typename traits>
class string_ref_traits_eq {
public:
string_ref_traits_eq ( charT ch ) : ch_(ch) {}
bool operator () ( charT val ) const { return traits::eq ( ch_, val ); }
charT ch_;
};
}
template<typename charT, typename traits>
class basic_string_ref {
public:
// types
typedef charT value_type;
typedef const charT* pointer;
typedef const charT& reference;
typedef const charT& const_reference;
typedef pointer const_iterator; // impl-defined
typedef const_iterator iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef const_reverse_iterator reverse_iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);
// construct/copy
BOOST_CONSTEXPR basic_string_ref ()
: ptr_(NULL), len_(0) {}
BOOST_CONSTEXPR basic_string_ref (const basic_string_ref &rhs)
: ptr_(rhs.ptr_), len_(rhs.len_) {}
basic_string_ref& operator=(const basic_string_ref &rhs) {
ptr_ = rhs.ptr_;
len_ = rhs.len_;
return *this;
}
basic_string_ref(const charT* str)
: ptr_(str), len_(traits::length(str)) {}
template<typename Allocator>
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str)
: ptr_(str.data()), len_(str.length()) {}
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len)
: ptr_(str), len_(len) {}
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
template<typename Allocator>
explicit operator std::basic_string<charT, traits, Allocator>() const {
return std::basic_string<charT, traits, Allocator> ( ptr_, len_ );
}
#endif
std::basic_string<charT, traits> to_string () const {
return std::basic_string<charT, traits> ( ptr_, len_ );
}
// iterators
BOOST_CONSTEXPR const_iterator begin() const { return ptr_; }
BOOST_CONSTEXPR const_iterator cbegin() const { return ptr_; }
BOOST_CONSTEXPR const_iterator end() const { return ptr_ + len_; }
BOOST_CONSTEXPR const_iterator cend() const { return ptr_ + len_; }
const_reverse_iterator rbegin() const { return const_reverse_iterator (end()); }
const_reverse_iterator crbegin() const { return const_reverse_iterator (end()); }
const_reverse_iterator rend() const { return const_reverse_iterator (begin()); }
const_reverse_iterator crend() const { return const_reverse_iterator (begin()); }
// capacity
BOOST_CONSTEXPR size_type size() const { return len_; }
BOOST_CONSTEXPR size_type length() const { return len_; }
BOOST_CONSTEXPR size_type max_size() const { return len_; }
BOOST_CONSTEXPR bool empty() const { return len_ == 0; }
// element access
BOOST_CONSTEXPR const charT& operator[](size_type pos) const { return ptr_[pos]; }
const charT& at(size_t pos) const {
if ( pos >= len_ )
BOOST_THROW_EXCEPTION( std::out_of_range ( "boost::string_ref::at" ) );
return ptr_[pos];
}
BOOST_CONSTEXPR const charT& front() const { return ptr_[0]; }
BOOST_CONSTEXPR const charT& back() const { return ptr_[len_-1]; }
BOOST_CONSTEXPR const charT* data() const { return ptr_; }
// modifiers
void clear() { len_ = 0; }
void remove_prefix(size_type n) {
if ( n > len_ )
n = len_;
ptr_ += n;
len_ -= n;
}
void remove_suffix(size_type n) {
if ( n > len_ )
n = len_;
len_ -= n;
}
// basic_string_ref string operations
basic_string_ref substr(size_type pos, size_type n=npos) const {
if ( pos > size())
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_ref::substr" ) );
if ( n == npos || pos + n > size())
n = size () - pos;
return basic_string_ref ( data() + pos, n );
}
int compare(basic_string_ref x) const {
const int cmp = traits::compare ( ptr_, x.ptr_, (std::min)(len_, x.len_));
return cmp != 0 ? cmp : ( len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1 );
}
bool starts_with(charT c) const { return !empty() && traits::eq ( c, front()); }
bool starts_with(basic_string_ref x) const {
return len_ >= x.len_ && traits::compare ( ptr_, x.ptr_, x.len_ ) == 0;
}
bool ends_with(charT c) const { return !empty() && traits::eq ( c, back()); }
bool ends_with(basic_string_ref x) const {
return len_ >= x.len_ && traits::compare ( ptr_ + len_ - x.len_, x.ptr_, x.len_ ) == 0;
}
size_type find(basic_string_ref s) const {
const_iterator iter = std::search ( this->cbegin (), this->cend (),
s.cbegin (), s.cend (), traits::eq );
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
}
size_type find(charT c) const {
const_iterator iter = std::find_if ( this->cbegin (), this->cend (),
detail::string_ref_traits_eq<charT, traits> ( c ));
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
}
size_type rfind(basic_string_ref s) const {
const_reverse_iterator iter = std::search ( this->crbegin (), this->crend (),
s.crbegin (), s.crend (), traits::eq );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
}
size_type rfind(charT c) const {
const_reverse_iterator iter = std::find_if ( this->crbegin (), this->crend (),
detail::string_ref_traits_eq<charT, traits> ( c ));
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
}
size_type find_first_of(charT c) const { return find (c); }
size_type find_last_of (charT c) const { return rfind (c); }
size_type find_first_of(basic_string_ref s) const {
const_iterator iter = std::find_first_of
( this->cbegin (), this->cend (), s.cbegin (), s.cend (), traits::eq );
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
}
size_type find_last_of(basic_string_ref s) const {
const_reverse_iterator iter = std::find_first_of
( this->crbegin (), this->crend (), s.cbegin (), s.cend (), traits::eq );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter);
}
size_type find_first_not_of(basic_string_ref s) const {
const_iterator iter = find_not_of ( this->cbegin (), this->cend (), s );
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
}
size_type find_first_not_of(charT c) const {
for ( const_iterator iter = this->cbegin (); iter != this->cend (); ++iter )
if ( !traits::eq ( c, *iter ))
return std::distance ( this->cbegin (), iter );
return npos;
}
size_type find_last_not_of(basic_string_ref s) const {
const_reverse_iterator iter = find_not_of ( this->crbegin (), this->crend (), s );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
}
size_type find_last_not_of(charT c) const {
for ( const_reverse_iterator iter = this->crbegin (); iter != this->crend (); ++iter )
if ( !traits::eq ( c, *iter ))
return reverse_distance ( this->crbegin (), iter );
return npos;
}
private:
template <typename r_iter>
size_type reverse_distance ( r_iter first, r_iter last ) const {
return len_ - 1 - std::distance ( first, last );
}
template <typename Iterator>
Iterator find_not_of ( Iterator first, Iterator last, basic_string_ref s ) const {
for ( ; first != last ; ++first )
if ( 0 == traits::find ( s.ptr_, s.len_, *first ))
return first;
return last;
}
const charT *ptr_;
std::size_t len_;
};
// Comparison operators
// Equality
template<typename charT, typename traits>
inline bool operator==(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
if ( x.size () != y.size ()) return false;
return x.compare(y) == 0;
}
template<typename charT, typename traits, typename Allocator>
inline bool operator==(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x == basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline bool operator==(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) == y;
}
template<typename charT, typename traits>
inline bool operator==(basic_string_ref<charT, traits> x, const charT * y) {
return x == basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits>
inline bool operator==(const charT * x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) == y;
}
// Inequality
template<typename charT, typename traits>
inline bool operator!=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
if ( x.size () != y.size ()) return true;
return x.compare(y) != 0;
}
template<typename charT, typename traits, typename Allocator>
inline bool operator!=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x != basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline bool operator!=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) != y;
}
template<typename charT, typename traits>
inline bool operator!=(basic_string_ref<charT, traits> x, const charT * y) {
return x != basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits>
inline bool operator!=(const charT * x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) != y;
}
// Less than
template<typename charT, typename traits>
inline bool operator<(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
return x.compare(y) < 0;
}
template<typename charT, typename traits, typename Allocator>
inline bool operator<(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x < basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline bool operator<(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) < y;
}
template<typename charT, typename traits>
inline bool operator<(basic_string_ref<charT, traits> x, const charT * y) {
return x < basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits>
inline bool operator<(const charT * x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) < y;
}
// Greater than
template<typename charT, typename traits>
inline bool operator>(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
return x.compare(y) > 0;
}
template<typename charT, typename traits, typename Allocator>
inline bool operator>(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x > basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline bool operator>(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) > y;
}
template<typename charT, typename traits>
inline bool operator>(basic_string_ref<charT, traits> x, const charT * y) {
return x > basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits>
inline bool operator>(const charT * x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) > y;
}
// Less than or equal to
template<typename charT, typename traits>
inline bool operator<=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
return x.compare(y) <= 0;
}
template<typename charT, typename traits, typename Allocator>
inline bool operator<=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x <= basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline bool operator<=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) <= y;
}
template<typename charT, typename traits>
inline bool operator<=(basic_string_ref<charT, traits> x, const charT * y) {
return x <= basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits>
inline bool operator<=(const charT * x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) <= y;
}
// Greater than or equal to
template<typename charT, typename traits>
inline bool operator>=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
return x.compare(y) >= 0;
}
template<typename charT, typename traits, typename Allocator>
inline bool operator>=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x >= basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline bool operator>=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) >= y;
}
template<typename charT, typename traits>
inline bool operator>=(basic_string_ref<charT, traits> x, const charT * y) {
return x >= basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits>
inline bool operator>=(const charT * x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) >= y;
}
namespace detail {
template<class charT, class traits>
inline void insert_fill_chars(std::basic_ostream<charT, traits>& os, std::size_t n) {
enum { chunk_size = 8 };
charT fill_chars[chunk_size];
std::fill_n(fill_chars, static_cast< std::size_t >(chunk_size), os.fill());
for (; n >= chunk_size && os.good(); n -= chunk_size)
os.write(fill_chars, static_cast< std::size_t >(chunk_size));
if (n > 0 && os.good())
os.write(fill_chars, n);
}
template<class charT, class traits>
void insert_aligned(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) {
const std::size_t size = str.size();
const std::size_t alignment_size = static_cast< std::size_t >(os.width()) - size;
const bool align_left = (os.flags() & std::basic_ostream<charT, traits>::adjustfield) == std::basic_ostream<charT, traits>::left;
if (!align_left) {
detail::insert_fill_chars(os, alignment_size);
if (os.good())
os.write(str.data(), size);
}
else {
os.write(str.data(), size);
if (os.good())
detail::insert_fill_chars(os, alignment_size);
}
}
} // namespace detail
// Inserter
template<class charT, class traits>
inline std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) {
if (os.good()) {
const std::size_t size = str.size();
const std::size_t w = static_cast< std::size_t >(os.width());
if (w <= size)
os.write(str.data(), size);
else
detail::insert_aligned(os, str);
os.width(0);
}
return os;
}
#if 0
// numeric conversions
//
// These are short-term implementations.
// In a production environment, I would rather avoid the copying.
//
inline int stoi (string_ref str, size_t* idx=0, int base=10) {
return std::stoi ( std::string(str), idx, base );
}
inline long stol (string_ref str, size_t* idx=0, int base=10) {
return std::stol ( std::string(str), idx, base );
}
inline unsigned long stoul (string_ref str, size_t* idx=0, int base=10) {
return std::stoul ( std::string(str), idx, base );
}
inline long long stoll (string_ref str, size_t* idx=0, int base=10) {
return std::stoll ( std::string(str), idx, base );
}
inline unsigned long long stoull (string_ref str, size_t* idx=0, int base=10) {
return std::stoull ( std::string(str), idx, base );
}
inline float stof (string_ref str, size_t* idx=0) {
return std::stof ( std::string(str), idx );
}
inline double stod (string_ref str, size_t* idx=0) {
return std::stod ( std::string(str), idx );
}
inline long double stold (string_ref str, size_t* idx=0) {
return std::stold ( std::string(str), idx );
}
inline int stoi (wstring_ref str, size_t* idx=0, int base=10) {
return std::stoi ( std::wstring(str), idx, base );
}
inline long stol (wstring_ref str, size_t* idx=0, int base=10) {
return std::stol ( std::wstring(str), idx, base );
}
inline unsigned long stoul (wstring_ref str, size_t* idx=0, int base=10) {
return std::stoul ( std::wstring(str), idx, base );
}
inline long long stoll (wstring_ref str, size_t* idx=0, int base=10) {
return std::stoll ( std::wstring(str), idx, base );
}
inline unsigned long long stoull (wstring_ref str, size_t* idx=0, int base=10) {
return std::stoull ( std::wstring(str), idx, base );
}
inline float stof (wstring_ref str, size_t* idx=0) {
return std::stof ( std::wstring(str), idx );
}
inline double stod (wstring_ref str, size_t* idx=0) {
return std::stod ( std::wstring(str), idx );
}
inline long double stold (wstring_ref str, size_t* idx=0) {
return std::stold ( std::wstring(str), idx );
}
#endif
}
#if 0
namespace std {
// Hashing
template<> struct hash<boost::string_ref>;
template<> struct hash<boost::u16string_ref>;
template<> struct hash<boost::u32string_ref>;
template<> struct hash<boost::wstring_ref>;
}
#endif
#endif

View File

@ -0,0 +1,37 @@
/*
Copyright (c) Marshall Clow 2012-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
For more information, see http://www.boost.org
Based on the StringRef implementation in LLVM (http://llvm.org) and
N3422 by Jeffrey Yasskin
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
*/
#ifndef BOOST_STRING_REF_FWD_HPP
#define BOOST_STRING_REF_FWD_HPP
#include <boost/config.hpp>
#include <string>
namespace boost {
template<typename charT, typename traits = std::char_traits<charT> > class basic_string_ref;
typedef basic_string_ref<char, std::char_traits<char> > string_ref;
typedef basic_string_ref<wchar_t, std::char_traits<wchar_t> > wstring_ref;
#ifndef BOOST_NO_CXX11_CHAR16_T
typedef basic_string_ref<char16_t, std::char_traits<char16_t> > u16string_ref;
#endif
#ifndef BOOST_NO_CXX11_CHAR32_T
typedef basic_string_ref<char32_t, std::char_traits<char32_t> > u32string_ref;
#endif
}
#endif

View File

@ -5,7 +5,7 @@
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com

View File

@ -14,20 +14,30 @@
<p>But that doesn't mean there isn't useful stuff here. Take a look:</p>
<blockquote>
<p>
<a href="utility.htm#addressof">addressof</a><br>
<a href="assert.html">assert</a><br>
<a href="base_from_member.html">base_from_member</a><br>
<a href="utility.htm#BOOST_BINARY">BOOST_BINARY</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="current_function.html">current_function</a><br>
<a href="doc/html/declval.html">declval</a><br>
<a href="enable_if.html">enable_if</a><br>
<a href="iterator_adaptors.htm">iterator_adaptors</a><br>
<a href="generator_iterator.htm">generator iterator adaptors</a><br>
<a href="in_place_factories.html">in_place_factory</a><br>
<a href="iterator_adaptors.htm">iterator_adaptors</a><br>
<a href="generator_iterator.htm">generator iterator adaptors</a><br>
<a href="utility.htm#functions_next_prior">next/prior</a><br>
<a href="utility.htm#Class_noncopyable">noncopyable</a><br>
<a href="operators.htm">operators</a><br>
<a href="utility.htm#result_of">result_of</a><br>
<a href="swap.html">swap</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>
<a href="doc/html/string_ref.html">string_ref</a><br>
<a href="value_init.htm">value_init</a>
<a href="doc/html/explicit_operator_bool.html">BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL</a><br>
</p>
</blockquote>
<hr>
<p>&copy; Copyright Beman Dawes, 2001</p>

View File

@ -8,6 +8,11 @@
# bring in rules for testing
import testing ;
alias unit_test_framework
: # sources
/boost//unit_test_framework
;
# Please keep the tests ordered by filename
test-suite utility
:
@ -31,7 +36,11 @@ test-suite utility
[ run ../ref_test.cpp ../../test/build//boost_test_exec_monitor/<link>static ]
[ compile result_of_test.cpp ]
[ run ../shared_iterator_test.cpp ]
[ run string_ref_test1.cpp unit_test_framework ]
[ run string_ref_test2.cpp unit_test_framework ]
[ run string_ref_test_io.cpp unit_test_framework ]
[ run ../value_init_test.cpp ]
[ run ../value_init_workaround_test.cpp ]
[ run ../initialized_test.cpp ]
[ compile-fail ../value_init_test_fail1.cpp ]
[ compile-fail ../value_init_test_fail2.cpp ]
@ -39,5 +48,10 @@ test-suite utility
[ compile-fail ../initialized_test_fail1.cpp ]
[ compile-fail ../initialized_test_fail2.cpp ]
[ run ../verify_test.cpp ]
[ run explicit_operator_bool.cpp ]
[ compile-fail explicit_operator_bool_compile_fail_conv_int.cpp ]
[ compile-fail explicit_operator_bool_compile_fail_conv_pvoid.cpp ]
[ compile-fail explicit_operator_bool_compile_fail_delete.cpp ]
[ compile-fail explicit_operator_bool_compile_fail_shift.cpp ]
;

View File

@ -0,0 +1,54 @@
/*
* Copyright Andrey Semashev 2007 - 2013.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file explicit_operator_bool_compile.cpp
* \author Andrey Semashev
* \date 17.07.2010
*
* \brief This test checks that explicit operator bool can be used in
* the valid contexts.
*/
#define BOOST_TEST_MODULE explicit_operator_bool_compile
#include <boost/utility/explicit_operator_bool.hpp>
namespace {
// A test object that has the operator of explicit conversion to bool
struct checkable1
{
BOOST_EXPLICIT_OPERATOR_BOOL()
bool operator! () const
{
return false;
}
};
struct checkable2
{
BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()
BOOST_CONSTEXPR bool operator! () const
{
return false;
}
};
} // namespace
int main(int, char*[])
{
checkable1 val1;
if (val1)
{
checkable2 val2;
if (val2)
return 0;
}
return 1;
}

View File

@ -0,0 +1,40 @@
/*
* Copyright Andrey Semashev 2007 - 2013.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file explicit_operator_bool_compile_fail_conv_int.cpp
* \author Andrey Semashev
* \date 17.07.2010
*
* \brief This test checks that explicit operator bool cannot be used in
* an unintended context.
*/
#define BOOST_TEST_MODULE explicit_operator_bool_compile_fail_conv_int
#include <boost/utility/explicit_operator_bool.hpp>
namespace {
// A test object that has the operator of explicit conversion to bool
struct checkable
{
BOOST_EXPLICIT_OPERATOR_BOOL()
bool operator! () const
{
return false;
}
};
} // namespace
int main(int, char*[])
{
checkable val;
int n = val;
return 0;
}

View File

@ -0,0 +1,40 @@
/*
* Copyright Andrey Semashev 2007 - 2013.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file explicit_operator_bool_compile_fail_conv_pvoid.cpp
* \author Andrey Semashev
* \date 17.07.2010
*
* \brief This test checks that explicit operator bool cannot be used in
* an unintended context.
*/
#define BOOST_TEST_MODULE explicit_operator_bool_compile_fail_conv_pvoid
#include <boost/utility/explicit_operator_bool.hpp>
namespace {
// A test object that has the operator of explicit conversion to bool
struct checkable
{
BOOST_EXPLICIT_OPERATOR_BOOL()
bool operator! () const
{
return false;
}
};
} // namespace
int main(int, char*[])
{
checkable val;
void* p = val;
return 0;
}

View File

@ -0,0 +1,40 @@
/*
* Copyright Andrey Semashev 2007 - 2013.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file explicit_operator_bool_compile_fail_delete.cpp
* \author Andrey Semashev
* \date 17.07.2010
*
* \brief This test checks that explicit operator bool cannot be used in
* an unintended context.
*/
#define BOOST_TEST_MODULE util_explicit_operator_bool_delete
#include <boost/utility/explicit_operator_bool.hpp>
namespace {
// A test object that has the operator of explicit conversion to bool
struct checkable
{
BOOST_EXPLICIT_OPERATOR_BOOL()
bool operator! () const
{
return false;
}
};
} // namespace
int main(int, char*[])
{
checkable val;
delete val;
return 0;
}

View File

@ -0,0 +1,40 @@
/*
* Copyright Andrey Semashev 2007 - 2013.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file explicit_operator_bool_compile_fail_shift.cpp
* \author Andrey Semashev
* \date 17.07.2010
*
* \brief This test checks that explicit operator bool cannot be used in
* an unintended context.
*/
#define BOOST_TEST_MODULE explicit_operator_bool_compile_fail_shift
#include <boost/utility/explicit_operator_bool.hpp>
namespace {
// A test object that has the operator of explicit conversion to bool
struct checkable
{
BOOST_EXPLICIT_OPERATOR_BOOL()
bool operator! () const
{
return false;
}
};
} // namespace
int main(int, char*[])
{
checkable val;
val << 2;
return 0;
}

0
test/next_prior_test.cpp Executable file → Normal file
View File

View File

@ -5,7 +5,13 @@
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_RESULT_OF_USE_DECLTYPE
// Examples:
// To run the default test:
// $ cd libs/utility/test && bjam
// To test decltype on g++ 2.7:
// $ cd libs/utility/test && bjam cxxflags="-std=c++11 -D BOOST_RESULT_OF_USE_DECLTYPE"
#include <boost/config.hpp>
// For more information, see http://www.boost.org/libs/utility
#include <boost/utility/result_of.hpp>
@ -62,6 +68,9 @@ struct int_result_type_and_float_result_of_and_char_return_template
char operator()(char);
};
template<typename T>
struct cv_overload_check {};
struct result_of_member_function_template
{
template<typename F> struct result;
@ -69,13 +78,13 @@ struct result_of_member_function_template
template<typename This, typename That> struct result<This(That)> { typedef That type; };
template<class T> typename result<result_of_member_function_template(T)>::type operator()(T);
template<typename This, typename That> struct result<const This(That)> { typedef const That type; };
template<typename This, typename That> struct result<const This(That)> { typedef cv_overload_check<const That> type; };
template<class T> typename result<const result_of_member_function_template(T)>::type operator()(T) const;
template<typename This, typename That> struct result<volatile This(That)> { typedef volatile That type; };
template<typename This, typename That> struct result<volatile This(That)> { typedef cv_overload_check<volatile That> type; };
template<class T> typename result<volatile result_of_member_function_template(T)>::type operator()(T) volatile;
template<typename This, typename That> struct result<const volatile This(That)> { typedef const volatile That type; };
template<typename This, typename That> struct result<const volatile This(That)> { typedef cv_overload_check<const volatile That> type; };
template<class T> typename result<const volatile result_of_member_function_template(T)>::type operator()(T) const volatile;
template<typename This, typename That> struct result<This(That &, That)> { typedef That & type; };
@ -91,25 +100,62 @@ struct result_of_member_function_template
template<class T> typename result<result_of_member_function_template(T const volatile &, T)>::type operator()(T const volatile &, T);
};
struct no_result_type_or_result_of
struct no_result_type_or_result
{
int operator()(double);
short operator()(double) const;
unsigned int operator()();
unsigned short operator()() volatile;
const unsigned short operator()() const volatile;
short operator()(double);
cv_overload_check<const short> operator()(double) const;
cv_overload_check<volatile short> operator()(double) volatile;
cv_overload_check<const volatile short> operator()(double) const volatile;
int operator()();
cv_overload_check<const int> operator()() const;
cv_overload_check<volatile int> operator()() volatile;
cv_overload_check<const volatile int> operator()() const volatile;
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
short operator()(int&&);
int operator()(int&);
long operator()(int const&);
#endif
};
template<typename T>
struct no_result_type_or_result_of_template
struct no_result_type_or_result_template
{
int operator()(double);
short operator()(double) const;
unsigned int operator()();
unsigned short operator()() volatile;
const unsigned short operator()() const volatile;
short operator()(double);
cv_overload_check<const short> operator()(double) const;
cv_overload_check<volatile short> operator()(double) volatile;
cv_overload_check<const volatile short> operator()(double) const volatile;
int operator()();
cv_overload_check<const int> operator()() const;
cv_overload_check<volatile int> operator()() volatile;
cv_overload_check<const volatile int> operator()() const volatile;
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
short operator()(int&&);
int operator()(int&);
long operator()(int const&);
#endif
};
// sfinae_tests are derived from example code from Joel de Guzman,
// which demonstrated the interaction between result_of and SFINAE.
template <typename F, typename Arg>
typename boost::result_of<F(Arg const&)>::type
sfinae_test(F f, Arg const& arg)
{
return f(arg);
}
template <typename F, typename Arg>
typename boost::result_of<F(Arg&)>::type
sfinae_test(F f, Arg& arg)
{
return f(arg);
}
int sfinae_test_f(int& i)
{
return i;
}
struct X {};
int main()
@ -120,6 +166,10 @@ int main()
typedef int (&func_ref)(float, double);
typedef int (*func_ptr_0)();
typedef int (&func_ref_0)();
typedef void (*func_ptr_void)(float, double);
typedef void (&func_ref_void)(float, double);
typedef void (*func_ptr_void_0)();
typedef void (&func_ref_void_0)();
typedef int (X::*mem_func_ptr)(float);
typedef int (X::*mem_func_ptr_c)(float) const;
typedef int (X::*mem_func_ptr_v)(float) volatile;
@ -146,8 +196,8 @@ int main()
BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile int_result_of_template<void>(void)>::type, void>::value));
// Prior to decltype, result_of could not deduce the return type
// nullary function objects unless they exposed a result_type.
#if !defined(BOOST_NO_DECLTYPE)
// of nullary function objects unless they exposed a result_type.
#if defined(BOOST_RESULT_OF_USE_DECLTYPE)
BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(void)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of(void)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<int_result_of_template<void>(void)>::type, int>::value));
@ -159,14 +209,11 @@ int main()
BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of_template<void>(void)>::type, void>::value));
#endif
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
// Prior to decltype, result_of ignored a nested result<> if
// result_type was defined. After decltype, result_of deduces the
// actual return type of the function object, ignoring both
// result<> and result_type.
#if !defined(BOOST_NO_DECLTYPE)
#if defined(BOOST_RESULT_OF_USE_DECLTYPE)
BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, char>::value));
BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, char>::value));
#else
@ -174,41 +221,52 @@ int main()
BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
#endif
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr(char, float)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<func_ref(char, float)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_0()>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<func_ref_0()>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_void(char, float)>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<result_of<func_ref_void(char, float)>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_void_0()>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<result_of<func_ref_void_0()>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_c(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_v(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_cv(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_0(X)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr(void)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(char, float)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref(char, float)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_0()>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_0()>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_void(char, float)>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_void(char, float)>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_void_0()>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_void_0()>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_c(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_v(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_cv(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_0(X)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(void)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref(void)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(double)>::type, double>::value));
BOOST_STATIC_ASSERT((is_same<result_of<const result_of_member_function_template(double)>::type, const double>::value));
BOOST_STATIC_ASSERT((is_same<result_of<volatile result_of_member_function_template(double)>::type, volatile double>::value));
BOOST_STATIC_ASSERT((is_same<result_of<const volatile result_of_member_function_template(double)>::type, const volatile double>::value));
BOOST_STATIC_ASSERT((is_same<result_of<const result_of_member_function_template(double)>::type, cv_overload_check<const double> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<volatile result_of_member_function_template(double)>::type, cv_overload_check<volatile double> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<const volatile result_of_member_function_template(double)>::type, cv_overload_check<const volatile double> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int &, int)>::type, int &>::value));
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int const &, int)>::type, int const &>::value));
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int volatile &, int)>::type, int volatile &>::value));
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int const volatile &, int)>::type, int const volatile &>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(double)>::type, double>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<const result_of_member_function_template(double)>::type, const double>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile result_of_member_function_template(double)>::type, volatile double>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<const volatile result_of_member_function_template(double)>::type, const volatile double>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<const result_of_member_function_template(double)>::type, cv_overload_check<const double> >::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile result_of_member_function_template(double)>::type, cv_overload_check<volatile double> >::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<const volatile result_of_member_function_template(double)>::type, cv_overload_check<const volatile double> >::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int &, int)>::type, int &>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int const &, int)>::type, int const &>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int volatile &, int)>::type, int volatile &>::value));
@ -221,18 +279,38 @@ int main()
BOOST_STATIC_ASSERT((is_same<tr1_result_of<pf_t(int)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<pf_t const(int)>::type,int>::value));
#if !defined(BOOST_NO_DECLTYPE)
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of(double)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of(void)>::type, unsigned int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_of(double)>::type, short>::value));
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_of(void)>::type, unsigned short>::value));
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_of(void)>::type, const unsigned short>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of_template<void>(double)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of_template<void>(void)>::type, unsigned int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_of_template<void>(double)>::type, short>::value));
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_of_template<void>(void)>::type, unsigned short>::value));
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_of_template<void>(void)>::type, const unsigned short>::value));
#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(double)>::type, short>::value));
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result(double)>::type, cv_overload_check<const short> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result(double)>::type, cv_overload_check<volatile short> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result(double)>::type, cv_overload_check<const volatile short> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(void)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result(void)>::type, cv_overload_check<const int> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result(void)>::type, cv_overload_check<volatile int> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result(void)>::type, cv_overload_check<const volatile int> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(double)>::type, short>::value));
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(double)>::type, cv_overload_check<const short> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(double)>::type, cv_overload_check<volatile short> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_template<void>(double)>::type, cv_overload_check<const volatile short> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(void)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const int> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<volatile int> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const volatile int> >::value));
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&&)>::type, short>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int const&)>::type, long>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int&&)>::type, short>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int&)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int const&)>::type, long>::value));
#endif
#endif
#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
int i = 123;
sfinae_test(sfinae_test_f, i);
#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
return 0;
}

109
test/string_ref_test1.cpp Normal file
View File

@ -0,0 +1,109 @@
/*
Copyright (c) Marshall Clow 2012-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
For more information, see http://www.boost.org
*/
#include <iostream>
#include <algorithm>
#include <string>
#include <boost/utility/string_ref.hpp>
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
typedef boost::string_ref string_ref;
// Should be equal
void interop ( const std::string &str, string_ref ref ) {
// BOOST_CHECK ( str == ref );
BOOST_CHECK ( str.size () == ref.size ());
BOOST_CHECK ( std::equal ( str.begin (), str.end (), ref.begin ()));
BOOST_CHECK ( std::equal ( str.rbegin (), str.rend (), ref.rbegin ()));
}
void null_tests ( const char *p ) {
// All zero-length string-refs should be equal
string_ref sr1; // NULL, 0
string_ref sr2 ( NULL, 0 );
string_ref sr3 ( p, 0 );
string_ref sr4 ( p );
sr4.clear ();
BOOST_CHECK ( sr1 == sr2 );
BOOST_CHECK ( sr1 == sr3 );
BOOST_CHECK ( sr2 == sr3 );
BOOST_CHECK ( sr1 == sr4 );
}
// make sure that substrings work just like strings
void test_substr ( const std::string &str ) {
const size_t sz = str.size ();
string_ref ref ( str );
// Substrings at the end
for ( size_t i = 0; i <= sz; ++ i )
interop ( str.substr ( i ), ref.substr ( i ));
// Substrings at the beginning
for ( size_t i = 0; i <= sz; ++ i )
interop ( str.substr ( 0, i ), ref.substr ( 0, i ));
// All possible substrings
for ( size_t i = 0; i < sz; ++i )
for ( size_t j = i; j < sz; ++j )
interop ( str.substr ( i, j ), ref.substr ( i, j ));
}
// make sure that removing prefixes and suffixes work just like strings
void test_remove ( const std::string &str ) {
const size_t sz = str.size ();
std::string work;
string_ref ref;
for ( size_t i = 1; i <= sz; ++i ) {
work = str;
ref = str;
while ( ref.size () >= i ) {
interop ( work, ref );
work.erase ( 0, i );
ref.remove_prefix (i);
}
}
for ( size_t i = 1; i < sz; ++ i ) {
work = str;
ref = str;
while ( ref.size () >= i ) {
interop ( work, ref );
work.erase ( work.size () - i, i );
ref.remove_suffix (i);
}
}
}
const char *test_strings [] = {
"",
"1",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"0123456789",
NULL
};
BOOST_AUTO_TEST_CASE( test_main )
{
const char **p = &test_strings[0];
while ( *p != NULL ) {
interop ( *p, *p );
test_substr ( *p );
test_remove ( *p );
null_tests ( *p );
p++;
}
}

318
test/string_ref_test2.cpp Normal file
View File

@ -0,0 +1,318 @@
/*
Copyright (c) Marshall Clow 2012-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
For more information, see http://www.boost.org
*/
#include <iostream>
#include <cstring> // for std::strchr
#include <boost/utility/string_ref.hpp>
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
typedef boost::string_ref string_ref;
void ends_with ( const char *arg ) {
const size_t sz = strlen ( arg );
string_ref sr ( arg );
string_ref sr2 ( arg );
const char *p = arg;
while ( *p ) {
BOOST_CHECK ( sr.ends_with ( p ));
++p;
}
while ( !sr2.empty ()) {
BOOST_CHECK ( sr.ends_with ( sr2 ));
sr2.remove_prefix (1);
}
sr2 = arg;
while ( !sr2.empty ()) {
BOOST_CHECK ( sr.ends_with ( sr2 ));
sr2.remove_prefix (1);
}
char ch = sz == 0 ? '\0' : arg [ sz - 1 ];
sr2 = arg;
if ( sz > 0 )
BOOST_CHECK ( sr2.ends_with ( ch ));
BOOST_CHECK ( !sr2.ends_with ( ++ch ));
BOOST_CHECK ( sr2.ends_with ( string_ref ()));
}
void starts_with ( const char *arg ) {
const size_t sz = strlen ( arg );
string_ref sr ( arg );
string_ref sr2 ( arg );
const char *p = arg + std::strlen ( arg ) - 1;
while ( p >= arg ) {
std::string foo ( arg, p + 1 );
BOOST_CHECK ( sr.starts_with ( foo ));
--p;
}
while ( !sr2.empty ()) {
BOOST_CHECK ( sr.starts_with ( sr2 ));
sr2.remove_suffix (1);
}
char ch = *arg;
sr2 = arg;
if ( sz > 0 )
BOOST_CHECK ( sr2.starts_with ( ch ));
BOOST_CHECK ( !sr2.starts_with ( ++ch ));
BOOST_CHECK ( sr2.starts_with ( string_ref ()));
}
void reverse ( const char *arg ) {
// Round trip
string_ref sr1 ( arg );
std::string string1 ( sr1.rbegin (), sr1.rend ());
string_ref sr2 ( string1 );
std::string string2 ( sr2.rbegin (), sr2.rend ());
BOOST_CHECK ( std::equal ( sr2.rbegin (), sr2.rend (), arg ));
BOOST_CHECK ( string2 == arg );
BOOST_CHECK ( std::equal ( sr1.begin (), sr1.end (), string2.begin ()));
}
// This helper function eliminates signed vs. unsigned warnings
string_ref::size_type ptr_diff ( const char *res, const char *base ) {
BOOST_CHECK ( res >= base );
return static_cast<string_ref::size_type> ( res - base );
}
void find ( const char *arg ) {
string_ref sr1;
string_ref sr2;
const char *p;
// Look for each character in the string(searching from the start)
p = arg;
sr1 = arg;
while ( *p ) {
string_ref::size_type pos = sr1.find(*p);
BOOST_CHECK ( pos != string_ref::npos && ( pos <= ptr_diff ( p, arg )));
++p;
}
// Look for each character in the string (searching from the end)
p = arg;
sr1 = arg;
while ( *p ) {
string_ref::size_type pos = sr1.rfind(*p);
BOOST_CHECK ( pos != string_ref::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg )));
++p;
}
// Look for pairs on characters (searching from the start)
sr1 = arg;
p = arg;
while ( *p && *(p+1)) {
string_ref sr3 ( p, 2 );
string_ref::size_type pos = sr1.find ( sr3 );
BOOST_CHECK ( pos != string_ref::npos && pos <= static_cast<string_ref::size_type>( p - arg ));
p++;
}
sr1 = arg;
p = arg;
// for all possible chars, see if we find them in the right place.
// Note that strchr will/might do the _wrong_ thing if we search for NULL
for ( int ch = 1; ch < 256; ++ch ) {
string_ref::size_type pos = sr1.find(ch);
const char *strp = std::strchr ( arg, ch );
BOOST_CHECK (( strp == NULL ) == ( pos == string_ref::npos ));
if ( strp != NULL )
BOOST_CHECK ( ptr_diff ( strp, arg ) == pos );
}
sr1 = arg;
p = arg;
// for all possible chars, see if we find them in the right place.
// Note that strchr will/might do the _wrong_ thing if we search for NULL
for ( int ch = 1; ch < 256; ++ch ) {
string_ref::size_type pos = sr1.rfind(ch);
const char *strp = std::strrchr ( arg, ch );
BOOST_CHECK (( strp == NULL ) == ( pos == string_ref::npos ));
if ( strp != NULL )
BOOST_CHECK ( ptr_diff ( strp, arg ) == pos );
}
// Find everything at the start
p = arg;
sr1 = arg;
while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.find(*p);
BOOST_CHECK ( pos == 0 );
sr1.remove_prefix (1);
++p;
}
// Find everything at the end
sr1 = arg;
p = arg + strlen ( arg ) - 1;
while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.rfind(*p);
BOOST_CHECK ( pos == sr1.size () - 1 );
sr1.remove_suffix (1);
--p;
}
// Find everything at the start
sr1 = arg;
p = arg;
while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.find_first_of(*p);
BOOST_CHECK ( pos == 0 );
sr1.remove_prefix (1);
++p;
}
// Find everything at the end
sr1 = arg;
p = arg + strlen ( arg ) - 1;
while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.find_last_of(*p);
BOOST_CHECK ( pos == sr1.size () - 1 );
sr1.remove_suffix (1);
--p;
}
// Basic sanity checking for "find_first_of / find_first_not_of"
sr1 = arg;
sr2 = arg;
while ( !sr1.empty() ) {
BOOST_CHECK ( sr1.find_first_of ( sr2 ) == 0 );
BOOST_CHECK ( sr1.find_first_not_of ( sr2 ) == string_ref::npos );
sr1.remove_prefix ( 1 );
}
p = arg;
sr1 = arg;
while ( *p ) {
string_ref::size_type pos1 = sr1.find_first_of(*p);
string_ref::size_type pos2 = sr1.find_first_not_of(*p);
BOOST_CHECK ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 <= ptr_diff ( p, arg ));
if ( pos2 != string_ref::npos ) {
for ( size_t i = 0 ; i < pos2; ++i )
BOOST_CHECK ( sr1[i] == *p );
BOOST_CHECK ( sr1 [ pos2 ] != *p );
}
BOOST_CHECK ( pos2 != pos1 );
++p;
}
// Basic sanity checking for "find_last_of / find_last_not_of"
sr1 = arg;
sr2 = arg;
while ( !sr1.empty() ) {
BOOST_CHECK ( sr1.find_last_of ( sr2 ) == ( sr1.size () - 1 ));
BOOST_CHECK ( sr1.find_last_not_of ( sr2 ) == string_ref::npos );
sr1.remove_suffix ( 1 );
}
p = arg;
sr1 = arg;
while ( *p ) {
string_ref::size_type pos1 = sr1.find_last_of(*p);
string_ref::size_type pos2 = sr1.find_last_not_of(*p);
BOOST_CHECK ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 >= ptr_diff ( p, arg ));
BOOST_CHECK ( pos2 == string_ref::npos || pos1 < sr1.size ());
if ( pos2 != string_ref::npos ) {
for ( size_t i = sr1.size () -1 ; i > pos2; --i )
BOOST_CHECK ( sr1[i] == *p );
BOOST_CHECK ( sr1 [ pos2 ] != *p );
}
BOOST_CHECK ( pos2 != pos1 );
++p;
}
}
void to_string ( const char *arg ) {
string_ref sr1;
std::string str1;
std::string str2;
str1.assign ( arg );
sr1 = arg;
// str2 = sr1.to_string<std::allocator<char> > ();
str2 = sr1.to_string ();
BOOST_CHECK ( str1 == str2 );
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
std::string str3 = static_cast<std::string> ( sr1 );
BOOST_CHECK ( str1 == str3 );
#endif
}
void compare ( const char *arg ) {
string_ref sr1;
std::string str1;
std::string str2 = str1;
str1.assign ( arg );
sr1 = arg;
BOOST_CHECK ( sr1 == sr1); // compare string_ref and string_ref
BOOST_CHECK ( sr1 == str1); // compare string and string_ref
BOOST_CHECK ( str1 == sr1 ); // compare string_ref and string
BOOST_CHECK ( sr1 == arg ); // compare string_ref and pointer
BOOST_CHECK ( arg == sr1 ); // compare pointer and string_ref
if ( sr1.size () > 0 ) {
(*str1.rbegin())++;
BOOST_CHECK ( sr1 != str1 );
BOOST_CHECK ( str1 != sr1 );
BOOST_CHECK ( sr1 < str1 );
BOOST_CHECK ( sr1 <= str1 );
BOOST_CHECK ( str1 > sr1 );
BOOST_CHECK ( str1 >= sr1 );
(*str1.rbegin()) -= 2;
BOOST_CHECK ( sr1 != str1 );
BOOST_CHECK ( str1 != sr1 );
BOOST_CHECK ( sr1 > str1 );
BOOST_CHECK ( sr1 >= str1 );
BOOST_CHECK ( str1 < sr1 );
BOOST_CHECK ( str1 <= sr1 );
}
}
const char *test_strings [] = {
"",
"0",
"abc",
"AAA", // all the same
"adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf",
"abc\0asdfadsfasf",
NULL
};
BOOST_AUTO_TEST_CASE( test_main )
{
const char **p = &test_strings[0];
while ( *p != NULL ) {
starts_with ( *p );
ends_with ( *p );
reverse ( *p );
find ( *p );
to_string ( *p );
compare ( *p );
p++;
}
}

183
test/string_ref_test_io.cpp Normal file
View File

@ -0,0 +1,183 @@
/*
* Copyright Andrey Semashev 2013.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file string_ref_test_io.cpp
* \author Andrey Semashev
* \date 26.05.2013
*
* \brief This header contains tests for stream operations of \c basic_string_ref.
*/
#define BOOST_TEST_MODULE string_ref_test_io
#include <boost/utility/string_ref.hpp>
#include <iomanip>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <string>
#include <boost/config.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/test/unit_test.hpp>
typedef boost::mpl::vector<
char
#if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_STD_WSTREAMBUF) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
, wchar_t
#endif
/* Current implementations seem to be missing codecvt facets to convert chars to char16_t and char32_t even though the types are available.
#if !defined(BOOST_NO_CXX11_CHAR16_T)
, char16_t
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
, char32_t
#endif
*/
>::type char_types;
static const char* test_strings[] =
{
"begin",
"abcd",
"end"
};
//! The context with test data for particular character type
template< typename CharT >
struct context
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
string_type begin, abcd, end;
context()
{
boost::string_ref str = test_strings[0];
std::copy(str.begin(), str.end(), std::back_inserter(begin));
str = test_strings[1];
std::copy(str.begin(), str.end(), std::back_inserter(abcd));
str = test_strings[2];
std::copy(str.begin(), str.end(), std::back_inserter(end));
}
};
// Test regular output
BOOST_AUTO_TEST_CASE_TEMPLATE(string_ref_output, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type;
context< char_type > ctx;
ostream_type strm;
strm << string_ref_type(ctx.abcd);
BOOST_CHECK(strm.str() == ctx.abcd);
}
// Test support for padding
BOOST_AUTO_TEST_CASE_TEMPLATE(padding, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type;
context< char_type > ctx;
// Test for padding
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
// Test for long padding
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::setw(100) << string_ref_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::setw(100) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
// Test that short width does not truncate the string
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::setw(1) << string_ref_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::setw(1) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
}
// Test support for padding fill
BOOST_AUTO_TEST_CASE_TEMPLATE(padding_fill, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type;
context< char_type > ctx;
ostream_type strm_ref;
strm_ref << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
// Test support for alignment
BOOST_AUTO_TEST_CASE_TEMPLATE(alignment, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type;
context< char_type > ctx;
// Left alignment
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::left << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::left << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
// Right alignment
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::right << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::right << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
}

View File

@ -84,8 +84,10 @@ const std::list&lt;T&gt;::iterator next = boost::next(prev, 2);</pre>
will prevent the otherwise implicitly-generated functions (which don't have the
proper semantics) from becoming a trap for other programmers.</p>
<p>The traditional way to deal with these is to declare a private copy constructor
and copy assignment, and then document why this is done.&nbsp; But deriving
from <b>noncopyable</b> is simpler and clearer, and doesn't require additional
and copy assignment, and then document why this is done.&nbsp; A new alternative
was introduced in C++2011, declaring a copy constructor and a copy assignment
operator, but marking both as <code>delete</code>d.&nbsp; Deriving
from <b>noncopyable</b> is simpler and clearer, and doesn't require additional
documentation.</p>
<p>The program <a href="noncopyable_test.cpp">noncopyable_test.cpp</a> can be used
to verify class <b>noncopyable</b> works as expected. It has have been run
@ -106,7 +108,9 @@ class ResourceLadenFileSystem : boost::noncopyable {
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>
thus have non-trivial destruction semantics.&quot;&nbsp; With C++2011, using an
optimized and trivial constructor and similar destructor can be enforced by
declaring both and marking them <code>default</code>.</p>
<h2><a name="addressof">Function template addressof()</a></h2>
<p>Function <strong>addressof()</strong> returns the address of an object.</p>
<blockquote>
@ -143,7 +147,7 @@ void f() {
<h2><a name="result_of">Class template
result_of</a></h2> <p>The class template
<code>result_of</code> helps determine the type of a
call expression. Given an lvalue <code>f</code> of
call expression. For example, given an lvalue <code>f</code> of
type <code>F</code> and lvalues <code>t1</code>,
<code>t2</code>, ..., <code>t<em>N</em></code> of
types <code>T1</code>, <code>T2</code>, ...,
@ -151,37 +155,481 @@ void f() {
<code>result_of&lt;F(T1, T2, ...,
T<em>N</em>)&gt;::type</code> defines the result type
of the expression <code>f(t1, t2,
...,t<em>N</em>)</code>. The implementation permits
...,t<em>N</em>)</code>. This implementation permits
the type <code>F</code> to be a function pointer,
function reference, member function pointer, or class
type.</p> <p>If your compiler does not support
<code>decltype</code>, then when <code>F</code> is a
class type with a member type <code>result_type</code>,
type. By default, <em>N</em> may be any value between 0 and
16. To change the upper limit, define the macro
<code>BOOST_RESULT_OF_NUM_ARGS</code> to the maximum
value for <em>N</em>. Class template <code>result_of</code>
resides in the header <code>&lt;<a
href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>&gt;</code>.</p>
<p>If your compiler's support for <code>decltype</code> is
adequate, <code>result_of</code> automatically uses it to
deduce the type of the call expression, in which case
<code>result_of&lt;F(T1, T2, ...,
T<em>N</em>)&gt;</code> is
<code>F::result_type</code>. When <code>F</code>
does not contain <code>result_type</code>,
T<em>N</em>)&gt;::type</code> names the type
<code>decltype(boost::declval&lt;F&gt;()(boost::declval&lt;T1&gt;(),
boost::declval&lt;T2&gt;(), ...,
boost::declval&lt;T<em>N</em>&gt;()))</code>, as in the
following example.</p>
<blockquote>
<pre>struct functor {
template&lt;class T&gt;
T operator()(T x)
{
return x;
}
};
typedef boost::result_of&lt;
functor(int)
&gt;::type type; // type is int</pre>
</blockquote>
<p>You can test whether <code>result_of</code> is using
<code>decltype</code> by checking if the macro
<code>BOOST_RESULT_OF_USE_DECLTYPE</code> is defined after
including <code>result_of.hpp</code>. You can also force
<code>result_of</code> to use <code>decltype</code> by
defining <code>BOOST_RESULT_OF_USE_DECLTYPE</code> prior
to including <code>result_of.hpp</code>.</p>
<p>If <code>decltype</code> is not used,
then automatic result type deduction of function
objects is not possible. Instead, <code>result_of</code>
uses the following protocol to allow the programmer to
specify a type. When <code>F</code> is a class type with a
member type <code>result_type</code>,
<code>result_of&lt;F(T1, T2, ...,
T<em>N</em>)&gt;</code> is <code>F::result&lt;F(T1,
T<em>N</em>)&gt;::type</code> is
<code>F::result_type</code>. When <code>F</code> does
not contain <code>result_type</code>,
<code>result_of&lt;F(T1, T2, ...,
T<em>N</em>)&gt;::type</code> is <code>F::result&lt;F(T1,
T2, ..., T<em>N</em>)&gt;::type</code> when
<code><em>N</em> &gt; 0</code> or <code>void</code>
when <code><em>N</em> = 0</code>. For additional
information about <code>result_of</code>, see the
C++ Library Technical Report, <a
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">N1836</a>,
or, for motivation and design rationale, the <code>result_of</code> <a
href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1454.html">proposal</a>.</p>
when <code><em>N</em> = 0</code>. Note that it is the
responsibility of the programmer to ensure that
function objects accurately advertise their result
type via this protocol, as in the following
example.</p>
<p>Class template <code>result_of</code> resides in
the header <code>&lt;<a
href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>&gt;</code>. By
default, <em>N</em> may be any value between 0 and
10. To change the upper limit, define the macro
<code>BOOST_RESULT_OF_NUM_ARGS</code> to the maximum
value for <em>N</em>.</p>
<blockquote>
<pre>struct functor {
template&lt;class&gt; struct result;
template&lt;class F, class T&gt;
struct result&lt;F(T)&gt; {
typedef T type;
};
template&lt;class T&gt;
T operator()(T x)
{
return x;
}
};
typedef boost::result_of&lt;
functor(int)
&gt;::type type; // type is int</pre>
</blockquote>
<p>Since <code>decltype</code> is a new language
feature recently standardized in C++11,
if you are writing a function object
to be used with <code>result_of</code>, for
maximum portability, you might consider following
the above protocol even if your compiler has
proper <code>decltype</code> support. If you wish to continue to
use the protocol on compilers that
support <code>decltype</code>, there are two options:
You can use <code>boost::tr1_result_of</code>, which is also
defined in <code>&lt;<a href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>&gt;</code>.
Alternatively, you can define the macro
<code>BOOST_RESULT_OF_USE_TR1</code>, which causes
<code>result_of</code> to use the protocol described
above instead of <code>decltype</code>. If you choose to
follow the protocol, take care to ensure that the
<code>result_type</code> and
<code>result&lt;&gt;</code> members accurately
represent the return type of
<code>operator()</code> given a call expression.</p>
<p>Additionally, <code>boost::result_of</code>
provides a third mode of operation, which some users
may find convenient. When
<code>BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK</code>
is defined, <code>boost::result_of</code> behaves as
follows. If the function object has a member
type <code>result_type</code> or member
template <code>result&lt;&gt;</code>, then
<code>boost::result_of</code> will use the TR1
protocol. Otherwise,
<code>boost::result_of</code> will
use <code>decltype</code>. Using TR1 with
a <code>declytpe</code> fallback may workaround
certain problems at the cost of portability. For
example:
<ul>
<li>Deficient compiler: If your code
requires <code>boost::result_of</code> to work
with incomplete return types but your
compiler's <code>decltype</code> implementation
does not support incomplete return types, then you
can use the TR1 protocol as a workaround. Support
for incomplete return types was added late in the
C++11 standardization process
(see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf">N3276</a>)
and is not implemented by some compilers.</li>
<li>Deficient legacy code: If your existing TR1
function object advertises a different type than
the actual result type deduced
by <code>decltype</code>, then using TR1 with a
<code>decltype</code> fallback will allow you to
work with both your existing TR1 function objects
and new C++11 function object. This situation
could occur if your legacy function objects
misused the TR1 protocol. See the documentation on
known <a href="#result_of_tr1_diff">differences</a>
between <code>boost::result_of</code> and TR1.</li>
</ul>
<a name="BOOST_NO_RESULT_OF"></a>
<p>This implementation of <code>result_of</code> requires class template partial specialization, the ability to parse function types properly, and support for SFINAE. If <code>result_of</code> is not supported by your compiler, including the header <code>boost/utility/result_of.hpp</code> will define the macro <code>BOOST_NO_RESULT_OF</code>. Contributed by Doug Gregor.</p>
<p>This implementation of <code>result_of</code>
requires class template partial specialization, the
ability to parse function types properly, and support
for SFINAE. If <code>result_of</code> is not supported
by your compiler, including the header
<code>boost/utility/result_of.hpp</code> will
define the macro <code>BOOST_NO_RESULT_OF</code>.</p>
<p>For additional information
about <code>result_of</code>, see the C++ Library
Technical Report,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">N1836</a>,
or, for motivation and design rationale,
the <code>result_of</code> <a href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1454.html">proposal</a>.</p>
<a name="result_of_guidelines">
<h3>Usage guidelines for boost::result_of</h3>
</a>
<p>The following are general suggestions about when
and how to use <code>boost::result_of</code>.</p>
<ol>
<li> If you are targeting C++11 and are not concerned
about portability to non-compliant compilers or
previous versions of the standard, then use
<code>std::result_of</code>. If <code>std::result_of</code>
meets your needs, then there's no reason to stop using
it.</li>
<li> If you are targeting C++11 but may port your code
to legacy compilers at some time in the future, then
use <code>boost::result_of</code> with
<code>decltype</code>. When <code>decltype</code> is
used <code>boost::result_of</code>
and <code>std::result_of</code> are usually
interchangeable. See the documentation on
known <a href="#result_of_cxx11_diff">differences</a>
between boost::result_of and C++11 result_of.</li>
<li> If compiler portability is required,
use <code>boost::result_of</code> with the TR1 protocol.</li>
</ol>
<p>Regardless of how you
configure <code>boost::result_of</code>, it is
important to bear in mind that the return type of a
function may change depending on its arguments, and
additionally, the return type of a member function may
change depending on the cv-qualification of the
object. <code>boost::result_of</code> must be passed
the appropriately cv-qualified types in order to
deduce the corresponding return type. For example:
<blockquote>
<pre>struct functor {
int& operator()(int);
int const& operator()(int) const;
float& operator()(float&);
float const& operator()(float const&);
};
typedef boost::result_of&lt;
functor(int)
&gt;::type type1; // type1 is int &
typedef boost::result_of&lt;
const functor(int)
&gt;::type type2; // type2 is int const &
typedef boost::result_of&lt;
functor(float&)
&gt;::type type3; // type3 is float &
typedef boost::result_of&lt;
functor(float const&)
&gt;::type type4; // type4 is float const &</pre>
</blockquote>
<a name="result_of_tr1_protocol_guidelines">
<h3>Usage guidelines for the TR1 result_of protocol</h3>
</a>
<p>On compliant C++11
compilers, <code>boost::result_of</code> can
use <code>decltype</code> to deduce the type of any
call expression, including calls to function
objects. However, on pre-C++11 compilers or on
compilers without adequate decltype support,
additional scaffolding is needed from function
objects as described above. The following are
suggestions about how to use the TR1 protocol.</p>
<ul>
<li>When the return type does not depend on the
argument types or the cv-qualification of the
function object, simply
define <code>result_type</code>. There is no need
to use the <code>result</code> template unless the
return type varies.</li>
<li>Use the protocol specified type when defining
function prototypes. This can help ensure the
actual return type does not get out of sync with
the protocol specification. For example:
<blockquote>
<pre>struct functor {
typedef int result_type;
result_type operator()(int);
};</pre>
</blockquote> </li>
<li>Always specify the <code>result</code>
specialization near the corresponding
<code>operator()</code> overload. This can make it
easier to keep the specializations in sync with the
overloads. For example:
<blockquote>
<pre>struct functor {
template&lt;class&gt; struct result;
template&lt;class F&gt;
struct result&lt;F(int)&gt; {
typedef int& type;
};
result&lt;functor(int)&gt;::type operator()(int);
template&lt;class F&gt;
struct result&lt;const F(int)&gt; {
typedef int const& type;
};
result&lt;const functor(int)&gt;::type operator()(int) const;
};</pre>
</blockquote> </li>
<li>Use type transformations to simplify
the <code>result</code> template specialization. For
example, the following uses
<a href="../type_traits/doc/html/index.html">Boost.TypeTraits</a>
to specialize the <code>result</code> template for
a single <code>operator()</code> that can be called on
both a const and non-const function object with
either an lvalue or rvalue argument.
<blockquote>
<pre>struct functor {
template&lt;class&gt; struct result;
template&lt;class F, class T&gt;
struct result&lt;F(T)&gt;
: boost::remove_cv&lt;
typename boost::remove_reference&lt;T&gt;::type
&gt;
{};
template&lt;class T&gt;
T operator()(T const&amp; x) const;
};</pre>
</blockquote></li>
</ul>
<a name="result_of_tr1_diff">
<h3>Known differences between boost::result_of and TR1 result_of</h3>
</a>
When using <code>decltype</code>, <code>boost::result_of</code>
ignores the TR1 protocol and instead deduces the
return type of function objects directly
via <code>decltype</code>. In most situations, users
will not notice a difference, so long as they use the
protocol correctly. The following are situations in
which the type deduced
by <code>boost::result_of</code> is known to differ depending on
whether <code>decltype</code> or the TR1 protocol is
used.
<ul>
<li> TR1 protocol misusage
<p>When using the TR1
protocol, <code>boost::result_of</code> cannot
detect whether the actual type of a call to a
function object is the same as the type specified
by the protocol, which allows for the possibility
of inadvertent mismatches between the specified
type and the actual type. When
using <code>decltype</code>, these subtle bugs
may result in compilation errors. For example:</p>
<blockquote>
<pre>struct functor {
typedef short result_type;
int operator()(short);
};
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
BOOST_STATIC_ASSERT((
boost::is_same&lt;boost::result_of&lt;functor(short)&gt;::type, int&gt;::value
));
#else
BOOST_STATIC_ASSERT((
boost::is_same&lt;boost::result_of&lt;functor(short)&gt;::type, short&gt;::value
));
#endif</pre>
</blockquote>
<p>Note that the user can
force <code>boost::result_of</code> to use the TR1
protocol even on platforms that
support <code>decltype</code> by
defining <code>BOOST_RESULT_OF_USE_TR1</code>.</p></li>
<li> Nullary function objects
<p>When using the TR1 protocol, <code>boost::result_of</code>
cannot always deduce the type of calls to
nullary function objects, in which case the
type defaults to void. When using <code>decltype</code>,
<code>boost::result_of</code> always gives the actual type of the
call expression. For example:</p>
<blockquote>
<pre>struct functor {
template&lt;class&gt; struct result {
typedef int type;
};
int operator()();
};
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
BOOST_STATIC_ASSERT((
boost::is_same&lt;boost::result_of&lt;functor()&gt;::type, int&gt;::value
));
#else
BOOST_STATIC_ASSERT((
boost::is_same&lt;boost::result_of&lt;functor()&gt;::type, void&gt;::value
));
#endif</pre>
</blockquote>
<p>Note that there are some workarounds for the
nullary function problem. So long as the return
type does not vary,
<code>result_type</code> can always be used to
specify the return type regardless of arity. If the
return type does vary, then the user can
specialize <code>boost::result_of</code> itself for
nullary calls.</p></li>
<li> Non-class prvalues and cv-qualification
<p>When using the TR1
protocol, <code>boost::result_of</code> will
report the cv-qualified type specified
by <code>result_type</code> or
the <code>result</code> template regardless of
the actual cv-qualification of the call
expression. When using
<code>decltype</code>, <code>boost::result_of</code>
will report the actual type of the call expression,
which is not cv-qualified when the expression is a
non-class prvalue. For example:</p>
<blockquote>
<pre>struct functor {
template&lt;class&gt; struct result;
template&lt;class F, class T&gt; struct result&lt;F(const T)&gt; {
typedef const T type;
};
const short operator()(const short);
int const & operator()(int const &);
};
// Non-prvalue call expressions work the same with or without decltype.
BOOST_STATIC_ASSERT((
boost::is_same&lt;
boost::result_of&lt;functor(int const &)&gt;::type,
int const &
::value
));
// Non-class prvalue call expressions are not actually cv-qualified,
// but only the decltype-based result_of reports this accurately.
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
BOOST_STATIC_ASSERT((
boost::is_same&lt;
boost::result_of&lt;functor(const short)&gt;::type,
short
::value
));
#else
BOOST_STATIC_ASSERT((
boost::is_same&lt;
boost::result_of&lt;functor(const short)&gt;::type,
const short
::value
));
#endif</pre>
</blockquote></li>
</ul>
<a name="result_of_cxx11_diff">
<h3>Known differences between boost::result_of and C++11 result_of</h3>
</a>
<p>When using <code>decltype</code>, <code>boost::result_of</code>
implements most of the C++11 result_of
specification. One known exception is that
<code>boost::result_of</code> does not implement the
requirements regarding pointers to member data.</p>
<p>Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others</p>
<h2>Class templates for the Base-from-Member Idiom</h2>
<p>See <a href="base_from_member.html">separate documentation</a>.</p>

View File

@ -295,7 +295,7 @@ so for those compilers that need to have such a workaround, based on the
<br> operator T&amp;() { return x ; }
<br> T const &amp;data() const { return x ; }
<br> T&amp; data() { return x ; }
<br> void swap( value_initialized&lt;T&gt;&amp; );
<br> void swap( value_initialized&amp; );
<br>
<br> private :
<br> <i>unspecified</i> x ;
@ -313,6 +313,12 @@ so for those compilers that need to have such a workaround, based on the
<br> return x.data() ;
<br>}
<br>
<br>template&lt;class T&gt;
<br>void swap ( value_initialized&lt;T&gt;&amp; lhs, value_initialized&lt;T&gt;&amp; rhs )
<br>{
<br> lhs.swap(rhs) ;
<br>}
<br>
<br>} // namespace boost
<br></pre>
@ -385,7 +391,7 @@ the wrapped object is always performed with the <code>get()</code> idiom:</p>
<br> operator T&amp;();
<br> T const &amp;data() const;
<br> T&amp; data();
<br> void swap( value_initialized&lt;T&gt;&amp; );
<br> void swap( initialized&amp; );
<br>
<br> private :
<br> <i>unspecified</i> x ;
@ -397,6 +403,9 @@ the wrapped object is always performed with the <code>get()</code> idiom:</p>
<br>template&lt;class T&gt;
<br>T&amp; get ( initialized&lt;T&gt;&amp; x );
<br>
<br>template&lt;class T&gt;
<br>void swap ( initialized&lt;T&gt;&amp; lhs, initialized&lt;T&gt;&amp; rhs );
<br>
<br>} // namespace boost
<br></pre>

View File

@ -0,0 +1,144 @@
// Copyright 2010, Niels Dekker.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Test program for the boost::value_initialized<T> workaround.
//
// 17 June 2010 (Created) Niels Dekker
// Switch the workaround off, before inluding "value_init.hpp".
#define BOOST_DETAIL_VALUE_INIT_WORKAROUND 0
#include <boost/utility/value_init.hpp>
#include <iostream> // For cout.
#include <cstdlib> // For EXIT_SUCCESS and EXIT_FAILURE.
namespace
{
struct empty_struct
{
};
// A POD aggregate struct derived from an empty struct.
// Similar to struct Foo1 from Microsoft Visual C++ bug report 484295,
// "VC++ does not value-initialize members of derived classes without
// user-declared constructor", reported in 2009 by Sylvester Hesp:
// https://connect.microsoft.com/VisualStudio/feedback/details/484295
struct derived_struct: empty_struct
{
int data;
};
bool is_value_initialized(const derived_struct& arg)
{
return arg.data == 0;
}
class virtual_destructor_holder
{
public:
int i;
virtual ~virtual_destructor_holder()
{
}
};
bool is_value_initialized(const virtual_destructor_holder& arg)
{
return arg.i == 0;
}
// Equivalent to the Stats class from GCC Bug 33916,
// "Default constructor fails to initialize array members", reported in 2007 by
// Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916
// and fixed for GCC 4.2.4.
class private_int_array_pair
{
friend bool is_value_initialized(const private_int_array_pair& arg);
private:
int first[12];
int second[12];
};
bool is_value_initialized(const private_int_array_pair& arg)
{
for ( unsigned i = 0; i < 12; ++i)
{
if ( (arg.first[i] != 0) || (arg.second[i] != 0) )
{
return false;
}
}
return true;
}
template <typename T>
bool is_value_initialized(const T(& arg)[2])
{
return
is_value_initialized(arg[0]) &&
is_value_initialized(arg[1]);
}
template <typename T>
bool is_value_initialized(const boost::value_initialized<T>& arg)
{
return is_value_initialized(arg.data());
}
// Returns zero when the specified object is value-initializated, and one otherwise.
// Prints a message to standard output if the value-initialization has failed.
template <class T>
unsigned failed_to_value_initialized(const T& object, const char *const object_name)
{
if ( is_value_initialized(object) )
{
return 0u;
}
else
{
std::cout << "Note: Failed to value-initialize " << object_name << '.' << std::endl;
return 1u;
}
}
// A macro that passed both the name and the value of the specified object to
// the function above here.
#define FAILED_TO_VALUE_INITIALIZE(value) failed_to_value_initialized(value, #value)
// Equivalent to the dirty_stack() function from GCC Bug 33916,
// "Default constructor fails to initialize array members", reported in 2007 by
// Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916
void dirty_stack()
{
unsigned char array_on_stack[4096];
for (unsigned i = 0; i < sizeof(array_on_stack); ++i)
{
array_on_stack[i] = 0x11;
}
}
}
int main()
{
dirty_stack();
// TODO More types may be added later.
const unsigned num_failures =
FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<derived_struct>()) +
FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<virtual_destructor_holder[2]>()) +
FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<private_int_array_pair>());
#ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
// One or more failures are expected.
return num_failures > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
#else
// No failures are expected.
return num_failures == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
#endif
}