Compare commits

...

84 Commits

Author SHA1 Message Date
46d5bb0538 Create branches/filesystem-v3 for v2 removal
[SVN r77385]
2012-03-18 20:54:17 +00:00
5825b6c329 Fixed test indentation and updated docs.
[SVN r77080]
2012-02-20 20:17:07 +00:00
54c78121c2 Updated ScopeExit "world" tests making person a struct instead of a class.
Added a code comment to Utility/IdentityType tmp_assert test.

[SVN r77071]
2012-02-18 19:29:35 +00:00
2891cb52d6 Added Boost.Utility/IdentityType and Boost.Functional/OverloadedFunction to status/Jamfile.v2 list of regression tests.
Updated Boost.ScopeExit documentation.

[SVN r77059]
2012-02-17 21:02:00 +00:00
0db9276e8c Fixed (hopefully) conflict between boost::base_from_member's C++11 constructor template and the automatically defined non-template copy- and/or move-constructors.
[SVN r77046]
2012-02-17 01:55:33 +00:00
d6cb9a9176 Fixed a bug in BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST: a typo VOId -> VOID.
Fixed a bug in scope_exit.hpp: An extra trailing \ in a macro definition (compiled only when BOOST_NO_VARIADIC_MACROS is defined).
Renamed LocalFunction and ScopeExit tests and examples from _err to _error.
Updated LocalFunction docs.

[SVN r77042]
2012-02-16 18:24:34 +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
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
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
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
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
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
a4b8043e68 Fix some header links.
[SVN r64006]
2010-07-14 08:15:33 +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
a991936c96 Made memset call in value_init conditional, see #3869. Updated the section "compiler issues" of its documentation.
[SVN r62307]
2010-05-30 09:19:09 +00:00
6239e685a2 value_init_test now uses lightweight_test by Peter Dimov; see #4246. Fernando Cacciola mailed me he agreed as well.
[SVN r62158]
2010-05-22 22:05:54 +00:00
e601fcb9c9 Locally disabled a trivial MSVC warning in value_init.hpp (C4512, "assignment operator could not be generated")
[SVN r62030]
2010-05-16 11:08:00 +00:00
f29a5db08e Hopefully fixed value_initialized compile errors on clang and comeau (strict mode) reported by Christopher Jefferson, see #4213
[SVN r61947]
2010-05-13 14:36:06 +00:00
22743ee125 Added boost::initialized<T> as was agreed at http://lists.boost.org/Archives/boost/2010/04/164916.php -- see #3472
[SVN r61883]
2010-05-09 20:51:24 +00:00
e3c982287a add tr1_result_of that always behaves as TR1 specifies, fix Boost.TR1's result_of to use tr1_result_of
[SVN r61248]
2010-04-13 15:01:11 +00:00
82e1111bb8 Revert [60052], as it causes other libraries to break.
[SVN r61097]
2010-04-06 07:56:54 +00:00
9339b32178 Updated copyright notice.
[SVN r61075]
2010-04-05 19:08:01 +00:00
3770221507 Hopefully fixed #3984 (std::bitset constructor issue). Tested by Juergen Hunold on msvc-10.0, msvc-9.0, and gcc-4.4. See thread starting at http://lists.boost.org/Archives/boost/2010/03/162690.php
[SVN r60331]
2010-03-07 21:42:22 +00:00
e6cb3a77ee Fix a couple of comments.
[SVN r60294]
2010-03-07 13:11:10 +00:00
bbccfbbab4 Remove use of deprecated macro in result_of test.
[SVN r60293]
2010-03-07 13:10:54 +00:00
74a6a693d3 Remove use of deprecated config macro in result_of.
[SVN r60052]
2010-03-01 19:39:52 +00:00
bf713ad47a Revert unintentional reference to "noncopyable_adl_barrier" test that's not checked in.
[SVN r59332]
2010-01-28 14:41:16 +00:00
76b17c497b Support different MS calling conventions, thanks to Nicolas Lelong.
Closes #3833.


[SVN r59247]
2010-01-24 02:08:46 +00:00
3de5974419 Suppressing warnings. Please report any problems (may have broken something!)
[SVN r58072]
2009-12-01 02:16:50 +00:00
7eb1536590 Suppress/fix some msvc and gcc compiler warnings.
[SVN r57494]
2009-11-08 18:53:59 +00:00
9339431e03 rm cmake from trunk. I'm not entirely sure this is necessary to satisfy the inspect script, but I'm not taking any chances, and it is easy to put back
[SVN r56942]
2009-10-17 02:07:38 +00:00
f2349baf7d Updated value_init documentation, because the fix of #2548 was not yet included with Boost release 1.40.0.
[SVN r56544]
2009-10-03 09:18:26 +00:00
8745ca628a Updated revision date of Boost Swap documentation
[SVN r56108]
2009-09-08 17:07:13 +00:00
ba61e9d796 Mentioned swap.hpp header, as requested by Thorsten Ottosen <http://lists.boost.org/Archives/boost/2009/06/153477.php> and David Abrahams <http://lists.boost.org/Archives/boost/2009/09/156064.php>
[SVN r56107]
2009-09-08 16:54:54 +00:00
afe74fffbc Copyrights on CMakeLists.txt to keep them from clogging up the inspect
reports.  This is essentially the same commit as r55095 on the release
branch.



[SVN r55159]
2009-07-26 00:49:56 +00:00
09a0137016 Reverted value_init revision [54502], intel_9_value_init_conversion-operator.patch from ticket #2548, as it only increased the number of compile errors at the regression page, and Fernando Cacciola also suggested me to leave it broken (without the patch), for this specific (old) compiler version.
[SVN r54832]
2009-07-09 08:06:19 +00:00
a1d3ec6c53 Documentation update
[SVN r54828]
2009-07-09 03:51:30 +00:00
5be3004e6c Added commonly used error_info typedefs.
Added boost/exception/all.hpp.
Removed tabs from source files.

[SVN r54825]
2009-07-08 23:44:28 +00:00
d387905150 Updated documentation of value_initialized, according to a remark by Daniel James at ticket #2548
[SVN r54503]
2009-06-29 18:04:24 +00:00
b514e40733 Worked around Intel 9 specific ambiguity w.r.t. value_initialized conversion operators, by applying intel_9_value_init_conversion-operator.patch, as discussed w/ Daniel James at ticket #2548
[SVN r54502]
2009-06-29 17:53:33 +00:00
b02677375f Fixed most tab and min/max issues from trunk inspection report
[SVN r53141]
2009-05-20 19:19:00 +00:00
61a6015b5a Replace aFactoty with aFactory. Fixes #3019
[SVN r53060]
2009-05-17 00:06:34 +00:00
682032a340 Use a local copy of the valid HTML 4.01 icon.
[SVN r53048]
2009-05-16 14:23:59 +00:00
67afd7e315 eliminate noisy warning on msvc, fixes #2993
[SVN r52837]
2009-05-07 17:47:08 +00:00
75cf20cace primary operand type must be class type, see ticket #2938
[SVN r52463]
2009-04-18 09:06:31 +00:00
91385ac627 Another try at the Sun workaround.
[SVN r52010]
2009-03-27 12:50:09 +00:00
61e9b93f7c Try the Sun workaround with int instead of size_t.
[SVN r51986]
2009-03-26 13:05:05 +00:00
d97b303777 Try to fix array addressof failures on Sun C++.
[SVN r51977]
2009-03-26 00:06:47 +00:00
3900e8ece4 Disable new addressof code for all Borland versions. Refs #2878.
[SVN r51891]
2009-03-21 20:20:37 +00:00
e27fc4a853 Attempt to fix addressof in trunk to handle classes with conversion operators. Refs #2878.
[SVN r51872]
2009-03-20 17:14:00 +00:00
f7aa9a8935 Refs #2128 (fixed in trunk.)
[SVN r51512]
2009-03-01 17:04:14 +00:00
0af1959b30 Updated value_initialized documentation and test following changeset [51355].
[SVN r51356]
2009-02-20 20:35:34 +00:00
5f0cf4f5de Fixed const issue of value_initialized according to ticket #2548. See also http://lists.boost.org/Archives/boost/2009/02/148489.php
[SVN r51355]
2009-02-20 20:28:54 +00:00
0282c8a141 added #error in headers incompatible with BOOST_NO_EXCEPTIONS
[SVN r50887]
2009-01-30 00:06:01 +00:00
6725719bd9 This html was outdated; changed to forward to throw_exception.html documentation from Boost Exception
[SVN r50879]
2009-01-29 19:13:08 +00:00
97e11b024e [utility/swap] Distinguished between testing array-of-array-of-class and array-of-array-of-int, as the latter appears to succeed on CodeGear 6.10 while the former does not.
[SVN r49954]
2008-11-27 11:14:52 +00:00
118e473a3d [utility/swap] Added comment to various array swapping tests, added member typedef to swap_test_template, to make the test more realistic.
[SVN r49953]
2008-11-27 11:08:05 +00:00
d4b6193f94 Replaced swap/test/swap_arrays by more specific tests: array_of_array, array_of_class, and array_of_int.
[SVN r49916]
2008-11-24 17:41:15 +00:00
d420c98a53 Added array_of_template test, testing the boost::swap utility on an array of objects of a template class.
[SVN r49862]
2008-11-21 21:28:47 +00:00
d153ab4daa Fix a typo.
[SVN r49811]
2008-11-16 23:10:00 +00:00
561f83b991 Updated swap.html because LWG issue 809 is now accepted as a defect. Fixed some HTML formatting.
[SVN r49771]
2008-11-15 15:07:42 +00:00
57124703f9 Fixing include path to compile with modularized source tree.
[SVN r49685]
2008-11-11 17:22:34 +00:00
53f6d10652 Updating CMake files to latest trunk. Added dependency information for regression tests and a few new macros for internal use.
[SVN r49627]
2008-11-07 17:02:56 +00:00
ebe853ff2f Continuing merge of CMake build system files into trunk with the encouragement of Doug Gregor
[SVN r49510]
2008-11-01 13:15:41 +00:00
487a5c1ea5 Swap documentation: fixed a misspelling of the name of Steven Watanabe.
[SVN r49416]
2008-10-21 09:55:54 +00:00
c4338b1ce8 Clean up some link errors.
[SVN r48987]
2008-09-28 12:21:39 +00:00
70 changed files with 2883 additions and 417 deletions

View File

@ -85,7 +85,7 @@
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional"
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised

View File

@ -509,7 +509,7 @@ Returns the largest size that this Collection can ever have. <A href="#8">[8]</A
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional"
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised

View File

@ -160,7 +160,7 @@ t.~T()
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional"
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised

View File

@ -185,7 +185,7 @@
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional"
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised

View File

@ -70,7 +70,7 @@
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional"
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised

76
addressof_fn_test.cpp Normal file
View File

@ -0,0 +1,76 @@
#include <boost/config.hpp>
#if defined(BOOST_MSVC)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#endif
// addressof_fn_test.cpp: addressof( f )
//
// Copyright (c) 2008, 2009 Peter Dimov
//
// 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
#include <boost/utility/addressof.hpp>
#include <boost/detail/lightweight_test.hpp>
void f0()
{
}
void f1(int)
{
}
void f2(int, int)
{
}
void f3(int, int, int)
{
}
void f4(int, int, int, int)
{
}
void f5(int, int, int, int, int)
{
}
void f6(int, int, int, int, int, int)
{
}
void f7(int, int, int, int, int, int, int)
{
}
void f8(int, int, int, int, int, int, int, int)
{
}
void f9(int, int, int, int, int, int, int, int, int)
{
}
int main()
{
BOOST_TEST( boost::addressof( f0 ) == &f0 );
BOOST_TEST( boost::addressof( f1 ) == &f1 );
BOOST_TEST( boost::addressof( f2 ) == &f2 );
BOOST_TEST( boost::addressof( f3 ) == &f3 );
BOOST_TEST( boost::addressof( f4 ) == &f4 );
BOOST_TEST( boost::addressof( f5 ) == &f5 );
BOOST_TEST( boost::addressof( f6 ) == &f6 );
BOOST_TEST( boost::addressof( f7 ) == &f7 );
BOOST_TEST( boost::addressof( f8 ) == &f8 );
BOOST_TEST( boost::addressof( f9 ) == &f9 );
return boost::report_errors();
}

95
addressof_test2.cpp Normal file
View File

@ -0,0 +1,95 @@
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
// Douglas Gregor (gregod@cs.rpi.edu)
//
// Copyright 2009 Peter Dimov
//
// 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 <boost/utility/addressof.hpp>
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
#pragma warning(push, 3)
#endif
#include <iostream>
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
#pragma warning(pop)
#endif
#include <boost/detail/lightweight_test.hpp>
template<class T> void scalar_test( T * = 0 )
{
T* px = new T();
T& x = *px;
BOOST_TEST( boost::addressof(x) == px );
const T& cx = *px;
const T* pcx = boost::addressof(cx);
BOOST_TEST( pcx == px );
volatile T& vx = *px;
volatile T* pvx = boost::addressof(vx);
BOOST_TEST( pvx == px );
const volatile T& cvx = *px;
const volatile T* pcvx = boost::addressof(cvx);
BOOST_TEST( pcvx == px );
delete px;
}
template<class T> void array_test( T * = 0 )
{
T nrg[3] = {1,2,3};
T (*pnrg)[3] = &nrg;
BOOST_TEST( boost::addressof(nrg) == pnrg );
T const cnrg[3] = {1,2,3};
T const (*pcnrg)[3] = &cnrg;
BOOST_TEST( boost::addressof(cnrg) == pcnrg );
}
class convertible {
public:
convertible( int = 0 )
{
}
template<class U> operator U () const
{
return U();
}
};
class convertible2 {
public:
convertible2( int = 0 )
{
}
operator convertible2* () const
{
return 0;
}
};
int main()
{
scalar_test<convertible>();
scalar_test<convertible2>();
array_test<convertible>();
array_test<convertible2>();
return boost::report_errors();
}

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

@ -281,7 +281,7 @@ object_id_compare::operator ()
}
else
{
return a.second->before( *b.second );
return a.second->before( *b.second ) != 0;
}
}
}

View File

@ -11,6 +11,10 @@
#include <algorithm>
#include <cstddef>
#ifdef BOOST_MSVC
#pragma warning(disable:4996) // warning C4996: 'std::equal': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
#endif
/*
Note: This file tests every single valid bit-grouping on its own, and some
random combinations of bit-groupings.

View File

@ -21,6 +21,10 @@
#include <libs/type_traits/test/test.hpp>
#include <libs/type_traits/test/check_type.hpp>
#ifdef BOOST_MSVC
#pragma warning(disable:4181) // : warning C4181: qualifier applied to reference type; ignored
#endif
// a way prevent warnings for unused variables
template<class T> inline void unused_variable(const T&) {}
@ -52,7 +56,8 @@ struct contained
const_reference const_get()const { return v_; }
// pass value:
void call(param_type){}
private:
contained& operator=(const contained&);
};
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
@ -77,6 +82,8 @@ struct contained<T[N]>
reference get() { return v_; }
const_reference const_get()const { return v_; }
void call(param_type){}
private:
contained& operator=(const contained&);
};
#endif
@ -197,14 +204,16 @@ struct comparible_UDT
bool operator == (const comparible_UDT& v){ return v.i_ == i_; }
};
int main(int argc, char *argv[ ])
int main()
{
call_traits_checker<comparible_UDT> c1;
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)
@ -285,7 +294,11 @@ int main(int argc, char *argv[ ])
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;
}

68
doc/Jamfile.v2 Normal file
View File

@ -0,0 +1,68 @@
# 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
:
# 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
;

104
doc/declval.qbk Normal file
View File

@ -0,0 +1,104 @@
[/
/ Copyright (c) 2008 Howard Hinnant
/ Copyright (c) 2008 Beman Dawes
/ Copyright (c) 2009-20010 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 [Dawes, Beman]]
[authors [Botet Escriba, Vicente J.]]
[copyright 2008 Howard Hinnant]
[copyright 2008 Beman Dawes]
[copyright 2009-2010 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]

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

@ -0,0 +1,163 @@
<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.75.2">
<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">Beman</span> <span class="surname">Dawes</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; 2008 Beman Dawes</p></div>
<div><p class="copyright">Copyright &#169; 2009, 2010 Vicente J. Botet Escriba</p></div>
<div><div class="legalnotice">
<a name="id3354293"></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>
</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="comment">//noexcept; // 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>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><p><small>Last revised: April 06, 2011 at 20:06:10 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td>
</tr></table>
<hr>
<div class="spirit-nav"></div>
</body>
</html>

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

@ -146,7 +146,7 @@ int main()
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional"
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised

View File

@ -0,0 +1,31 @@
# 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{1}=\"\\xmlonly<link linkend='boost_utility_identitytype.\\1'>\\1</link>\\endxmlonly\" RefSectId{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=../../../../..
;

View File

@ -0,0 +1,237 @@
<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 type expressions within round parenthesis so they
can be passed to macros even when they contain commas.
</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 parameters <code class="computeroutput"><span class="special">()</span></code>. Angular
<code class="computeroutput"><span class="special">&lt;&gt;</span></code> or squared <code class="computeroutput"><span class="special">[]</span></code> parenthesis are not used by the preprocessor
when parsing the 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 some cases
a <code class="computeroutput"><span class="keyword">typedef</span></code> can be 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 not possible or desired (e.g., see the function template <code class="computeroutput"><span class="identifier">f</span></code> in the section below), the 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>
This 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 (because 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>
</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 <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 in <code class="computeroutput"><span class="identifier">f</span><span class="special">(</span><span class="identifier">a</span><span class="special">)</span></code>. <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 worked around 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/tmp_assert.cpp" target="_top"><code class="literal">tmp_assert.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 in the definition of 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 user macro definition, the call of the user macro will only
have to specify the extra parenthesis (see also <a href="../../test/tmp_assert.cpp" target="_top"><code class="literal">tmp_assert.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="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 user 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>
within the user macro definition might provide the best syntax for the user.
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.
</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="id512092"></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 require variadic macros).</p><p>This macro must be prefixed by <code class="computeroutput">typename</code> when used within templates. However, 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 an abstract types requires to add and remove a reference to the 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. This code is for explanatory purposes
only.
</p></div></div></div></body></html>

View File

@ -0,0 +1,162 @@
[/ 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 type expressions within round parenthesis so they can be passed to macros even when they contain commas.
[import ../test/var_error.cpp]
[import ../test/var.cpp]
[import ../test/template.cpp]
[import ../test/tmp_assert.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 parameters `()`.
Angular `<>` or squared `[]` parenthesis are not used by the preprocessor when parsing the 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 some cases a `typedef` can be used to specify the type expression with the commas outside the macro (see also [@../../test/var.cpp =var.cpp=]):
[var_typedef]
When this is not possible or desired (e.g., see the function template `f` in the section below), the 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]
This 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 (because 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).
]
[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 `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 in `f(a)`.
[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 worked around 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/tmp_assert.cpp =tmp_assert.cpp=]):
[tmp_assert_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 in the definition of a user-defined macro (as shown below).
When [macroref BOOST_IDENTITY_TYPE] is used in the user macro definition, the call of the user macro will only have to specify the extra parenthesis (see also [@../../test/tmp_assert.cpp =tmp_assert.cpp=]):
[tmp_assert_alternative]
However, note that the user will /always/ have to specify the extra parenthesis even when the macro parameters contain no comma:
[tmp_assert_alternative_always]
In some cases, using [macroref BOOST_IDENTITY_TYPE] within the user macro definition might provide the best syntax for the user.
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.
[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.
This 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,14 @@
# 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 tmp_assert.cpp ;

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,53 @@
// 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 <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <map>
//[tmp_assert_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
);
//]
//[tmp_assert_alternative
#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)
// 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>)));
//]
//[tmp_assert_alternative_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,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

@ -99,7 +99,7 @@ directly to the container:</p>
<H2><A NAME="framework"></A>Framework</H2>
<p>
This library proposes a framework to allow some containers to directly contruct contained objects in-place without requiring
the entire set of constructor overloads ftom the contained type. It also allows the container to remove the CopyConstuctible
the entire set of constructor overloads from the contained type. It also allows the container to remove the CopyConstuctible
requirement from the contained type since objects can be directly constructed in-place without need of a copy.<br>
The only requirement on the container is that it must provide proper storage (that is, correctly aligned and sized).
Naturally, the container will typically support uninitialized storage to avoid the in-place construction to override
@ -117,7 +117,7 @@ The following simplified example shows the basic idea. A complete example follow
<pre>struct C
{
template&lt;class InPlaceFactory&gt;
C ( InPlaceFactory const& aFactoty )
C ( InPlaceFactory const& aFactory )
:
contained_ ( uninitialized_storage() )
{
@ -293,4 +293,4 @@ the latest version of this file can be found at <A
HREF="http://www.boost.org">www.boost.org</A>, and the boost
<A HREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P>
</BODY>
</HTML>
</HTML>

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)
@ -25,18 +38,91 @@
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) ((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/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) ((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/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
{
inline void assertion_failed_msg(char 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) ((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

@ -6,12 +6,6 @@
#ifndef UUID_1D94A7C6054E11DB9804B622A1EF5492
#define UUID_1D94A7C6054E11DB9804B622A1EF5492
#include <boost/exception/diagnostic_information.hpp>
#include <boost/exception/error_info.hpp>
#include <boost/exception/exception.hpp>
#include <boost/exception/get_error_info.hpp>
#include <boost/exception/info.hpp>
#include <boost/exception/info_tuple.hpp>
#include <boost/exception_ptr.hpp>
#error The header <boost/exception.hpp> has been deprecated. Please #include <boost/exception/all.hpp> instead.
#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

@ -179,6 +179,11 @@ unwrap_ref(T& t)
return t;
}
template<class T> inline T* get_pointer( reference_wrapper<T> const & r )
{
return r.get_pointer();
}
} // namespace boost
#endif // #ifndef BOOST_REF_HPP_INCLUDED

View File

@ -7,6 +7,6 @@
#ifndef BOOST_SWAP_HPP
#define BOOST_SWAP_HPP
#include "./utility/swap.hpp"
#include "boost/utility/swap.hpp"
#endif

View File

@ -21,6 +21,17 @@ namespace boost
namespace detail
{
template<class T> struct addr_impl_ref
{
T & v_;
inline addr_impl_ref( T & v ): v_( v ) {}
inline operator T& () const { return v_; }
private:
addr_impl_ref & operator=(const addr_impl_ref &);
};
template<class T> struct addressof_impl
{
static inline T * f( T & v, long )
@ -39,12 +50,40 @@ template<class T> struct addressof_impl
template<class T> T * addressof( T & v )
{
#if defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) )
return boost::detail::addressof_impl<T>::f( v, 0 );
#else
return boost::detail::addressof_impl<T>::f( boost::detail::addr_impl_ref<T>( v ), 0 );
#endif
}
#if defined( __SUNPRO_CC ) && BOOST_WORKAROUND( __SUNPRO_CC, BOOST_TESTED_AT( 0x590 ) )
namespace detail
{
template<class T> struct addressof_addp
{
typedef T * type;
};
} // namespace detail
template< class T, std::size_t N >
typename detail::addressof_addp< T[N] >::type addressof( T (&t)[N] )
{
return &t;
}
#endif
// Borland doesn't like casting an array reference to a char reference
// but these overloads work around the problem.
# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
#if defined( __BORLANDC__ ) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
template<typename T,std::size_t N>
T (*addressof(T (&t)[N]))[N]
{
@ -56,7 +95,7 @@ const T (*addressof(const T (&t)[N]))[N]
{
return reinterpret_cast<const T(*)[N]>(&t);
}
# endif
#endif
} // namespace boost

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_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,24 @@ class base_from_member
protected:
MemberType member;
#if !defined(BOOST_NO_RVALUE_REFERENCES) && \
!defined(BOOST_NO_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS)
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 @@
// common_type.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_TYPE_TRAITS_EXT_DECLVAL__HPP
#define BOOST_TYPE_TRAITS_EXT_DECLVAL__HPP
#include <boost/config.hpp>
//----------------------------------------------------------------------------//
#include <boost/type_traits/add_rvalue_reference.hpp>
//----------------------------------------------------------------------------//
// //
// C++03 implementation of //
// Written by Vicente J. Botet Escriba //
//~ 20.3.4 Function template declval [declval]
//~ 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 participats in overloading if the type From can be
//~ explicitly converted to type To. For another example see class template common_type (20.7.6.6). <20>end
//~ example ]
// //
//----------------------------------------------------------------------------//
namespace boost {
template <typename T>
typename add_rvalue_reference<T>::type declval(); //noexcept; // as unevaluated operand
} // namespace boost
#endif // BOOST_TYPE_TRAITS_EXT_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

@ -10,47 +10,6 @@
# error Boost result_of - do not include this file!
#endif
#if defined(BOOST_HAS_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))>
: mpl::if_<
mpl::or_< is_pointer<F>, is_member_function_pointer<F> >
, detail::result_of_impl<
typename remove_cv<F>::type,
typename remove_cv<F>::type(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false
>
, detail::result_of_decltype_impl<
F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))
>
>::type
{};
namespace detail {
# define BOOST_RESULT_OF_STATIC_MEMBERS(z, n, _) \
static T ## n t ## n; \
/**/
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
class result_of_decltype_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;
};
} // namespace detail
#else // defined(BOOST_HAS_DECLTYPE)
// CWPro8 requires an argument in a function type specialization
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3002)) && BOOST_PP_ITERATION() == 0
# define BOOST_RESULT_OF_ARGS void
@ -61,22 +20,64 @@ public:
#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)>
struct result_of<F(BOOST_RESULT_OF_ARGS)>
struct tr1_result_of<F(BOOST_RESULT_OF_ARGS)>
: mpl::if_<
mpl::or_< is_pointer<F>, is_member_function_pointer<F> >
, boost::detail::result_of_impl<
, boost::detail::tr1_result_of_impl<
typename remove_cv<F>::type,
typename remove_cv<F>::type(BOOST_RESULT_OF_ARGS),
(boost::detail::has_result_type<F>::value)>
, boost::detail::result_of_impl<
, boost::detail::tr1_result_of_impl<
F,
F(BOOST_RESULT_OF_ARGS),
(boost::detail::has_result_type<F>::value)> >::type { };
#endif
#undef BOOST_RESULT_OF_ARGS
#if !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE)
#endif // defined(BOOST_HAS_DECLTYPE)
// Uses declval following N3225 20.7.7.6 when F is not a pointer.
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))>
: mpl::if_<
mpl::or_< is_pointer<F>, is_member_function_pointer<F> >
, detail::tr1_result_of_impl<
typename remove_cv<F>::type,
typename remove_cv<F>::type(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false
>
, detail::cpp0x_result_of_impl<
F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))
>
>::type
{};
namespace detail {
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
{
typedef decltype(
boost::declval<F>()(
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), declval<T, >() BOOST_PP_INTERCEPT)
)
) type;
};
} // namespace detail
#else // defined(BOOST_NO_DECLTYPE)
#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)>
struct result_of<F(BOOST_RESULT_OF_ARGS)>
: tr1_result_of<F(BOOST_RESULT_OF_ARGS)> { };
#endif
#endif // defined(BOOST_NO_DECLTYPE)
#undef BOOST_RESULT_OF_ARGS
#if BOOST_PP_ITERATION() >= 1
@ -84,14 +85,14 @@ namespace detail {
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of_impl<R (*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
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)>
struct result_of_impl<R (&)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
struct tr1_result_of_impl<R (&)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
{
typedef R type;
};
@ -99,7 +100,7 @@ struct result_of_impl<R (&)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs
#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)>
struct result_of_impl<R (T0::*)
struct tr1_result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T)),
FArgs, false>
{
@ -108,7 +109,7 @@ struct result_of_impl<R (T0::*)
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of_impl<R (T0::*)
struct tr1_result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
const,
FArgs, false>
@ -118,7 +119,7 @@ struct result_of_impl<R (T0::*)
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of_impl<R (T0::*)
struct tr1_result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
volatile,
FArgs, false>
@ -128,7 +129,7 @@ struct result_of_impl<R (T0::*)
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of_impl<R (T0::*)
struct tr1_result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
const volatile,
FArgs, false>

View File

@ -0,0 +1,45 @@
// 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 require variadic macros).
This macro must be prefixed by <c>typename</c> when used within templates.
However, 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 an abstract types requires to
add and remove a reference to the 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

@ -13,7 +13,9 @@
#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_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>
@ -22,22 +24,24 @@
#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/utility/declval.hpp>
#ifndef BOOST_RESULT_OF_NUM_ARGS
# define BOOST_RESULT_OF_NUM_ARGS 10
# define BOOST_RESULT_OF_NUM_ARGS 16
#endif
namespace boost {
template<typename F> struct result_of;
template<typename F> struct tr1_result_of; // a TR1-style implementation of result_of
#if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace detail {
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
template<typename F, typename FArgs, bool HasResultType> struct result_of_impl;
template<typename F> struct result_of_decltype_impl;
template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_impl;
template<typename F> struct cpp0x_result_of_impl;
template<typename F>
struct result_of_void_impl
@ -60,10 +64,10 @@ struct result_of_void_impl<R (&)(void)>
// Determine the return type of a function pointer or pointer to member.
template<typename F, typename FArgs>
struct result_of_pointer
: result_of_impl<typename remove_cv<F>::type, FArgs, false> { };
: tr1_result_of_impl<typename remove_cv<F>::type, FArgs, false> { };
template<typename F, typename FArgs>
struct result_of_impl<F, FArgs, true>
struct tr1_result_of_impl<F, FArgs, true>
{
typedef typename F::result_type type;
};
@ -79,10 +83,10 @@ struct result_of_nested_result : F::template result<FArgs>
{};
template<typename F, typename FArgs>
struct result_of_impl<F, FArgs, false>
struct tr1_result_of_impl<F, FArgs, false>
: mpl::if_<is_function_with_no_args<FArgs>,
result_of_void_impl<F>,
result_of_nested_result<F, FArgs> >::type
result_of_void_impl<F>,
result_of_nested_result<F, FArgs> >::type
{};
} // end namespace detail

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

@ -8,6 +8,9 @@
// 24 Dec 2007 (Refactored and worked around various compiler bugs) Fernando Cacciola, Niels Dekker
// 23 May 2008 (Fixed operator= const issue, added initialized_value) Niels Dekker, Fernando Cacciola
// 21 Ago 2008 (Added swap) Niels Dekker, Fernando Cacciola
// 20 Feb 2009 (Fixed logical const-ness issues) Niels Dekker, Fernando Cacciola
// 03 Apr 2010 (Added initialized<T>, suggested by Jeffrey Hellrung, fixing #3472) Niels Dekker
// 30 May 2010 (Made memset call conditional, fixing #3869) Niels Dekker
//
#ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
#define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
@ -19,6 +22,7 @@
// contains. More details on these issues are at libs/utility/value_init.htm
#include <boost/aligned_storage.hpp>
#include <boost/config.hpp> // For BOOST_NO_COMPLETE_VALUE_INITIALIZATION.
#include <boost/detail/workaround.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/cv_traits.hpp>
@ -27,10 +31,39 @@
#include <cstring>
#include <new>
#ifdef BOOST_MSVC
#pragma warning(push)
#if _MSC_VER >= 1310
// It is safe to ignore the following warning from MSVC 7.1 or higher:
// "warning C4351: new behavior: elements of array will be default initialized"
#pragma warning(disable: 4351)
// It is safe to ignore the following MSVC warning, which may pop up when T is
// a const type: "warning C4512: assignment operator could not be generated".
#pragma warning(disable: 4512)
#endif
#endif
#ifdef BOOST_NO_COMPLETE_VALUE_INITIALIZATION
// Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
// suggests that a workaround should be applied, because of compiler issues
// regarding value-initialization.
#define BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
#endif
// Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND
// switches the value-initialization workaround either on or off.
#ifndef BOOST_DETAIL_VALUE_INIT_WORKAROUND
#ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
#define BOOST_DETAIL_VALUE_INIT_WORKAROUND 1
#else
#define BOOST_DETAIL_VALUE_INIT_WORKAROUND 0
#endif
#endif
namespace boost {
template<class T>
class value_initialized
class initialized
{
private :
struct wrapper
@ -39,6 +72,18 @@ class value_initialized
typename
#endif
remove_const<T>::type data;
wrapper()
:
data()
{
}
wrapper(T const & arg)
:
data(arg)
{
}
};
mutable
@ -54,30 +99,25 @@ class value_initialized
public :
value_initialized()
initialized()
{
#if BOOST_DETAIL_VALUE_INIT_WORKAROUND
std::memset(&x, 0, sizeof(x));
#ifdef BOOST_MSVC
#pragma warning(push)
#if _MSC_VER >= 1310
// When using MSVC 7.1 or higher, the following placement new expression may trigger warning C4345:
// "behavior change: an object of POD type constructed with an initializer of the form ()
// will be default-initialized". It is safe to ignore this warning when using value_initialized.
#pragma warning(disable: 4345)
#endif
#endif
new (wrapper_address()) wrapper();
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
value_initialized(value_initialized const & arg)
initialized(initialized const & arg)
{
new (wrapper_address()) wrapper( static_cast<wrapper const &>(*(arg.wrapper_address())));
}
value_initialized & operator=(value_initialized const & arg)
explicit initialized(T const & arg)
{
new (wrapper_address()) wrapper(arg);
}
initialized & operator=(initialized const & arg)
{
// Assignment is only allowed when T is non-const.
BOOST_STATIC_ASSERT( ! is_const<T>::value );
@ -85,25 +125,96 @@ class value_initialized
return *this;
}
~value_initialized()
~initialized()
{
wrapper_address()->wrapper::~wrapper();
}
T& data() const
T const & data() const
{
return wrapper_address()->data;
}
void swap(value_initialized & arg)
T& data()
{
return wrapper_address()->data;
}
void swap(initialized & arg)
{
::boost::swap( this->data(), arg.data() );
}
operator T&() const { return this->data(); }
operator T const &() const
{
return wrapper_address()->data;
}
operator T&()
{
return wrapper_address()->data;
}
} ;
template<class T>
T const& get ( initialized<T> const& x )
{
return x.data() ;
}
template<class T>
T& get ( initialized<T>& x )
{
return x.data() ;
}
template<class T>
void swap ( initialized<T> & lhs, initialized<T> & rhs )
{
lhs.swap(rhs) ;
}
template<class T>
class value_initialized
{
private :
// initialized<T> does value-initialization by default.
initialized<T> m_data;
public :
value_initialized()
:
m_data()
{ }
T const & data() const
{
return m_data.data();
}
T& data()
{
return m_data.data();
}
void swap(value_initialized & arg)
{
m_data.swap(arg.m_data);
}
operator T const &() const
{
return m_data;
}
operator T&()
{
return m_data;
}
} ;
template<class T>
@ -111,6 +222,7 @@ T const& get ( value_initialized<T> const& x )
{
return x.data() ;
}
template<class T>
T& get ( value_initialized<T>& x )
{
@ -130,7 +242,7 @@ class initialized_value_t
template <class T> operator T() const
{
return get( value_initialized<T>() );
return initialized<T>().data();
}
};
@ -139,5 +251,8 @@ initialized_value_t const initialized_value = {} ;
} // namespace boost
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
#endif

View File

@ -14,20 +14,28 @@
<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="enable_if.html">enable_if</a><br>
<a href="doc/html/declval.html">declval</a><br>
<a href="enable_if.html">enable_if</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="value_init.htm">value_init</a>
</p>
</blockquote>
<hr>
<p>&copy; Copyright Beman Dawes, 2001</p>

116
initialized_test.cpp Normal file
View File

@ -0,0 +1,116 @@
// 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 boost::initialized<T>.
//
// 2 May 2010 (Created) Niels Dekker
#include <boost/utility/value_init.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <string>
namespace
{
// Typical use case for boost::initialized<T>: A generic class that
// holds a value of type T, which must be initialized by either
// value-initialization or direct-initialization.
template <class T> class key_value_pair
{
std::string m_key;
boost::initialized<T> m_value;
public:
// Value-initializes the object held by m_value.
key_value_pair() { }
// Value-initializes the object held by m_value.
explicit key_value_pair(const std::string& key)
:
m_key(key)
{
}
// Direct-initializes the object held by m_value.
key_value_pair(const std::string& key, const T& value)
:
m_key(key), m_value(value)
{
}
const T& get_value() const
{
return m_value;
}
};
// Tells whether the argument is value-initialized.
bool is_value_initialized(const int& arg)
{
return arg == 0;
}
// Tells whether the argument is value-initialized.
bool is_value_initialized(const std::string& arg)
{
return arg.empty();
}
struct foo
{
int data;
};
bool operator==(const foo& lhs, const foo& rhs)
{
return lhs.data == rhs.data;
}
// Tells whether the argument is value-initialized.
bool is_value_initialized(const foo& arg)
{
return arg.data == 0;
}
template <class T>
void test_key_value_pair(const T& magic_value)
{
// The value component of a default key_value_pair must be value-initialized.
key_value_pair<T> default_key_value_pair;
BOOST_TEST( is_value_initialized(default_key_value_pair.get_value() ) );
// The value component of a key_value_pair that only has its key explicitly specified
// must also be value-initialized.
BOOST_TEST( is_value_initialized(key_value_pair<T>("key").get_value()) );
// However, the value component of the following key_value_pair must be
// "magic_value", as it must be direct-initialized.
BOOST_TEST( key_value_pair<T>("key", magic_value).get_value() == magic_value );
}
}
// Tests boost::initialize for a fundamental type, a type with a
// user-defined constructor, and a user-defined type without
// a user-defined constructor.
int main()
{
const int magic_number = 42;
test_key_value_pair(magic_number);
const std::string magic_string = "magic value";
test_key_value_pair(magic_string);
const foo magic_foo = { 42 };
test_key_value_pair(magic_foo);
return boost::report_errors();
}

View File

@ -0,0 +1,33 @@
// 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 boost::initialized<T>. Must fail to compile.
//
// Initial: 2 May 2010
#include <boost/utility/value_init.hpp>
namespace
{
void direct_initialize_from_int()
{
// Okay: initialized<T> supports direct-initialization from T.
boost::initialized<int> direct_initialized_int(1);
}
void copy_initialize_from_int()
{
// The following line should not compile, because initialized<T>
// was not intended to supports copy-initialization from T.
boost::initialized<int> copy_initialized_int = 1;
}
}
int main()
{
// This should fail to compile, so there is no need to call any function.
return 0;
}

View File

@ -0,0 +1,37 @@
// 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 boost::initialized<T>. Must fail to compile.
//
// Initial: 2 May 2010
#include <boost/utility/value_init.hpp>
namespace
{
void from_value_initialized_to_initialized()
{
boost::value_initialized<int> value_initialized_int;
// Okay: initialized<T> can be initialized by value_initialized<T>.
boost::initialized<int> initialized_int(value_initialized_int);
}
void from_initialized_to_value_initialized()
{
boost::initialized<int> initialized_int(13);
// The following line should not compile, because initialized<T>
// should not be convertible to value_initialized<T>.
boost::value_initialized<int> value_initialized_int(initialized_int);
}
}
int main()
{
// This should fail to compile, so there is no need to call any function.
return 0;
}

View File

@ -132,18 +132,18 @@
class MyInt
: boost::operators&lt;MyInt&gt;
{
bool operator&lt;(const MyInt&amp; x) const;
bool operator&lt;(const MyInt&amp; x) const;
bool operator==(const MyInt&amp; x) const;
MyInt&amp; operator+=(const MyInt&amp; x);
MyInt&amp; operator-=(const MyInt&amp; x);
MyInt&amp; operator*=(const MyInt&amp; x);
MyInt&amp; operator/=(const MyInt&amp; x);
MyInt&amp; operator%=(const MyInt&amp; x);
MyInt&amp; operator|=(const MyInt&amp; x);
MyInt&amp; operator&amp;=(const MyInt&amp; x);
MyInt&amp; operator^=(const MyInt&amp; x);
MyInt&amp; operator++();
MyInt&amp; operator--();
MyInt&amp; operator+=(const MyInt&amp; x);
MyInt&amp; operator-=(const MyInt&amp; x);
MyInt&amp; operator*=(const MyInt&amp; x);
MyInt&amp; operator/=(const MyInt&amp; x);
MyInt&amp; operator%=(const MyInt&amp; x);
MyInt&amp; operator|=(const MyInt&amp; x);
MyInt&amp; operator&amp;=(const MyInt&amp; x);
MyInt&amp; operator^=(const MyInt&amp; x);
MyInt&amp; operator++();
MyInt&amp; operator--();
};
</pre>
</blockquote>
@ -345,7 +345,7 @@ class MyInt
</ul>
<p>As Daniel Kr&uuml;gler pointed out, this technique violates 14.6.5/2
and is thus non-portable. The reasoning is, that the operators injected
and is thus non-portable. The reasoning is, that the operators injected
by the instantiation of e.g.
<code>less_than_comparable&lt;myclass&gt;</code> can not be found
by ADL according to the rules given by 3.4.2/2, since myclass is
@ -445,6 +445,9 @@ const point&lt;float&gt; pi_over_4_normalized = pi_over_4 / length(pi_over_4);
optional template parameter <code>B</code>, which is not shown, for the
<a href="#chaining">base class chaining</a> technique.</p>
<p>The primary operand type <code>T</code> needs to be of class type,
built-in types are not supported.</p>
<table cellpadding="5" border="1" align="center">
<caption>
Simple Arithmetic Operator Template Classes
@ -917,7 +920,7 @@ T operator+( const T&amp; lhs, const T&amp; rhs )
created, <code>operator+=</code> is called on it and it is copied to the
function return value (which is another unnamed object of type
<code>T</code>). The standard doesn't generally allow the intermediate
object to be optimized away:
object to be optimized away:
<blockquote>
3.7.2/2: Automatic storage duration<br>
@ -928,7 +931,7 @@ T operator+( const T&amp; lhs, const T&amp; rhs )
unused, except that a class object or its copy may be eliminated as
specified in 12.8.
</blockquote>
The reference to 12.8 is important for us:
The reference to 12.8 is important for us:
<blockquote>
12.8/15: Copying class objects<br>
@ -942,7 +945,7 @@ T operator+( const T&amp; lhs, const T&amp; rhs )
</blockquote>
This optimization is known as the named return value optimization (NRVO),
which leads us to the following implementation for
<code>operator+</code>:
<code>operator+</code>:
<pre>
T operator+( const T&amp; lhs, const T&amp; rhs )
{
@ -956,7 +959,7 @@ T operator+( const T&amp; lhs, const T&amp; rhs )
even implement it in an incorrect way which makes it useless here.
Without the NRVO, the NRVO-friendly code is no worse than the original
code showed above, but there is another possible implementation, which
has some very special properties:
has some very special properties:
<pre>
T operator+( T lhs, const T&amp; rhs )
{
@ -982,7 +985,7 @@ T operator+( T lhs, const T&amp; rhs )
will force the NRVO-friendly implementation to be used even for compilers
that don't implement the NRVO. <br>
<br>
<h3><a name="grpd_oprs">Grouped Arithmetic Operators</a></h3>
<p>The following templates provide common groups of related operations.
@ -1864,7 +1867,7 @@ T operator+( T lhs, const T&amp; rhs )
V, D, P, R&gt;</a></code></td>
<td>
Supports the operations and has the requirements of
Supports the operations and has the requirements of
<ul>
<li><code><a href="#input_iteratable">input_iteratable&lt;T,
@ -1878,7 +1881,7 @@ T operator+( T lhs, const T&amp; rhs )
"output_iterator_helper">output_iterator_helper&lt;T&gt;</a></code></td>
<td>
Supports the operations and has the requirements of
Supports the operations and has the requirements of
<ul>
<li><code><a href=
@ -1894,7 +1897,7 @@ T operator+( T lhs, const T&amp; rhs )
R&gt;</a></code></td>
<td>
Supports the operations and has the requirements of
Supports the operations and has the requirements of
<ul>
<li><code><a href="#forward_iteratable">forward_iteratable&lt;T,
@ -1909,7 +1912,7 @@ T operator+( T lhs, const T&amp; rhs )
V, D, P, R&gt;</a></code></td>
<td>
Supports the operations and has the requirements of
Supports the operations and has the requirements of
<ul>
<li><code><a href=
@ -1925,7 +1928,7 @@ T operator+( T lhs, const T&amp; rhs )
V, D, P, R&gt;</a></code></td>
<td>
Supports the operations and has the requirements of
Supports the operations and has the requirements of
<ul>
<li><code><a href=
@ -1976,8 +1979,8 @@ struct function_output_iterator
template&lt;typename T&gt;
function_output_iterator&amp; operator=(T const&amp; value)
{
this-&gt;func(value);
return *this;
this-&gt;func(value);
return *this;
}
private:
@ -2030,7 +2033,7 @@ public:
</pre>
</blockquote>
<p>Check the <a href="../../status/compiler_status.html">compiler status
<p>Check the <a href="http://www.boost.org/development/testing.html">compiler status
report</a> for the test results with selected platforms.</p>
<hr>
@ -2130,8 +2133,8 @@ public:
<p>Revised: 7 Aug 2008</p>
<p>Copyright &copy; Beman Dawes, David Abrahams, 1999-2001.</p>
<p>Copyright &copy; Daniel Frey, 2002-2008.</p>
<p>Use, modification, and distribution is subject to the Boost Software
<p>Copyright &copy; Daniel Frey, 2002-2009.</p>
<p>Use, modification, and distribution is subject to 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">

View File

@ -70,7 +70,7 @@ struct ref_wrapper
struct copy_counter {
static int count_;
copy_counter(copy_counter const& other) {
copy_counter(copy_counter const& /*other*/) {
++count_;
}
copy_counter() {}

View File

@ -7,14 +7,18 @@
</head>
<body>
<!-- Page header -->
<h2>
<img src="../../boost.png" alt="C++ Boost" align="middle" width="277" height="86"/>
Header &lt;<a href="../../boost/swap.hpp">boost/swap.hpp</a>&gt;
</h2>
<h1>Swap</h1>
<p>
<tt>template&lt;class T&gt; void swap(T&amp; <em>left</em>, T&amp; <em>right</em>);</tt>
</p>
<!-- Intoduction -->
<!-- Introduction -->
<p>
The template function <tt>boost::swap</tt> allows the values of two variables to be swapped, using argument dependent lookup to select a specialized swap function if available. If no specialized swap function is available, <tt>std::swap</tt> is used.
</p>
@ -24,10 +28,10 @@
<p>
The generic <tt>std::swap</tt> function requires that the elements to be swapped are assignable and copy constructible. It is usually implemented using one copy construction and two assignments - this is often both unnecessarily restrictive and unnecessarily slow. In addition, where the generic swap implementation provides only the basic guarantee, specialized swap functions are often able to provide the no-throw exception guarantee (and it is considered best practice to do so where possible<sup><a href="#ref1">1</a></sup>).</p>
<p>
The alternative to using argument dependent lookup in this situation is to provide a template specialization of std::swap for every type that requires a specialized swap. Although this is legal C++, no Boost libraries use this method, whereas many Boost libraries provide specialized swap functions in their own namespaces.
The alternative to using argument dependent lookup in this situation is to provide a template specialization of <tt>std::swap</tt> for every type that requires a specialized swap. Although this is legal C++, no Boost libraries use this method, whereas many Boost libraries provide specialized swap functions in their own namespaces.
</p>
<p>
<tt>boost::swap</tt> also supports swapping built-in arrays. Note that <tt>std::swap</tt> doesn't yet do so, but a request to add an overload of <tt>std::swap</tt> for built-in arrays has been well-received by the Library Working Group of the C++ Standards Committee<sup><a href="#ref2">2</a></sup>.
<tt>boost::swap</tt> also supports swapping built-in arrays. Note that <tt>std::swap</tt> originally did not do so, but a request to add an overload of <tt>std::swap</tt> for built-in arrays has been accepted by the C++ Standards Committee<sup><a href="#ref2">2</a></sup>.
</p>
<!-- Exception Safety -->
@ -45,11 +49,11 @@
</ul>
<p>Or:</p>
<ul>
<li>A function with the signature <tt>swap(T&,T&)</tt> is available via argument dependent lookup</li>
<li>A function with the signature <tt>swap(T&amp;,T&amp;)</tt> is available via argument dependent lookup</li>
</ul>
<p>Or:</p>
<ul>
<li>A template specialization of std::swap exists for T</li>
<li>A template specialization of <tt>std::swap</tt> exists for T</li>
</ul>
<p>Or:</p>
<ul>
@ -73,20 +77,20 @@
<em><a href="mailto:Joseph.Gauterin@googlemail.com">Joseph Gauterin</a></em> - for the initial idea, implementation, tests, and documentation
</li>
<li>
<em>Steven Wanatabe</em> - for the idea to make boost::swap less specialized than std::swap, thereby allowing the function to have the name 'swap' without introducing ambiguity
<em>Steven Watanabe</em> - for the idea to make <tt>boost::swap</tt> less specialized than <tt>std::swap</tt>, thereby allowing the function to have the name 'swap' without introducing ambiguity
</li>
</ul>
<!-- References -->
<hr/>
<p><sup><a id="ref1"/>[1]</sup>Scott Meyers, Effective C++ Third Edition, Item 25: "Consider support for a non-throwing swap"</p>
<p><sup><a id="ref2"/>[2]</sup><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#809">LWG issue 809 (std::swap should be overloaded for array types)</a></p>
<p><sup><a id="ref2"/>[2]</sup><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#809">LWG Defect Report 809 (std::swap should be overloaded for array types)</a></p>
<!-- Copyright info -->
<hr/>
<p>Revised: 4 August 2008</p>
<p>Revised: 08 September 2009</p>
<p>
Copyright 2007, 2008 Joseph Gauterin. Use, modification, and distribution are subject to the Boost Software License, Version 1.0.
Copyright 2007 - 2009 Joseph Gauterin. 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

@ -29,5 +29,9 @@ test-suite utility/swap
[ run std_vector_of_global.cpp ../../../test/build//boost_test_exec_monitor/<link>static ]
[ run std_vector_of_other.cpp ../../../test/build//boost_test_exec_monitor/<link>static ]
[ run no_ambiguity_in_boost.cpp ../../../test/build//boost_test_exec_monitor/<link>static ]
[ run swap_arrays.cpp ../../../test/build//boost_test_exec_monitor/<link>static ]
[ run array_of_array_of_class.cpp ../../../test/build//boost_test_exec_monitor/<link>static ]
[ run array_of_array_of_int.cpp ../../../test/build//boost_test_exec_monitor/<link>static ]
[ run array_of_class.cpp ../../../test/build//boost_test_exec_monitor/<link>static ]
[ run array_of_int.cpp ../../../test/build//boost_test_exec_monitor/<link>static ]
[ run array_of_template.cpp ../../../test/build//boost_test_exec_monitor/<link>static ]
;

View File

@ -4,6 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Tests swapping an array of arrays of swap_test_class objects by means of boost::swap.
#include <boost/utility/swap.hpp>
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
@ -33,32 +35,8 @@ namespace std
}
}
// Tests swapping 1-dimensional arrays.
void test_swapping_1D_arrays()
{
const std::size_t dimension = 2;
const swap_test_class initial_array1[dimension] = { swap_test_class(1), swap_test_class(2) };
const swap_test_class initial_array2[dimension] = { swap_test_class(3), swap_test_class(4) };
swap_test_class array1[dimension];
swap_test_class array2[dimension];
std::copy(initial_array1, initial_array1 + dimension, array1);
std::copy(initial_array2, initial_array2 + dimension, array2);
swap_test_class::reset();
boost::swap(array1, array2);
BOOST_CHECK(std::equal(array1, array1 + dimension, initial_array2));
BOOST_CHECK(std::equal(array2, array2 + dimension, initial_array1));
BOOST_CHECK_EQUAL(swap_test_class::swap_count(), dimension);
BOOST_CHECK_EQUAL(swap_test_class::copy_count(), 0);
}
// Tests swapping 2-dimensional arrays.
void test_swapping_2D_arrays()
int test_main(int, char*[])
{
const std::size_t first_dimension = 3;
const std::size_t second_dimension = 4;
@ -76,7 +54,6 @@ void test_swapping_2D_arrays()
ptr2[i].set_data( static_cast<int>(i + number_of_elements) );
}
swap_test_class::reset();
boost::swap(array1, array2);
for (std::size_t i = 0; i < number_of_elements; ++i)
@ -87,14 +64,6 @@ void test_swapping_2D_arrays()
BOOST_CHECK_EQUAL(swap_test_class::swap_count(), number_of_elements);
BOOST_CHECK_EQUAL(swap_test_class::copy_count(), 0);
}
int test_main(int, char*[])
{
test_swapping_1D_arrays();
test_swapping_2D_arrays();
return 0;
}

View File

@ -0,0 +1,42 @@
// Copyright (c) 2008 Joseph Gauterin, 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)
// Tests swapping an array of arrays of integers by means of boost::swap.
#include <boost/utility/swap.hpp>
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <algorithm> //for std::copy and std::equal
#include <cstddef> //for std::size_t
int test_main(int, char*[])
{
const std::size_t first_dimension = 3;
const std::size_t second_dimension = 4;
const std::size_t number_of_elements = first_dimension * second_dimension;
int array1[first_dimension][second_dimension];
int array2[first_dimension][second_dimension];
int* const ptr1 = array1[0];
int* const ptr2 = array2[0];
for (std::size_t i = 0; i < number_of_elements; ++i)
{
ptr1[i] = static_cast<int>(i);
ptr2[i] = static_cast<int>(i + number_of_elements);
}
boost::swap(array1, array2);
for (std::size_t i = 0; i < number_of_elements; ++i)
{
BOOST_CHECK_EQUAL(ptr1[i], static_cast<int>(i + number_of_elements) );
BOOST_CHECK_EQUAL(ptr2[i], static_cast<int>(i) );
}
return 0;
}

View File

@ -0,0 +1,61 @@
// Copyright (c) 2008 Joseph Gauterin, 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)
// Tests swapping an array of arrays of swap_test_class objects by means of boost::swap.
#include <boost/utility/swap.hpp>
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
//Put test class in the global namespace
#include "./swap_test_class.hpp"
#include <algorithm> //for std::copy and std::equal
#include <cstddef> //for std::size_t
//Provide swap function in both the namespace of swap_test_class
//(which is the global namespace), and the std namespace.
//It's common to provide a swap function for a class in both
//namespaces. Scott Meyers recommends doing so: Effective C++,
//Third Edition, item 25, "Consider support for a non-throwing swap".
void swap(swap_test_class& left, swap_test_class& right)
{
left.swap(right);
}
namespace std
{
template <>
void swap(swap_test_class& left, swap_test_class& right)
{
left.swap(right);
}
}
int test_main(int, char*[])
{
const std::size_t array_size = 2;
const swap_test_class initial_array1[array_size] = { swap_test_class(1), swap_test_class(2) };
const swap_test_class initial_array2[array_size] = { swap_test_class(3), swap_test_class(4) };
swap_test_class array1[array_size];
swap_test_class array2[array_size];
std::copy(initial_array1, initial_array1 + array_size, array1);
std::copy(initial_array2, initial_array2 + array_size, array2);
swap_test_class::reset();
boost::swap(array1, array2);
BOOST_CHECK(std::equal(array1, array1 + array_size, initial_array2));
BOOST_CHECK(std::equal(array2, array2 + array_size, initial_array1));
BOOST_CHECK_EQUAL(swap_test_class::swap_count(), array_size);
BOOST_CHECK_EQUAL(swap_test_class::copy_count(), 0);
return 0;
}

View File

@ -0,0 +1,35 @@
// Copyright (c) 2008 Joseph Gauterin, 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)
// Tests swapping an array of integers by means of boost::swap.
#include <boost/utility/swap.hpp>
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <algorithm> //for std::copy and std::equal
#include <cstddef> //for std::size_t
int test_main(int, char*[])
{
const std::size_t array_size = 3;
const int initial_array1[array_size] = { 1, 2, 3 };
const int initial_array2[array_size] = { 4, 5, 6 };
int array1[array_size];
int array2[array_size];
std::copy(initial_array1, initial_array1 + array_size, array1);
std::copy(initial_array2, initial_array2 + array_size, array2);
boost::swap(array1, array2);
BOOST_CHECK(std::equal(array1, array1 + array_size, initial_array2));
BOOST_CHECK(std::equal(array2, array2 + array_size, initial_array1));
return 0;
}

View File

@ -0,0 +1,71 @@
// Copyright (c) 2008 Joseph Gauterin, 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)
// Tests swapping an array of swap_test_template<int> objects by means of boost::swap.
#include <boost/utility/swap.hpp>
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
//Put test class in the global namespace
#include "./swap_test_class.hpp"
#include <algorithm> //for std::copy and std::equal
#include <cstddef> //for std::size_t
template <class T>
class swap_test_template
{
public:
typedef T template_argument;
swap_test_class swap_test_object;
};
template <class T>
inline bool operator==(const swap_test_template<T> & lhs, const swap_test_template<T> & rhs)
{
return lhs.swap_test_object == rhs.swap_test_object;
}
template <class T>
inline bool operator!=(const swap_test_template<T> & lhs, const swap_test_template<T> & rhs)
{
return !(lhs == rhs);
}
//Provide swap function in the namespace of swap_test_template
//(which is the global namespace). Note that it isn't allowed to put
//an overload of this function within the std namespace.
template <class T>
void swap(swap_test_template<T>& left, swap_test_template<T>& right)
{
left.swap_test_object.swap(right.swap_test_object);
}
int test_main(int, char*[])
{
const std::size_t array_size = 2;
const swap_test_template<int> initial_array1[array_size] = { swap_test_class(1), swap_test_class(2) };
const swap_test_template<int> initial_array2[array_size] = { swap_test_class(3), swap_test_class(4) };
swap_test_template<int> array1[array_size];
swap_test_template<int> array2[array_size];
std::copy(initial_array1, initial_array1 + array_size, array1);
std::copy(initial_array2, initial_array2 + array_size, array2);
swap_test_class::reset();
boost::swap(array1, array2);
BOOST_CHECK(std::equal(array1, array1 + array_size, initial_array2));
BOOST_CHECK(std::equal(array2, array2 + array_size, initial_array1));
BOOST_CHECK_EQUAL(swap_test_class::swap_count(), array_size);
BOOST_CHECK_EQUAL(swap_test_class::copy_count(), 0);
return 0;
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2008 Joseph Gauterin, Niels Dekker
// Copyright (c) 2008 - 2010 Joseph Gauterin, Niels Dekker
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@ -17,9 +17,9 @@
int test_main(int, char*[])
{
typedef std::bitset<8> bitset_type;
const bitset_type initial_value1 = 1ul;
const bitset_type initial_value2 = 2ul;
const bitset_type initial_value1 = 1;
const bitset_type initial_value2 = 2;
bitset_type object1 = initial_value1;
bitset_type object2 = initial_value2;

View File

@ -12,7 +12,7 @@
class swap_test_class
{
int m_data;
int m_data;
public:
explicit swap_test_class(int arg = 0)
:

View File

@ -11,7 +11,9 @@ import testing ;
# Please keep the tests ordered by filename
test-suite utility
:
[ run ../addressof_fn_test.cpp ]
[ run ../addressof_test.cpp ]
[ run ../addressof_test2.cpp ]
[ run ../assert_test.cpp ]
[ run ../base_from_member_test.cpp ]
[ run ../binary_search_test.cpp ]
@ -30,9 +32,13 @@ test-suite utility
[ compile result_of_test.cpp ]
[ run ../shared_iterator_test.cpp ]
[ 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 ]
[ compile-fail ../value_init_test_fail3.cpp ]
[ compile-fail ../initialized_test_fail1.cpp ]
[ compile-fail ../initialized_test_fail2.cpp ]
[ run ../verify_test.cpp ]
;

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

View File

@ -5,6 +5,8 @@
// 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
// For more information, see http://www.boost.org/libs/utility
#include <boost/utility/result_of.hpp>
#include <utility>
@ -96,6 +98,11 @@ struct no_result_type_or_result_of
unsigned int operator()();
unsigned short operator()() volatile;
const unsigned short operator()() const volatile;
#if !defined(BOOST_NO_RVALUE_REFERENCES)
short operator()(int&&);
int operator()(int&);
long operator()(int const&);
#endif
};
template<typename T>
@ -106,6 +113,11 @@ struct no_result_type_or_result_of_template
unsigned int operator()();
unsigned short operator()() volatile;
const unsigned short operator()() const volatile;
#if !defined(BOOST_NO_RVALUE_REFERENCES)
short operator()(int&&);
int operator()(int&);
long operator()(int const&);
#endif
};
struct X {};
@ -131,9 +143,21 @@ int main()
BOOST_STATIC_ASSERT((is_same<result_of<int_result_of_template<void>(double)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<const int_result_of_template<void>(double)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type(float)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of(double)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<const int_result_of(double)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_template<void>(float)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of_template<void>(double)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<const int_result_of_template<void>(double)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of(void)>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile int_result_of(void)>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of_template<void>(void)>::type, void>::value));
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_HAS_DECLTYPE)
#if !defined(BOOST_NO_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));
@ -145,11 +169,14 @@ 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_HAS_DECLTYPE)
#if !defined(BOOST_NO_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
@ -168,6 +195,17 @@ int main()
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<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<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));
@ -177,11 +215,23 @@ int main()
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<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));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int const volatile &, int)>::type, int const volatile &>::value));
typedef int (*pf_t)(int);
BOOST_STATIC_ASSERT((is_same<result_of<pf_t(int)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<pf_t const(int)>::type,int>::value));
#if defined(BOOST_HAS_DECLTYPE)
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));
@ -192,6 +242,14 @@ int main()
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_NO_RVALUE_REFERENCES)
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of(int&&)>::type, short>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of(int&)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of(int const&)>::type, long>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of_template<void>(int&&)>::type, short>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of_template<void>(int&)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of_template<void>(int const&)>::type, long>::value));
#endif
#endif
return 0;

View File

@ -1,58 +1,15 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Boost: throw_exception.hpp documentation</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
<table border="0" width="100%">
<tr>
<td width="277"><A href="../../index.htm"> <img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86" border="0"></A>
</td>
<td align="center">
<h1>throw_exception.hpp</h1>
</td>
</tr>
<tr>
<td colspan="2" height="64">&nbsp;</td>
</tr>
</table>
<p>
The header <STRONG>&lt;boost/throw_exception.hpp&gt;</STRONG> defines the
helper function <STRONG>boost::throw_exception</STRONG>. It is intended to be
used in Boost libraries that need to throw exceptions, but support
configurations and platforms where exceptions aren't available, as indicated by
the presence of the <STRONG>BOOST_NO_EXCEPTIONS</STRONG> <A href="../config/config.htm#macro_ref">
configuration macro</A>.
</p>
<P>When <STRONG>BOOST_NO_EXCEPTIONS</STRONG> is not defined, <tt>boost::throw_exception(e)</tt>
is equivalent to <tt>throw e</tt>. Otherwise, the function is left undefined,
and the user is expected to supply an appropriate definition. Callers of <tt>throw_exception</tt>
are allowed to assume that the function never returns; therefore, if the
user-defined <tt>throw_exception</tt> returns, the behavior is undefined.</P>
<h3><a name="Synopsis">Synopsis</a></h3>
<pre>
namespace boost
{
#ifdef BOOST_NO_EXCEPTIONS
void throw_exception(std::exception const &amp; e); // user defined
#else
template&lt;class E&gt; void throw_exception(E const &amp; e)
{
throw e;
}
#endif
}
</pre>
<p><br>
<small>Copyright <20> 2002 by Peter Dimov. 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>
<head>
<meta http-equiv=refresh content="0; URL=../exception/doc/throw_exception.html">
<title>Automatic redirection</title>
</head>
<body>
Automatic redirection failed, please go to
<a href="../exception/doc/throw_exception.html">throw_exception.html</a>.&nbsp;<hr>
<p><EFBFBD> Copyright Beman Dawes, 2001</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 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

@ -151,37 +151,109 @@ 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 supports <code>decltype</code>,
then you can enable automatic result type deduction by
defining the macro <code>BOOST_RESULT_OF_USE_DECLTYPE</code>,
as in the following example.</p>
<blockquote>
<pre>#define BOOST_RESULT_OF_USE_DECLTYPE
#include &lt;boost/utility/result_of.hpp&gt;
struct functor {
template&lt;class T&gt;
T operator()(T x)
{
return x;
}
};
typedef boost::result_of&lt;
functor(int)
&gt;::type type;</pre>
</blockquote>
<p>If <code>decltype</code> is not enabled,
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_type</code>. When <code>F</code>
does not contain <code>result_type</code>,
<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;</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;</pre>
</blockquote>
<p>In a future
release, <code>BOOST_RESULT_OF_USE_DECLTYPE</code>
may be enabled by default on compilers that
support <code>decltype</code>, so if you use the above
protocol please take care to ensure that
the <code>result_type</code>
and <code>result&lt;&gt;</code> members accurately
represent the result type. If you wish to continue to
use the protocol on compilers that
support <code>decltype</code>,
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>.</p>
<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>
Contributed by Doug Gregor.</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

@ -33,6 +33,7 @@
<ul>
<li><a href="#val_init"><code>template class value_initialized&lt;T&gt;</code></a></li>
<li><a href="#initialized"><code>template class initialized&lt;T&gt;</code></a></li>
<li><a href="#initialized_value"><code>initialized_value</code></a></li>
</ul>
@ -123,6 +124,12 @@ constructed by the following declaration:
</pre>
</p>
<p>
The template <a href="#initialized"><code>initialized</code></a>
offers both value-initialization and direct-initialization.
It is especially useful as a data member type, allowing the very same object
to be either direct-initialized or value-initialized.
</p>
<p>
The <code>const</code> object <a href="#initialized_value"><code>initialized_value</code></a>
allows value-initializing a variable as follows:
<pre>
@ -216,44 +223,98 @@ it <em>may</em> in practice still be left uninitialized, because of those
compiler issues! It's hard to make a general statement on what those issues
are like, because they depend on the compiler you are using, its version number,
and the type of object you would like to have value-initialized.
Compilers usually support value-initialization for built-in types properly.
But objects of user-defined types that involve <em>aggregates</em> may <em>in some cases</em>
be partially, or even entirely left uninitialized, when they should be value-initialized.
All compilers we have tested so far support value-initialization for arithmetic types properly.
However, various compilers may leave some types of <em>aggregates</em> uninitialized, when they
should be value-initialized. Value-initialization of objects of a pointer-to-member type may also
go wrong on various compilers.
</p>
<p>
We have encountered issues regarding value-initialization on compilers by
Microsoft, Sun, Borland, and GNU. Here is a list of bug reports on those issues:
<table summary="Compiler bug reports regarding value-initialization" border="0" cellpadding="7" cellspacing="1" >
<tr><td>
<a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744">
Microsoft Feedback ID 100744 - Value-initialization in new-expression</a>
<br>Reported by Pavel Kuznetsov (MetaCommunications Engineering), 2005-07-28
<br>
<a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111">
GCC Bug 30111 - Value-initialization of POD base class doesn't initialize members</a>
<br>Reported by Jonathan Wakely, 2006-12-07
<br>
<a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916">
GCC Bug 33916 - Default constructor fails to initialize array members</a>
<br>Reported by Michael Elizabeth Chastain, 2007-10-26
<br>
<a href="http://qc.codegear.com/wc/qcmain.aspx?d=51854">
Borland Report 51854 - Value-initialization: POD struct should be zero-initialized</a>
<br>Reported by Niels Dekker (LKEB, Leiden University Medical Center), 2007-09-11
<br>
</td></tr></table>
At the moment of writing, May 2010, the following reported issues regarding
value-initialization are still there in current compiler releases:
<ul>
<li>
<a href="https://connect.microsoft.com/VisualStudio/feedback/details/100744">
Microsoft Visual Studio Feedback ID 100744, Value-initialization in new-expression</a>
<br>Reported by Pavel Kuznetsov (MetaCommunications Engineering), 2005
</li><li>
<a href="http://connect.microsoft.com/VisualStudio/feedback/details/484295">
Microsoft Visual Studio Feedback ID 484295, VC++ does not value-initialize members of derived classes without user-declared constructor</a>
<br>Reported by Sylvester Hesp, 2009
</li><li>
<a href="https://connect.microsoft.com/VisualStudio/feedback/details/499606">
Microsoft Visual Studio Feedback ID 499606, Presence of copy constructor breaks member class initialization</a>
<br>Reported by Alex Vakulenko, 2009
</li><li>
<a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=83751">
Embarcadero/C++Builder Report 83751, Value-initialization: arrays should have each element value-initialized</a>
<br>Reported by Niels Dekker (LKEB), 2010
</li><li>
<a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=83851">
Embarcadero/C++Builder Report 83851, Value-initialized temporary triggers internal backend error C1798</a>
<br>Reported by Niels Dekker, 2010
</li><li>
<a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=84279">
Embarcadero/C++Builder Report 84279, Internal compiler error (F1004), value-initializing member function pointer by "new T()"</a>
<br>Reported by Niels Dekker, 2010
</li><li>
Sun CR 6947016, Sun 5.10 may fail to value-initialize an object of a non-POD aggregate.
<br>Reported to Steve Clamage by Niels Dekker, 2010
</li><li>
IBM's XL V10.1 and V11.1 may fail to value-initialize a temporary of a non-POD aggregate.
<br>Reported to Michael Wong by Niels Dekker, 2010
</li><li>
Intel support issue 589832, Attempt to value-initialize pointer-to-member triggers internal error
on Intel 11.1.
<br>Reported by John Maddock, 2010
</li>
</ul>
Note that all known GCC issues regarding value-initialization are
fixed with GCC version 4.4, including
<a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111">GCC Bug 30111</a>.
Clang also has completely implemented value-initialization, as far as we know,
now that <a href="http://llvm.org/bugs/show_bug.cgi?id=7139">Clang Bug 7139</a> is fixed.
</p><p>
New versions of <code>value_initialized</code>
(Boost release version 1.35 or higher)
offer a workaround to these issues: <code>value_initialized</code> will now clear
its internal data, prior to constructing the object that it contains.
offer a workaround to these issues: <code>value_initialized</code> may now clear
its internal data, prior to constructing the object that it contains. It will do
so for those compilers that need to have such a workaround, based on the
<a href="../config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_that_describe_defects"
>compiler defect macro</a> BOOST_NO_COMPLETE_VALUE_INITIALIZATION.
</p>
<h2><a name="types"></a>Types and objects</h2>
<h2><a name="val_init"><code>template class value_initialized&lt;T&gt;</code></a></h2>
<pre>namespace boost {<br><br>template&lt;class T&gt;<br>class value_initialized<br>{<br> public :<br> value_initialized() : x() {}<br> operator T&amp;() const { return x ; }<br> T&amp; data() const { return x ; }<br> void swap( value_initialized&lt;T&gt;&amp; );<br><br> private :<br> <i>unspecified</i> x ;<br>} ;<br><br>template&lt;class T&gt;<br>T const&amp; get ( value_initialized&lt;T&gt; const&amp; x )<br>{<br> return x.data() ;<br>}<br><br>template&lt;class T&gt;<br>T&amp; get ( value_initialized&lt;T&gt;&amp; x )<br>{<br> return x.data() ;<br>}<br><br>} // namespace boost<br></pre>
<pre>namespace boost {<br><br>template&lt;class T&gt;<br>class value_initialized<br>{
<br> public :
<br> value_initialized() : x() {}
<br> operator T const &amp;() const { return x ; }
<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>
<br> private :
<br> <i>unspecified</i> x ;
<br>} ;
<br>
<br>template&lt;class T&gt;
<br>T const&amp; get ( value_initialized&lt;T&gt; const&amp; x )
<br>{
<br> return x.data() ;
<br>}
<br>
<br>template&lt;class T&gt;
<br>T&amp; get ( value_initialized&lt;T&gt;&amp; x )
<br>{
<br> return x.data() ;
<br>}
<br>
<br>} // namespace boost
<br></pre>
<p>An object of this template class is a <code>T</code>-wrapper convertible
to <code>'T&amp;'</code> whose wrapped object (data member of type <code>T</code>)
@ -271,7 +332,8 @@ its internal data, prior to constructing the object that it contains.
<code>T&amp;</code>, the member function <code>data()</code>, or the
non-member function <code>get()</code>: </p>
<pre>void watch(int);<br>value_initialized&lt;int&gt; x;<br><br>watch(x) ; // operator T&amp; used.<br>watch(x.data());<br>watch( get(x) ) // function get() used</pre>
<pre>void watch(int);<br>value_initialized&lt;int&gt; x;
<br><br>watch(x) ; // operator T&amp; used.<br>watch(x.data());<br>watch( get(x) ) // function get() used</pre>
<p>Both <code>const</code> and non-<code>const</code> objects can be wrapped.
Mutable objects can be modified directly from within the wrapper but constant
@ -281,41 +343,84 @@ non-member function <code>get()</code>: </p>
is swappable as well, by calling its <code>swap</code> member function
as well as by calling <code>boost::swap</code>.</p>
<pre>value_initialized&lt;int&gt; x ; <br>static_cast&lt;int&amp;&gt;(x) = 1 ; // OK<br>get(x) = 1 ; // OK<br><br>value_initialized&lt;int const&gt; y ; <br>static_cast&lt;int&amp;&gt;(y) = 1 ; // ERROR: cannot cast to int&amp;<br>static_cast&lt;int const&amp;&gt;(y) = 1 ; // ERROR: cannot modify a const value<br>get(y) = 1 ; // ERROR: cannot modify a const value</pre>
<pre>value_initialized&lt;int&gt; x ; <br>static_cast&lt;int&amp;&gt;(x) = 1 ; // OK<br>get(x) = 1 ; // OK
<br><br>value_initialized&lt;int const&gt; y ; <br>static_cast&lt;int&amp;&gt;(y) = 1 ; // ERROR: cannot cast to int&amp;<br>static_cast&lt;int const&amp;&gt;(y) = 1 ; // ERROR: cannot modify a const value<br>get(y) = 1 ; // ERROR: cannot modify a const value</pre>
<h3>Warning:</h3>
<p>Both the conversion operator and the <code>data()</code> member function
are <code>const</code> in order to allow access to the wrapped object
from a constant wrapper:</p>
<p>The <code>value_initialized</code> implementation of Boost version 1.40.0 and older
allowed <i>non-const</i> access to the wrapped object, from a constant wrapper,
both by its conversion operator and its <code>data()</code> member function. For example:</p>
<pre>void foo(int);<br>value_initialized&lt;int&gt; const x ;<br>foo(x);<br></pre>
<pre>value_initialized&lt;int&gt; const x_c ;<br>int&amp; xr = x_c ; // OK, conversion to int&amp; available even though x_c is itself const.
<br>xr = 2 ; </pre>
<p>But notice that this conversion operator is to <code>T&amp;</code> although
it is itself <code>const</code>. As a consequence, if <code>T</code> is
a non-<code>const</code> type, you can modify the wrapped object even from
within a constant wrapper:</p>
<pre>value_initialized&lt;int&gt; const x_c ;<br>int&amp; xr = x_c ; // OK, conversion to int&amp; available even though x_c is itself const.<br>xr = 2 ; </pre>
<p>The reason for this obscure behavior is that some commonly used compilers
just don't accept the following valid code:</p>
<p>The reason for this obscure behavior was that some compilers
didn't accept the following valid code:</p>
<pre>struct X<br>{<br> operator int&amp;() ;<br> operator int const&amp;() const ; <br>};<br>X x ;<br>(x == 1 ) ; // ERROR HERE!</pre>
<p>These compilers complain about ambiguity between the conversion operators.
This complaint is incorrect, but the only workaround that I know of is
to provide only one of them, which leads to the obscure behavior just explained.<br>
<p>The current version of <code>value_initialized</code> no longer has this obscure behavior.
As compilers nowadays widely support overloading the conversion operator by having a <code>const</code> and a <code>non-const</code> version, we have decided to fix the issue accordingly. So the current version supports the idea of logical constness.
<br>
</p>
<h3>Recommended practice: The non-member get() idiom</h3>
<p>The obscure behavior of being able to modify a non-<code>const</code>
wrapped object from within a constant wrapper can be avoided if access to
wrapped object from within a constant wrapper (as was supported by previous
versions of <code>value_initialized</code>)
can be avoided if access to
the wrapped object is always performed with the <code>get()</code> idiom:</p>
<pre>value_initialized&lt;int&gt; x ;<br>get(x) = 1 ; // OK<br><br>value_initialized&lt;int const&gt; cx ;<br>get(x) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized&lt;int&gt; const x_c ;<br>get(x_c) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized&lt;int const&gt; const cx_c ;<br>get(cx_c) = 1 ; // ERROR: Cannot modify a const object<br></pre>
<h2><a name="initialized"><code>template class initialized&lt;T&gt;</code></a></h2>
<pre>namespace boost {<br><br>template&lt;class T&gt;<br>class initialized<br>{
<br> public :
<br> initialized() : x() {}
<br> explicit initialized(T const &amp; arg) : x(arg) {}
<br> operator T const &amp;() const;
<br> operator T&amp;();
<br> T const &amp;data() const;
<br> T&amp; data();
<br> void swap( value_initialized&lt;T&gt;&amp; );
<br>
<br> private :
<br> <i>unspecified</i> x ;
<br>} ;
<br>
<br>template&lt;class T&gt;
<br>T const&amp; get ( initialized&lt;T&gt; const&amp; x );
<br>
<br>template&lt;class T&gt;
<br>T&amp; get ( initialized&lt;T&gt;&amp; x );
<br>
<br>} // namespace boost
<br></pre>
The template class <code>boost::initialized&lt;T&gt;</code> supports both value-initialization
and direct-initialization, so its interface is a superset of the interface
of <code>value_initialized&lt;T&gt;</code>: Its default-constructor
value-initializes the wrapped object just like the default-constructor of
<code>value_initialized&lt;T&gt;</code>, but <code>boost::initialized&lt;T&gt;</code>
also offers an extra <code>explicit</code>
constructor, which direct-initializes the wrapped object by the specified value.
<p>
<code>initialized&lt;T&gt;</code> is especially useful when the wrapped
object must be either value-initialized or direct-initialized, depending on
runtime conditions. For example, <code>initialized&lt;T&gt;</code> could
hold the value of a data member that may be value-initialized by some
constructors, and direct-initialized by others.
On the other hand, if it is known beforehand that the
object must <i>always</i> be value-initialized, <code>value_initialized&lt;T&gt;</code>
may be preferable. And if the object must always be
direct-initialized, none of the two wrappers really needs to be used.
</p>
<h2><a name="initialized_value"><code>initialized_value</code></a></h2>
<pre>
@ -375,6 +480,9 @@ Special thanks to Bj&ouml;rn Karlsson who carefully edited and completed this do
<p>value_initialized was reimplemented by Fernando Cacciola and Niels Dekker
for Boost release version 1.35 (2008), offering a workaround to various compiler issues.
</p>
<p><code>boost::initialized</code> was very much inspired by feedback from Edward Diener and
Jeffrey Hellrung.
</p>
<p>initialized_value was written by Niels Dekker, and added to Boost release version 1.36 (2008).
</p>
<p>Developed by <a href="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</a>,
@ -383,9 +491,9 @@ for Boost release version 1.35 (2008), offering a workaround to various compiler
</p>
<hr>
<p>Revised 28 August 2008</p>
<p>Revised 30 May 2010</p>
<p>&copy; Copyright Fernando Cacciola, 2002, 2008.</p>
<p>&copy; Copyright Fernando Cacciola, 2002 - 2010.</p>
<p>Distributed under the Boost Software License, Version 1.0. See
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p>
@ -394,4 +502,4 @@ for Boost release version 1.35 (2008), offering a workaround to various compiler
<br>
</body>
</html>
</html>

View File

@ -22,16 +22,16 @@
#pragma hdrstop
#endif
#include "boost/test/minimal.hpp"
#include <boost/detail/lightweight_test.hpp>
//
// Sample POD type
//
struct POD
{
POD () : c(0), i(0), f(0) {}
POD () : f(0), c(0), i(0){}
POD ( char c_, int i_, float f_ ) : c(c_), i(i_), f(f_) {}
POD ( char c_, int i_, float f_ ) : f(f_), c(c_), i(i_) {}
friend std::ostream& operator << ( std::ostream& os, POD const& pod )
{ return os << '(' << pod.c << ',' << pod.i << ',' << pod.f << ')' ; }
@ -215,7 +215,7 @@ template<class T>
void check_initialized_value ( T const& y )
{
T initializedValue = boost::initialized_value ;
BOOST_CHECK ( y == initializedValue ) ;
BOOST_TEST ( y == initializedValue ) ;
}
#ifdef __BORLANDC__
@ -245,128 +245,125 @@ void check_initialized_value( NonPOD const& )
template<class T>
bool test ( T const& y, T const& z )
{
const boost::unit_test::counter_t counter_before_test = boost::minimal_test::errors_counter();
const int errors_before_test = boost::detail::test_errors();
check_initialized_value(y);
boost::value_initialized<T> x ;
BOOST_CHECK ( y == x ) ;
BOOST_CHECK ( y == boost::get(x) ) ;
BOOST_TEST ( y == x ) ;
BOOST_TEST ( y == boost::get(x) ) ;
static_cast<T&>(x) = z ;
boost::get(x) = z ;
BOOST_CHECK ( x == z ) ;
BOOST_TEST ( x == z ) ;
boost::value_initialized<T> const x_c ;
BOOST_CHECK ( y == x_c ) ;
BOOST_CHECK ( y == boost::get(x_c) ) ;
T& x_c_ref = x_c ;
BOOST_TEST ( y == x_c ) ;
BOOST_TEST ( y == boost::get(x_c) ) ;
T& x_c_ref = const_cast<T&>( boost::get(x_c) ) ;
x_c_ref = z ;
BOOST_CHECK ( x_c == z ) ;
BOOST_TEST ( x_c == z ) ;
boost::value_initialized<T> const copy1 = x;
BOOST_CHECK ( boost::get(copy1) == boost::get(x) ) ;
BOOST_TEST ( boost::get(copy1) == boost::get(x) ) ;
boost::value_initialized<T> copy2;
copy2 = x;
BOOST_CHECK ( boost::get(copy2) == boost::get(x) ) ;
BOOST_TEST ( boost::get(copy2) == boost::get(x) ) ;
boost::shared_ptr<boost::value_initialized<T> > ptr( new boost::value_initialized<T> );
BOOST_CHECK ( y == *ptr ) ;
BOOST_TEST ( y == *ptr ) ;
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
boost::value_initialized<T const> cx ;
BOOST_CHECK ( y == cx ) ;
BOOST_CHECK ( y == boost::get(cx) ) ;
BOOST_TEST ( y == cx ) ;
BOOST_TEST ( y == boost::get(cx) ) ;
boost::value_initialized<T const> const cx_c ;
BOOST_CHECK ( y == cx_c ) ;
BOOST_CHECK ( y == boost::get(cx_c) ) ;
BOOST_TEST ( y == cx_c ) ;
BOOST_TEST ( y == boost::get(cx_c) ) ;
#endif
return boost::minimal_test::errors_counter() == counter_before_test ;
return boost::detail::test_errors() == errors_before_test ;
}
int test_main(int, char **)
int main(int, char **)
{
BOOST_CHECK ( test( 0,1234 ) ) ;
BOOST_CHECK ( test( 0.0,12.34 ) ) ;
BOOST_CHECK ( test( POD(0,0,0.0), POD('a',1234,56.78) ) ) ;
BOOST_CHECK ( test( NonPOD( std::string() ), NonPOD( std::string("something") ) ) ) ;
BOOST_TEST ( test( 0,1234 ) ) ;
BOOST_TEST ( test( 0.0,12.34 ) ) ;
BOOST_TEST ( test( POD(0,0,0.0), POD('a',1234,56.78f) ) ) ;
BOOST_TEST ( test( NonPOD( std::string() ), NonPOD( std::string("something") ) ) ) ;
NonPOD NonPOD_object( std::string("NonPOD_object") );
BOOST_CHECK ( test<NonPOD *>( 0, &NonPOD_object ) ) ;
BOOST_TEST ( test<NonPOD *>( 0, &NonPOD_object ) ) ;
AggregatePODStruct zeroInitializedAggregatePODStruct = { 0.0f, '\0', 0 };
AggregatePODStruct nonZeroInitializedAggregatePODStruct = { 1.25f, 'a', -1 };
BOOST_CHECK ( test(zeroInitializedAggregatePODStruct, nonZeroInitializedAggregatePODStruct) );
BOOST_TEST ( test(zeroInitializedAggregatePODStruct, nonZeroInitializedAggregatePODStruct) );
StringAndInt stringAndInt0;
StringAndInt stringAndInt1;
stringAndInt0.i = 0;
stringAndInt1.i = 1;
stringAndInt1.s = std::string("1");
BOOST_CHECK ( test(stringAndInt0, stringAndInt1) );
BOOST_TEST ( test(stringAndInt0, stringAndInt1) );
StructWithDestructor structWithDestructor0;
StructWithDestructor structWithDestructor1;
structWithDestructor0.i = 0;
structWithDestructor1.i = 1;
BOOST_CHECK ( test(structWithDestructor0, structWithDestructor1) );
BOOST_TEST ( test(structWithDestructor0, structWithDestructor1) );
StructWithVirtualFunction structWithVirtualFunction0;
StructWithVirtualFunction structWithVirtualFunction1;
structWithVirtualFunction0.i = 0;
structWithVirtualFunction1.i = 1;
BOOST_CHECK ( test(structWithVirtualFunction0, structWithVirtualFunction1) );
BOOST_TEST ( test(structWithVirtualFunction0, structWithVirtualFunction1) );
DerivedFromAggregatePODStruct derivedFromAggregatePODStruct0;
DerivedFromAggregatePODStruct derivedFromAggregatePODStruct1;
static_cast<AggregatePODStruct &>(derivedFromAggregatePODStruct0) = zeroInitializedAggregatePODStruct;
static_cast<AggregatePODStruct &>(derivedFromAggregatePODStruct1) = nonZeroInitializedAggregatePODStruct;
BOOST_CHECK ( test(derivedFromAggregatePODStruct0, derivedFromAggregatePODStruct1) );
BOOST_TEST ( test(derivedFromAggregatePODStruct0, derivedFromAggregatePODStruct1) );
AggregatePODStructWrapper aggregatePODStructWrapper0;
AggregatePODStructWrapper aggregatePODStructWrapper1;
aggregatePODStructWrapper0.dataMember = zeroInitializedAggregatePODStruct;
aggregatePODStructWrapper1.dataMember = nonZeroInitializedAggregatePODStruct;
BOOST_CHECK ( test(aggregatePODStructWrapper0, aggregatePODStructWrapper1) );
BOOST_TEST ( test(aggregatePODStructWrapper0, aggregatePODStructWrapper1) );
ArrayOfBytes zeroInitializedArrayOfBytes = { 0 };
boost::value_initialized<ArrayOfBytes> valueInitializedArrayOfBytes;
BOOST_CHECK (std::memcmp(get(valueInitializedArrayOfBytes), zeroInitializedArrayOfBytes, sizeof(ArrayOfBytes)) == 0);
BOOST_TEST (std::memcmp(get(valueInitializedArrayOfBytes), zeroInitializedArrayOfBytes, sizeof(ArrayOfBytes)) == 0);
boost::value_initialized<ArrayOfBytes> valueInitializedArrayOfBytes2;
valueInitializedArrayOfBytes2 = valueInitializedArrayOfBytes;
BOOST_CHECK (std::memcmp(get(valueInitializedArrayOfBytes), get(valueInitializedArrayOfBytes2), sizeof(ArrayOfBytes)) == 0);
BOOST_TEST (std::memcmp(get(valueInitializedArrayOfBytes), get(valueInitializedArrayOfBytes2), sizeof(ArrayOfBytes)) == 0);
boost::value_initialized<CopyFunctionCallTester> copyFunctionCallTester1;
BOOST_CHECK ( ! get(copyFunctionCallTester1).is_copy_constructed);
BOOST_CHECK ( ! get(copyFunctionCallTester1).is_assignment_called);
BOOST_TEST ( ! get(copyFunctionCallTester1).is_copy_constructed);
BOOST_TEST ( ! get(copyFunctionCallTester1).is_assignment_called);
boost::value_initialized<CopyFunctionCallTester> copyFunctionCallTester2 = boost::value_initialized<CopyFunctionCallTester>(copyFunctionCallTester1);
BOOST_CHECK ( get(copyFunctionCallTester2).is_copy_constructed);
BOOST_CHECK ( ! get(copyFunctionCallTester2).is_assignment_called);
BOOST_TEST ( get(copyFunctionCallTester2).is_copy_constructed);
BOOST_TEST ( ! get(copyFunctionCallTester2).is_assignment_called);
boost::value_initialized<CopyFunctionCallTester> copyFunctionCallTester3;
copyFunctionCallTester3 = boost::value_initialized<CopyFunctionCallTester>(copyFunctionCallTester1);
BOOST_CHECK ( ! get(copyFunctionCallTester3).is_copy_constructed);
BOOST_CHECK ( get(copyFunctionCallTester3).is_assignment_called);
BOOST_TEST ( ! get(copyFunctionCallTester3).is_copy_constructed);
BOOST_TEST ( get(copyFunctionCallTester3).is_assignment_called);
boost::value_initialized<SwapFunctionCallTester> swapFunctionCallTester1;
boost::value_initialized<SwapFunctionCallTester> swapFunctionCallTester2;
get(swapFunctionCallTester1).data = 1;
get(swapFunctionCallTester2).data = 2;
boost::swap(swapFunctionCallTester1, swapFunctionCallTester2);
BOOST_CHECK( get(swapFunctionCallTester1).data == 2 );
BOOST_CHECK( get(swapFunctionCallTester2).data == 1 );
BOOST_CHECK( get(swapFunctionCallTester1).is_custom_swap_called );
BOOST_CHECK( get(swapFunctionCallTester2).is_custom_swap_called );
BOOST_TEST( get(swapFunctionCallTester1).data == 2 );
BOOST_TEST( get(swapFunctionCallTester2).data == 1 );
BOOST_TEST( get(swapFunctionCallTester1).is_custom_swap_called );
BOOST_TEST( get(swapFunctionCallTester2).is_custom_swap_called );
return 0;
return boost::report_errors();
}
unsigned int expected_failures = 0;

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
}