forked from boostorg/utility
Compare commits
124 Commits
svn-branch
...
svn-branch
Author | SHA1 | Date | |
---|---|---|---|
dbb99bf7df | |||
0f5ae0e73c | |||
497198c624 | |||
9df000eece | |||
8e4054467e | |||
7ae5e14681 | |||
eca8d9f1ef | |||
15021632dc | |||
9baf33dd16 | |||
6bb1ce9b7b | |||
9092b9277b | |||
d09b37d3ef | |||
f3bb2a493c | |||
71b501a0b0 | |||
547c562464 | |||
91aab126e1 | |||
1057ff4d9e | |||
9cb31aee6e | |||
2e4007413e | |||
98bb9e6300 | |||
1cdb78c30a | |||
e0e16be802 | |||
9284a64936 | |||
6e2c1b6b53 | |||
e4d622019f | |||
05af0deaed | |||
00d151828c | |||
f0c62e9e00 | |||
71205b6e84 | |||
98d793152c | |||
dc8ffe92b8 | |||
c55d5ca7de | |||
943af35553 | |||
3cca2755cf | |||
93f6e3473b | |||
4a08e3d0bf | |||
3d650b7f92 | |||
0568a114a8 | |||
7148d6c95e | |||
1cfe3145b4 | |||
57d65d6a94 | |||
ac9f617f7f | |||
b6a55f878c | |||
a4e332c4c0 | |||
e9bbb50eb4 | |||
e8440e8855 | |||
ff0cb36416 | |||
37c5395e7a | |||
3558d61c51 | |||
a201cbe646 | |||
8036d4370f | |||
5fe00c4322 | |||
eb613e1b16 | |||
923caf4410 | |||
36bc0a72ac | |||
d5cacff7c6 | |||
b9411f807f | |||
4111de6f68 | |||
df9315101e | |||
2637dfcc59 | |||
a7e8d28621 | |||
acf8b66a4f | |||
c11e08b6b7 | |||
2cfe775694 | |||
799b066e7d | |||
9fa5d63525 | |||
2a6cd0c9c4 | |||
5825b6c329 | |||
54c78121c2 | |||
2891cb52d6 | |||
0db9276e8c | |||
d6cb9a9176 | |||
ef0f82f62b | |||
9a16aaa2b9 | |||
e763315b55 | |||
fe653d0a9a | |||
26b39384e3 | |||
9525d062b3 | |||
6d196c4244 | |||
e83682c091 | |||
1d146d010a | |||
5684a2f2b3 | |||
95d2c38379 | |||
7d23c75eef | |||
3279399fe3 | |||
87875cadda | |||
c58748cfd9 | |||
58bb88d4bd | |||
11d50ecb9f | |||
636283d7c2 | |||
1df0bf80bc | |||
71e78a0081 | |||
f7e4b0e399 | |||
fb1d2effef | |||
94b91e8c92 | |||
a4b8043e68 | |||
b4a08fc80e | |||
9da96d9737 | |||
a991936c96 | |||
6239e685a2 | |||
e601fcb9c9 | |||
f29a5db08e | |||
22743ee125 | |||
e3c982287a | |||
82e1111bb8 | |||
9339b32178 | |||
3770221507 | |||
e6cb3a77ee | |||
bbccfbbab4 | |||
74a6a693d3 | |||
bf713ad47a | |||
76b17c497b | |||
3de5974419 | |||
7eb1536590 | |||
9339431e03 | |||
f2349baf7d | |||
8745ca628a | |||
ba61e9d796 | |||
afe74fffbc | |||
09a0137016 | |||
a1d3ec6c53 | |||
5be3004e6c | |||
d387905150 | |||
b514e40733 |
@ -1,31 +0,0 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# This file was automatically generated from the original CMakeLists.txt file
|
||||
# Add a variable to hold the headers for the library
|
||||
set (lib_headers
|
||||
assert.hpp
|
||||
call_traits.hpp
|
||||
checked_delete.hpp
|
||||
compressed_pair.hpp
|
||||
current_function.hpp
|
||||
operators.hpp
|
||||
throw_exception.hpp
|
||||
utility.hpp
|
||||
utility
|
||||
)
|
||||
|
||||
# Add a library target to the build system
|
||||
boost_library_project(
|
||||
utility
|
||||
# SRCDIRS
|
||||
TESTDIRS test
|
||||
HEADERS ${lib_headers}
|
||||
# DOCDIRS
|
||||
DESCRIPTION "Various small utilities for C++ programming."
|
||||
MODULARIZED
|
||||
AUTHORS "David Abrahams <dave -at- boostpro.com>"
|
||||
"Brad King"
|
||||
"Douglas Gregor <doug.gregor -at- gmail.com>"
|
||||
# MAINTAINERS
|
||||
)
|
||||
|
||||
|
74
assert.html
74
assert.html
@ -17,36 +17,89 @@
|
||||
<td colspan="2" height="64"> </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><boost/assert.hpp></STRONG> defines the macro <b>BOOST_ASSERT</b>,
|
||||
which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG><cassert></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><boost/assert.hpp></STRONG>
|
||||
<P>If the macro <STRONG>BOOST_DISABLE_ASSERTS</STRONG> is defined when <STRONG><boost/assert.hpp></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><boost/assert.hpp></STRONG>
|
||||
<P>If the macro <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> is defined when <STRONG><boost/assert.hpp></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><boost/assert.hpp></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><cassert></STRONG>, <STRONG><boost/assert.hpp></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><boost/assert.hpp></STRONG> defines the macro <b>BOOST_ASSERT_MSG</b>,
|
||||
which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG><cassert></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><boost/assert.hpp></STRONG>
|
||||
to specify a different output stream. </P>
|
||||
<P>If the macro <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> is defined when <STRONG><boost/assert.hpp></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><boost/assert.hpp></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><cassert></STRONG>, <STRONG><boost/assert.hpp></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><boost/assert.hpp></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. 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>
|
@ -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()
|
||||
{
|
||||
|
@ -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 <type_traits> <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< typename ...T >
|
||||
explicit constexpr base_from_member( T&& ...x )
|
||||
noexcept( std::is_nothrow_constructible<MemberType, T...>::value );
|
||||
#else
|
||||
base_from_member();
|
||||
|
||||
template< typename T1 >
|
||||
@ -154,6 +161,7 @@ protected:
|
||||
typename T10 >
|
||||
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 "perfect forwarding" 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 <<a
|
||||
href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>>.)</p>
|
||||
|
@ -281,7 +281,7 @@ object_id_compare::operator ()
|
||||
}
|
||||
else
|
||||
{
|
||||
return a.second->before( *b.second );
|
||||
return a.second->before( *b.second ) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
100
doc/Jamfile.v2
Normal file
100
doc/Jamfile.v2
Normal file
@ -0,0 +1,100 @@
|
||||
|
||||
# Copyright John Maddock 2005. Use, modification, and distribution are
|
||||
# subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
project : requirements
|
||||
# Path for links to Boost:
|
||||
<xsl:param>boost.root=../../../..
|
||||
|
||||
# Some general style settings:
|
||||
<xsl:param>table.footnote.number.format=1
|
||||
<xsl:param>footnote.number.format=1
|
||||
|
||||
# HTML options first:
|
||||
# Use graphics not text for navigation:
|
||||
<xsl:param>navig.graphics=1
|
||||
# PDF Options:
|
||||
# TOC Generation: this is needed for FOP-0.9 and later:
|
||||
<xsl:param>fop1.extensions=0
|
||||
<xsl:param>xep.extensions=1
|
||||
# TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9!
|
||||
<xsl:param>fop.extensions=0
|
||||
# No indent on body text:
|
||||
<xsl:param>body.start.indent=0pt
|
||||
# Margin size:
|
||||
<xsl:param>page.margin.inner=0.5in
|
||||
# Margin size:
|
||||
<xsl:param>page.margin.outer=0.5in
|
||||
# Paper type = A4
|
||||
<xsl:param>paper.type=A4
|
||||
# Yes, we want graphics for admonishments:
|
||||
<xsl:param>admon.graphics=1
|
||||
# Set this one for PDF generation *only*:
|
||||
# default pnd graphics are awful in PDF form,
|
||||
# better use SVG's instead:
|
||||
<format>pdf:<xsl:param>admon.graphics.extension=".svg"
|
||||
<format>pdf:<xsl:param>admon.graphics.path=$(boost-images)/
|
||||
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/utility/doc/html
|
||||
;
|
||||
|
||||
using quickbook ;
|
||||
|
||||
path-constant boost-images : ../../../doc/src/images ;
|
||||
|
||||
xml declval : declval.qbk ;
|
||||
boostbook standalone_declval
|
||||
:
|
||||
declval
|
||||
:
|
||||
# File name of HTML output:
|
||||
<xsl:param>root.filename=declval
|
||||
# How far down we chunk nested sections, basically all of them:
|
||||
<xsl:param>chunk.section.depth=0
|
||||
# Don't put the first section on the same page as the TOC:
|
||||
<xsl:param>chunk.first.sections=0
|
||||
# How far down sections get TOC's
|
||||
<xsl:param>toc.section.depth=1
|
||||
# Max depth in each TOC:
|
||||
<xsl:param>toc.max.depth=1
|
||||
# How far down we go with TOC's
|
||||
<xsl:param>generate.section.toc.level=1
|
||||
;
|
||||
|
||||
xml string_ref : string_ref.qbk ;
|
||||
boostbook standalone_string_ref
|
||||
:
|
||||
string_ref
|
||||
:
|
||||
# File name of HTML output:
|
||||
<xsl:param>root.filename=string_ref
|
||||
# How far down we chunk nested sections, basically all of them:
|
||||
<xsl:param>chunk.section.depth=0
|
||||
# Don't put the first section on the same page as the TOC:
|
||||
<xsl:param>chunk.first.sections=0
|
||||
# How far down sections get TOC's
|
||||
<xsl:param>toc.section.depth=1
|
||||
# Max depth in each TOC:
|
||||
<xsl:param>toc.max.depth=1
|
||||
# How far down we go with TOC's
|
||||
<xsl:param>generate.section.toc.level=1
|
||||
;
|
||||
|
||||
xml explicit_operator_bool : explicit_operator_bool.qbk ;
|
||||
boostbook standalone_explicit_operator_bool
|
||||
:
|
||||
explicit_operator_bool
|
||||
:
|
||||
# File name of HTML output:
|
||||
<xsl:param>root.filename=explicit_operator_bool
|
||||
# How far down we chunk nested sections, basically all of them:
|
||||
<xsl:param>chunk.section.depth=0
|
||||
# Don't put the first section on the same page as the TOC:
|
||||
<xsl:param>chunk.first.sections=0
|
||||
# How far down sections get TOC's
|
||||
<xsl:param>toc.section.depth=1
|
||||
# Max depth in each TOC:
|
||||
<xsl:param>toc.max.depth=1
|
||||
# How far down we go with TOC's
|
||||
<xsl:param>generate.section.toc.level=1
|
||||
;
|
115
doc/declval.qbk
Normal file
115
doc/declval.qbk
Normal file
@ -0,0 +1,115 @@
|
||||
[/
|
||||
/ Copyright (c) 2008 Howard Hinnant
|
||||
/ Copyright (c) 2009-20012 Vicente J. Botet Escriba
|
||||
/
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
/]
|
||||
|
||||
[article Declval
|
||||
[quickbook 1.5]
|
||||
[authors [Hinnant, Howard]]
|
||||
[authors [Botet Escriba, Vicente J.]]
|
||||
[copyright 2008 Howard Hinnant]
|
||||
[copyright 2009-2012 Vicente J. Botet Escriba]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
||||
]
|
||||
]
|
||||
|
||||
[/===============]
|
||||
[section Overview]
|
||||
[/===============]
|
||||
|
||||
The motivation for `declval` was introduced in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2958.html#Value N2958:
|
||||
Moving Swap Forward]. Here follows a rewording of this chapter.
|
||||
|
||||
With the provision of decltype, late-specified return types, and default template-arguments for function templates a
|
||||
new generation of SFINAE patterns will emerge to at least partially compensate the lack of concepts on the C++0x timescale.
|
||||
Using this technique, it is sometimes necessary to obtain an object of a known type in a non-using context, e.g. given the declaration
|
||||
|
||||
template<class T>
|
||||
T&& declval(); // not used
|
||||
|
||||
as part of the function template declaration
|
||||
|
||||
template<class To, class From>
|
||||
decltype(static_cast<To>(declval<From>())) convert(From&&);
|
||||
|
||||
or as part of a class template definition
|
||||
|
||||
template<class> class result_of;
|
||||
|
||||
template<class Fn, class... ArgTypes>
|
||||
struct result_of<Fn(ArgTypes...)>
|
||||
{
|
||||
typedef decltype(declval<Fn>()(declval<ArgTypes>()...)) type;
|
||||
};
|
||||
|
||||
The role of the function template declval() is a transformation of a type T into a value without using or evaluating this function.
|
||||
The name is supposed to direct the reader's attention to the fact that the expression `declval<T>()` is an lvalue if and only if
|
||||
T is an lvalue-reference, otherwise an rvalue. To extend the domain of this function we can do a bit better by changing its declaration to
|
||||
|
||||
template<class T>
|
||||
typename std::add_rvalue_reference<T>::type declval(); // not used
|
||||
|
||||
which ensures that we can also use cv void as template parameter. The careful reader might have noticed that `declval()`
|
||||
already exists under the name create() as part of the definition of the semantics of the type trait is_convertible in the C++0x standard.
|
||||
|
||||
The provision of a new library component that allows the production of values in unevaluated expressions is considered
|
||||
important to realize constrained templates in C++0x where concepts are not available.
|
||||
This extremely light-weight function is expected to be part of the daily tool-box of the C++0x programmer.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[/=================]
|
||||
[section:reference Reference ]
|
||||
[/=================]
|
||||
|
||||
`#include <boost/utility/declval.hpp>`
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename T>
|
||||
typename add_rvalue_reference<T>::type declval() noexcept; // as unevaluated operand
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
The library provides the function template declval to simplify the definition of expressions which occur as unevaluated operands.
|
||||
|
||||
template <typename T>
|
||||
typename add_rvalue_reference<T>::type declval();
|
||||
|
||||
[*Remarks:] If this function is used, the program is ill-formed.
|
||||
|
||||
[*Remarks:] The template parameter T of declval may be an incomplete type.
|
||||
|
||||
[*Example:]
|
||||
|
||||
template <class To, class From>
|
||||
decltype(static_cast<To>(declval<From>())) convert(From&&);
|
||||
|
||||
Declares a function template convert which only participates in overloading if the type From can be explicitly converted to type To.
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[section History]
|
||||
[/===============]
|
||||
|
||||
[heading boost 1.50]
|
||||
|
||||
Fixes:
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/6570 #6570] Adding noexcept to boost::declval.
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
|
68
doc/explicit_operator_bool.qbk
Normal file
68
doc/explicit_operator_bool.qbk
Normal file
@ -0,0 +1,68 @@
|
||||
[/
|
||||
/ Copyright (c) 2013 Andrey Semashev
|
||||
/
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
/]
|
||||
|
||||
[article BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL
|
||||
[quickbook 1.5]
|
||||
[authors [Semashev, Andrey]]
|
||||
[copyright 2013 Andrey Semashev]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
||||
]
|
||||
]
|
||||
|
||||
[/===============]
|
||||
[section Overview]
|
||||
[/===============]
|
||||
|
||||
`BOOST_EXPLICIT_OPERATOR_BOOL()` and `BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()` are compatibility helper macros that expand to an explicit conversion operator to `bool`. For compilers not supporting explicit conversion operators introduced in C++11 the macros expand to a conversion operator that implements the [@http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool safe bool idiom]. In case if the compiler is not able to handle safe bool idiom well the macros expand to a regular conversion operator to `bool`.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[/===============]
|
||||
[section Examples]
|
||||
[/===============]
|
||||
|
||||
Both macros are intended to be placed within a user's class definition. The generated conversion operators will be implemented in terms of `operator!()` that should be defined by user in this class. In case of `BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()` the generated conversion operator will be declared `constexpr` which requires the corresponding `operator!()` to also be `constexpr`.
|
||||
|
||||
template< typename T >
|
||||
class my_ptr
|
||||
{
|
||||
T* m_p;
|
||||
|
||||
public:
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return !m_p;
|
||||
}
|
||||
};
|
||||
|
||||
Now `my_ptr` can be used in conditional expressions, similarly to a regular pointer:
|
||||
|
||||
my_ptr< int > p;
|
||||
if (p)
|
||||
std::cout << "true" << std::endl;
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[section History]
|
||||
[/===============]
|
||||
|
||||
[heading boost 1.55]
|
||||
|
||||
* The macro was extracted from Boost.Log.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
|
176
doc/html/declval.html
Normal file
176
doc/html/declval.html
Normal file
@ -0,0 +1,176 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Declval</title>
|
||||
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.76.0">
|
||||
<link rel="home" href="declval.html" title="Declval">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"></div>
|
||||
<div class="article">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div><h2 class="title">
|
||||
<a name="declval"></a>Declval</h2></div>
|
||||
<div><div class="authorgroup">
|
||||
<div class="author"><h3 class="author">
|
||||
<span class="firstname">Howard</span> <span class="surname">Hinnant</span>
|
||||
</h3></div>
|
||||
<div class="author"><h3 class="author">
|
||||
<span class="firstname">Vicente J.</span> <span class="surname">Botet Escriba</span>
|
||||
</h3></div>
|
||||
</div></div>
|
||||
<div><p class="copyright">Copyright © 2008 Howard Hinnant</p></div>
|
||||
<div><p class="copyright">Copyright © 2009 -2012 Vicente J. Botet Escriba</p></div>
|
||||
<div><div class="legalnotice">
|
||||
<a name="idp13456288"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></div>
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p><b>Table of Contents</b></p>
|
||||
<dl>
|
||||
<dt><span class="section"><a href="declval.html#declval.overview">Overview</a></span></dt>
|
||||
<dt><span class="section"><a href="declval.html#declval.reference">Reference </a></span></dt>
|
||||
<dt><span class="section"><a href="declval.html#declval.history">History</a></span></dt>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="section declval_overview">
|
||||
<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"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
||||
<span class="identifier">T</span><span class="special">&&</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"><</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">></span>
|
||||
<span class="identifier">decltype</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">To</span><span class="special">>(</span><span class="identifier">declval</span><span class="special"><</span><span class="identifier">From</span><span class="special">>()))</span> <span class="identifier">convert</span><span class="special">(</span><span class="identifier">From</span><span class="special">&&);</span>
|
||||
</pre>
|
||||
<p>
|
||||
or as part of a class template definition
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span><span class="special">></span> <span class="keyword">class</span> <span class="identifier">result_of</span><span class="special">;</span>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</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">></span>
|
||||
<span class="keyword">struct</span> <span class="identifier">result_of</span><span class="special"><</span><span class="identifier">Fn</span><span class="special">(</span><span class="identifier">ArgTypes</span><span class="special">...)></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"><</span><span class="identifier">Fn</span><span class="special">>()(</span><span class="identifier">declval</span><span class="special"><</span><span class="identifier">ArgTypes</span><span class="special">>()...))</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"><</span><span class="identifier">T</span><span class="special">>()</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"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></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"><</span><span class="identifier">T</span><span class="special">>::</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 declval_reference">
|
||||
<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"><</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">></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"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
||||
<span class="keyword">typename</span> <span class="identifier">add_rvalue_reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">declval</span><span class="special">()</span> <span class="identifier">noexcept</span><span class="special">;</span> <span class="comment">// as unevaluated operand
|
||||
</span>
|
||||
<span class="special">}</span> <span class="comment">// namespace boost
|
||||
</span></pre>
|
||||
<p>
|
||||
The library provides the function template declval to simplify the definition
|
||||
of expressions which occur as unevaluated operands.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
||||
<span class="keyword">typename</span> <span class="identifier">add_rvalue_reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</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"><</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">></span>
|
||||
<span class="identifier">decltype</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">To</span><span class="special">>(</span><span class="identifier">declval</span><span class="special"><</span><span class="identifier">From</span><span class="special">>()))</span> <span class="identifier">convert</span><span class="special">(</span><span class="identifier">From</span><span class="special">&&);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Declares a function template convert which only participates in overloading
|
||||
if the type From can be explicitly converted to type To.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section declval_history">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="declval.history"></a><a class="link" href="declval.html#declval.history" title="History">History</a>
|
||||
</h2></div></div></div>
|
||||
<a name="declval.history.boost_1_50"></a><h4>
|
||||
<a name="idp13559952"></a>
|
||||
<a class="link" href="declval.html#declval.history.boost_1_50">boost 1.50</a>
|
||||
</h4>
|
||||
<p>
|
||||
New Features:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
|
||||
<a href="http://svn.boost.org/trac/boost/ticket/6570" target="_top">#6570</a>
|
||||
Adding noexcept to boost::declval.
|
||||
</li></ul></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"><p><small>Last revised: March 25, 2012 at 18:26:23 GMT</small></p></td>
|
||||
<td align="right"><div class="copyright-footer"></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"></div>
|
||||
</body>
|
||||
</html>
|
280
doc/html/string_ref.html
Normal file
280
doc/html/string_ref.html
Normal file
@ -0,0 +1,280 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>String_Ref</title>
|
||||
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="string_ref.html" title="String_Ref">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"></div>
|
||||
<div class="article">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div><h2 class="title">
|
||||
<a name="string_ref"></a>String_Ref</h2></div>
|
||||
<div><div class="authorgroup"><div class="author"><h3 class="author">
|
||||
<span class="firstname">Marshall</span> <span class="surname">Clow</span>
|
||||
</h3></div></div></div>
|
||||
<div><p class="copyright">Copyright © 2012 Marshall Clow</p></div>
|
||||
<div><div class="legalnotice">
|
||||
<a name="string_ref.legal"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></div>
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p><b>Table of Contents</b></p>
|
||||
<dl>
|
||||
<dt><span class="section"><a href="string_ref.html#string_ref.overview">Overview</a></span></dt>
|
||||
<dt><span class="section"><a href="string_ref.html#string_ref.examples">Examples</a></span></dt>
|
||||
<dt><span class="section"><a href="string_ref.html#string_ref.reference">Reference </a></span></dt>
|
||||
<dt><span class="section"><a href="string_ref.html#string_ref.history">History</a></span></dt>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="section string_ref_overview">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="string_ref.overview"></a><a class="link" href="string_ref.html#string_ref.overview" title="Overview">Overview</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
Boost.StringRef is an implementation of Jeffrey Yaskin's <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html" target="_top">N3442:
|
||||
string_ref: a non-owning reference to a string</a>.
|
||||
</p>
|
||||
<p>
|
||||
When you are parsing/processing strings from some external source, frequently
|
||||
you want to pass a piece of text to a procedure for specialized processing.
|
||||
The canonical way to do this is as a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>,
|
||||
but that has certain drawbacks:
|
||||
</p>
|
||||
<p>
|
||||
1) If you are processing a buffer of text (say a HTTP response or the contents
|
||||
of a file), then you have to create the string from the text you want to pass,
|
||||
which involves memory allocation and copying of data.
|
||||
</p>
|
||||
<p>
|
||||
2) if a routine receives a constant <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
|
||||
and wants to pass a portion of that string to another routine, then it must
|
||||
create a new string of that substring.
|
||||
</p>
|
||||
<p>
|
||||
3) A routine receives a constant <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
|
||||
and wants to return a portion of the string, then it must create a new string
|
||||
to return.
|
||||
</p>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">string_ref</span></code> is designed to solve
|
||||
these efficiency problems. A <code class="computeroutput"><span class="identifier">string_ref</span></code>
|
||||
is a read-only reference to a contiguous sequence of characters, and provides
|
||||
much of the functionality of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>.
|
||||
A <code class="computeroutput"><span class="identifier">string_ref</span></code> is cheap to create,
|
||||
copy and pass by value, because it does not actually own the storage that it
|
||||
points to.
|
||||
</p>
|
||||
<p>
|
||||
A <code class="computeroutput"><span class="identifier">string_ref</span></code> is implemented
|
||||
as a small struct that contains a pointer to the start of the character data
|
||||
and a count. A <code class="computeroutput"><span class="identifier">string_ref</span></code> is
|
||||
cheap to create and cheap to copy.
|
||||
</p>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">string_ref</span></code> acts as a container;
|
||||
it includes all the methods that you would expect in a container, including
|
||||
iteration support, <code class="computeroutput"><span class="keyword">operator</span> <span class="special">[]</span></code>,
|
||||
<code class="computeroutput"><span class="identifier">at</span></code> and <code class="computeroutput"><span class="identifier">size</span></code>.
|
||||
It can be used with any of the iterator-based algorithms in the STL - as long
|
||||
as you don't need to change the underlying data (<code class="computeroutput"><span class="identifier">sort</span></code>
|
||||
and <code class="computeroutput"><span class="identifier">remove</span></code>, for example, will
|
||||
not work)
|
||||
</p>
|
||||
<p>
|
||||
Besides generic container functionality, <code class="computeroutput"><span class="identifier">string_ref</span></code>
|
||||
provides a subset of the interface of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>.
|
||||
This makes it easy to replace parameters of type <code class="computeroutput"><span class="keyword">const</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&</span></code>
|
||||
with <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span></code>. Like <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>,
|
||||
<code class="computeroutput"><span class="identifier">string_ref</span></code> has a static member
|
||||
variable named <code class="computeroutput"><span class="identifier">npos</span></code> to denote
|
||||
the result of failed searches, and to mean "the end".
|
||||
</p>
|
||||
<p>
|
||||
Because a <code class="computeroutput"><span class="identifier">string_ref</span></code> does not
|
||||
own the data that it "points to", it introduces lifetime issues into
|
||||
code that uses it. The programmer must ensure that the data that a <code class="computeroutput"><span class="identifier">string_ref</span></code> refers to exists as long as the
|
||||
<code class="computeroutput"><span class="identifier">string_ref</span></code> does.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section string_ref_examples">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="string_ref.examples"></a><a class="link" href="string_ref.html#string_ref.examples" title="Examples">Examples</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
Integrating <code class="computeroutput"><span class="identifier">string_ref</span></code> into
|
||||
your code is fairly simple. Wherever you pass a <code class="computeroutput"><span class="keyword">const</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&</span></code>
|
||||
or <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> as a parameter, that's a candidate
|
||||
for passing a <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span></code>.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&</span><span class="identifier">bar</span> <span class="special">)</span> <span class="special">{</span>
|
||||
<span class="keyword">return</span> <span class="identifier">bar</span><span class="special">.</span><span class="identifier">substr</span> <span class="special">(</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span> <span class="special">);</span>
|
||||
<span class="special">}</span>
|
||||
|
||||
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="string">"ABCDEFG"</span> <span class="special">).</span><span class="identifier">front</span><span class="special">()</span> <span class="special">==</span> <span class="string">"C"</span> <span class="special">)</span> <span class="special">{</span> <span class="comment">/* do something */</span> <span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
Let's figure out what happens in this (contrived) example.
|
||||
</p>
|
||||
<p>
|
||||
First, a temporary string is created from the string literal <code class="computeroutput"><span class="string">"ABCDEFG"</span></code>, and it is passed (by reference)
|
||||
to the routine <code class="computeroutput"><span class="identifier">extract_part</span></code>.
|
||||
Then a second string is created in the call <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">::</span><span class="identifier">substr</span></code>
|
||||
and returned to <code class="computeroutput"><span class="identifier">extract_part</span></code>
|
||||
(this copy may be elided by RVO). Then <code class="computeroutput"><span class="identifier">extract_part</span></code>
|
||||
returns that string back to the caller (again this copy may be elided). The
|
||||
first temporary string is deallocated, and <code class="computeroutput"><span class="identifier">front</span></code>
|
||||
is called on the second string, and then it is deallocated as well.
|
||||
</p>
|
||||
<p>
|
||||
Two <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>s are created, and two copy operations.
|
||||
That's (potentially) four memory allocations and deallocations, and the associated
|
||||
copying of data.
|
||||
</p>
|
||||
<p>
|
||||
Now let's look at the same code with <code class="computeroutput"><span class="identifier">string_ref</span></code>:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span> <span class="identifier">bar</span> <span class="special">)</span> <span class="special">{</span>
|
||||
<span class="keyword">return</span> <span class="identifier">bar</span><span class="special">.</span><span class="identifier">substr</span> <span class="special">(</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span> <span class="special">);</span>
|
||||
<span class="special">}</span>
|
||||
|
||||
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="string">"ABCDEFG"</span> <span class="special">).</span><span class="identifier">front</span><span class="special">()</span> <span class="special">==</span> <span class="string">"C"</span> <span class="special">)</span> <span class="special">{</span> <span class="comment">/* do something */</span> <span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
No memory allocations. No copying of character data. No changes to the code
|
||||
other than the types. There are two <code class="computeroutput"><span class="identifier">string_ref</span></code>s
|
||||
created, and two <code class="computeroutput"><span class="identifier">string_ref</span></code>s
|
||||
copied, but those are cheap operations.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section string_ref_reference">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="string_ref.reference"></a><a class="link" href="string_ref.html#string_ref.reference" title="Reference">Reference </a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
The header file "string_ref.hpp" defines a template <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">basic_string_ref</span></code>,
|
||||
and four specializations - for <code class="computeroutput"><span class="keyword">char</span></code>
|
||||
/ <code class="computeroutput"><span class="keyword">wchar_t</span></code> / <code class="computeroutput"><span class="identifier">char16_t</span></code>
|
||||
/ <code class="computeroutput"><span class="identifier">char32_t</span></code> .
|
||||
</p>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">utility</span><span class="special">/</span><span class="identifier">string_ref</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></code>
|
||||
</p>
|
||||
<p>
|
||||
Construction and copying:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span> <span class="special">();</span> <span class="comment">// Constructs an empty string_ref</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">str</span><span class="special">);</span> <span class="comment">// Constructs from a NULL-terminated string</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">str</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">len</span><span class="special">);</span> <span class="comment">// Constructs from a pointer, length pair</span>
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Allocator</span><span class="special">></span>
|
||||
<span class="identifier">basic_string_ref</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span> <span class="identifier">traits</span><span class="special">,</span> <span class="identifier">Allocator</span><span class="special">>&</span> <span class="identifier">str</span><span class="special">);</span> <span class="comment">// Constructs from a std::string</span>
|
||||
<span class="identifier">basic_string_ref</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">basic_string_ref</span> <span class="special">&</span><span class="identifier">rhs</span><span class="special">);</span>
|
||||
<span class="identifier">basic_string_ref</span><span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span><span class="keyword">const</span> <span class="identifier">basic_string_ref</span> <span class="special">&</span><span class="identifier">rhs</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">string_ref</span></code> does not define
|
||||
a move constructor nor a move-assignment operator because copying a <code class="computeroutput"><span class="identifier">string_ref</span></code> is just a cheap as moving one.
|
||||
</p>
|
||||
<p>
|
||||
Basic container-like functions:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">size</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">length</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">max_size</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">bool</span> <span class="identifier">empty</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
|
||||
<span class="comment">// All iterators are const_iterators</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">begin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">cbegin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">end</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">cend</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">const_reverse_iterator</span> <span class="identifier">rbegin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">const_reverse_iterator</span> <span class="identifier">crbegin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">const_reverse_iterator</span> <span class="identifier">rend</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">const_reverse_iterator</span> <span class="identifier">crend</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Access to the individual elements (all of which are const):
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&</span> <span class="keyword">operator</span><span class="special">[](</span><span class="identifier">size_type</span> <span class="identifier">pos</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&</span> <span class="identifier">at</span><span class="special">(</span><span class="identifier">size_t</span> <span class="identifier">pos</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&</span> <span class="identifier">front</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&</span> <span class="identifier">back</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">data</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Modifying the <code class="computeroutput"><span class="identifier">string_ref</span></code> (but
|
||||
not the underlying data):
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">clear</span><span class="special">();</span>
|
||||
<span class="keyword">void</span> <span class="identifier">remove_prefix</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">n</span><span class="special">);</span>
|
||||
<span class="keyword">void</span> <span class="identifier">remove_suffix</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">n</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Searching:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">size_type</span> <span class="identifier">find</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">rfind</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">rfind</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_first_of</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_last_of</span> <span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_first_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_last_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_first_not_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_first_not_of</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_last_not_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_last_not_of</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
String-like operations:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span> <span class="identifier">substr</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">pos</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">n</span><span class="special">=</span><span class="identifier">npos</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span> <span class="comment">// Creates a new string_ref</span>
|
||||
<span class="keyword">bool</span> <span class="identifier">starts_with</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="keyword">bool</span> <span class="identifier">starts_with</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">x</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="keyword">bool</span> <span class="identifier">ends_with</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="keyword">bool</span> <span class="identifier">ends_with</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">x</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section string_ref_history">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="string_ref.history"></a><a class="link" href="string_ref.html#string_ref.history" title="History">History</a>
|
||||
</h2></div></div></div>
|
||||
<h4>
|
||||
<a name="string_ref.history.h0"></a>
|
||||
<span><a name="string_ref.history.boost_1_53"></a></span><a class="link" href="string_ref.html#string_ref.history.boost_1_53">boost
|
||||
1.53</a>
|
||||
</h4>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
|
||||
Introduced
|
||||
</li></ul></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"><p><small>Last revised: January 14, 2013 at 16:24:14 GMT</small></p></td>
|
||||
<td align="right"><div class="copyright-footer"></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"></div>
|
||||
</body>
|
||||
</html>
|
167
doc/string_ref.qbk
Normal file
167
doc/string_ref.qbk
Normal file
@ -0,0 +1,167 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
/]
|
||||
|
||||
[article String_Ref
|
||||
[quickbook 1.5]
|
||||
[authors [Clow, Marshall]]
|
||||
[copyright 2012 Marshall Clow]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
||||
]
|
||||
]
|
||||
|
||||
[/===============]
|
||||
[section Overview]
|
||||
[/===============]
|
||||
|
||||
Boost.StringRef is an implementation of Jeffrey Yaskin's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html N3442:
|
||||
string_ref: a non-owning reference to a string].
|
||||
|
||||
When you are parsing/processing strings from some external source, frequently you want to pass a piece of text to a procedure for specialized processing. The canonical way to do this is as a `std::string`, but that has certain drawbacks:
|
||||
|
||||
1) If you are processing a buffer of text (say a HTTP response or the contents of a file), then you have to create the string from the text you want to pass, which involves memory allocation and copying of data.
|
||||
|
||||
2) if a routine receives a constant `std::string` and wants to pass a portion of that string to another routine, then it must create a new string of that substring.
|
||||
|
||||
3) A routine receives a constant `std::string` and wants to return a portion of the string, then it must create a new string to return.
|
||||
|
||||
`string_ref` is designed to solve these efficiency problems. A `string_ref` is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of `std::string`. A `string_ref` is cheap to create, copy and pass by value, because it does not actually own the storage that it points to.
|
||||
|
||||
A `string_ref` is implemented as a small struct that contains a pointer to the start of the character data and a count. A `string_ref` is cheap to create and cheap to copy.
|
||||
|
||||
`string_ref` acts as a container; it includes all the methods that you would expect in a container, including iteration support, `operator []`, `at` and `size`. It can be used with any of the iterator-based algorithms in the STL - as long as you don't need to change the underlying data (`sort` and `remove`, for example, will not work)
|
||||
|
||||
Besides generic container functionality, `string_ref` provides a subset of the interface of `std::string`. This makes it easy to replace parameters of type `const std::string &` with `boost::string_ref`. Like `std::string`, `string_ref` has a static member variable named `npos` to denote the result of failed searches, and to mean "the end".
|
||||
|
||||
Because a `string_ref` does not own the data that it "points to", it introduces lifetime issues into code that uses it. The programmer must ensure that the data that a `string_ref` refers to exists as long as the `string_ref` does.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[/===============]
|
||||
[section Examples]
|
||||
[/===============]
|
||||
|
||||
Integrating `string_ref` into your code is fairly simple. Wherever you pass a `const std::string &` or `std::string` as a parameter, that's a candidate for passing a `boost::string_ref`.
|
||||
|
||||
std::string extract_part ( const std::string &bar ) {
|
||||
return bar.substr ( 2, 3 );
|
||||
}
|
||||
|
||||
if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { /* do something */ }
|
||||
|
||||
Let's figure out what happens in this (contrived) example.
|
||||
|
||||
First, a temporary string is created from the string literal `"ABCDEFG"`, and it is passed (by reference) to the routine `extract_part`. Then a second string is created in the call `std::string::substr` and returned to `extract_part` (this copy may be elided by RVO). Then `extract_part` returns that string back to the caller (again this copy may be elided). The first temporary string is deallocated, and `front` is called on the second string, and then it is deallocated as well.
|
||||
|
||||
Two `std::string`s are created, and two copy operations. That's (potentially) four memory allocations and deallocations, and the associated copying of data.
|
||||
|
||||
Now let's look at the same code with `string_ref`:
|
||||
|
||||
boost::string_ref extract_part ( boost::string_ref bar ) {
|
||||
return bar.substr ( 2, 3 );
|
||||
}
|
||||
|
||||
if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ }
|
||||
|
||||
No memory allocations. No copying of character data. No changes to the code other than the types. There are two `string_ref`s created, and two `string_ref`s copied, but those are cheap operations.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[/=================]
|
||||
[section:reference Reference ]
|
||||
[/=================]
|
||||
|
||||
The header file "string_ref.hpp" defines a template `boost::basic_string_ref`, and four specializations - for `char` / `wchar_t` / `char16_t` / `char32_t` .
|
||||
|
||||
`#include <boost/utility/string_ref.hpp>`
|
||||
|
||||
Construction and copying:
|
||||
|
||||
BOOST_CONSTEXPR basic_string_ref (); // Constructs an empty string_ref
|
||||
BOOST_CONSTEXPR basic_string_ref(const charT* str); // Constructs from a NULL-terminated string
|
||||
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len); // Constructs from a pointer, length pair
|
||||
template<typename Allocator>
|
||||
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str); // Constructs from a std::string
|
||||
basic_string_ref (const basic_string_ref &rhs);
|
||||
basic_string_ref& operator=(const basic_string_ref &rhs);
|
||||
|
||||
`string_ref` does not define a move constructor nor a move-assignment operator because copying a `string_ref` is just a cheap as moving one.
|
||||
|
||||
Basic container-like functions:
|
||||
|
||||
BOOST_CONSTEXPR size_type size() const ;
|
||||
BOOST_CONSTEXPR size_type length() const ;
|
||||
BOOST_CONSTEXPR size_type max_size() const ;
|
||||
BOOST_CONSTEXPR bool empty() const ;
|
||||
|
||||
// All iterators are const_iterators
|
||||
BOOST_CONSTEXPR const_iterator begin() const ;
|
||||
BOOST_CONSTEXPR const_iterator cbegin() const ;
|
||||
BOOST_CONSTEXPR const_iterator end() const ;
|
||||
BOOST_CONSTEXPR const_iterator cend() const ;
|
||||
const_reverse_iterator rbegin() const ;
|
||||
const_reverse_iterator crbegin() const ;
|
||||
const_reverse_iterator rend() const ;
|
||||
const_reverse_iterator crend() const ;
|
||||
|
||||
Access to the individual elements (all of which are const):
|
||||
|
||||
BOOST_CONSTEXPR const charT& operator[](size_type pos) const ;
|
||||
const charT& at(size_t pos) const ;
|
||||
BOOST_CONSTEXPR const charT& front() const ;
|
||||
BOOST_CONSTEXPR const charT& back() const ;
|
||||
BOOST_CONSTEXPR const charT* data() const ;
|
||||
|
||||
Modifying the `string_ref` (but not the underlying data):
|
||||
|
||||
void clear();
|
||||
void remove_prefix(size_type n);
|
||||
void remove_suffix(size_type n);
|
||||
|
||||
Searching:
|
||||
|
||||
size_type find(basic_string_ref s) const ;
|
||||
size_type find(charT c) const ;
|
||||
size_type rfind(basic_string_ref s) const ;
|
||||
size_type rfind(charT c) const ;
|
||||
size_type find_first_of(charT c) const ;
|
||||
size_type find_last_of (charT c) const ;
|
||||
|
||||
size_type find_first_of(basic_string_ref s) const ;
|
||||
size_type find_last_of(basic_string_ref s) const ;
|
||||
size_type find_first_not_of(basic_string_ref s) const ;
|
||||
size_type find_first_not_of(charT c) const ;
|
||||
size_type find_last_not_of(basic_string_ref s) const ;
|
||||
size_type find_last_not_of(charT c) const ;
|
||||
|
||||
String-like operations:
|
||||
|
||||
BOOST_CONSTEXPR basic_string_ref substr(size_type pos, size_type n=npos) const ; // Creates a new string_ref
|
||||
bool starts_with(charT c) const ;
|
||||
bool starts_with(basic_string_ref x) const ;
|
||||
bool ends_with(charT c) const ;
|
||||
bool ends_with(basic_string_ref x) const ;
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[section History]
|
||||
[/===============]
|
||||
|
||||
[heading boost 1.53]
|
||||
* Introduced
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
|
111
enable_if.html
111
enable_if.html
@ -21,6 +21,7 @@
|
||||
<BR>
|
||||
<BR>
|
||||
Copyright 2003 Jaakko Jä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&);
|
||||
|
||||
</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<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t) { return t; }
|
||||
|
||||
</PRE>
|
||||
|
||||
<!--TOC section Using <TT>enable_if</TT>-->
|
||||
|
||||
<H2><A NAME="htoc5">3</A> 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 <class T>
|
||||
T foo(T t, typename enable_if<boost::is_arithmetic<T> >::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> 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 <boost/type_traits/is_arithmetic.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
class test
|
||||
{
|
||||
public:
|
||||
// A constructor that works for any argument list of size 10
|
||||
template< class... T
|
||||
, typename boost::enable_if_c< sizeof...( T ) == 10, int >::type = 0
|
||||
>
|
||||
test( T&&... );
|
||||
|
||||
// A conversion operation that can convert to any arithmetic type
|
||||
template< class T
|
||||
, typename boost::enable_if< boost::is_arithmetic< T >, int >::type = 0
|
||||
>
|
||||
operator T() const;
|
||||
|
||||
// A conversion operation that can convert to any pointer type
|
||||
template< class T
|
||||
, typename boost::enable_if< boost::is_pointer< T >, int >::type = 0
|
||||
>
|
||||
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> Enabling template class specializations</H3><!--SEC END -->
|
||||
<H3><A NAME="htoc7">3.2</A> 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> Overlapping enabler conditions</H3><!--SEC END -->
|
||||
<H3><A NAME="htoc8">3.3</A> 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> Lazy <TT>enable_if</TT></H3><!--SEC END -->
|
||||
<H3><A NAME="htoc9">3.4</A> 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<T, U>::value</TT> defines when
|
||||
<BR>
|
||||
<!--TOC subsection Compiler workarounds-->
|
||||
|
||||
<H3><A NAME="htoc9">3.4</A> Compiler workarounds</H3><!--SEC END -->
|
||||
<H3><A NAME="htoc10">3.5</A> 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 M. Josuttis.
|
||||
Addison-Wesley, 2002.</DL>
|
||||
|
||||
<hr/>
|
||||
<p>Copyright Jaakko Järvi, Jeremiah Willcock and Andrew Lumsdaine<BR>
|
||||
<EM>{jajarvi|jewillco|lums}@osl.iu.edu</EM><BR>
|
||||
Indiana University<BR>
|
||||
<p>Copyright Jaakko Jä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>
|
||||
|
44
identity_type/doc/Jamfile.v2
Normal file
44
identity_type/doc/Jamfile.v2
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
# Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
# Distributed under the Boost Software License, Version 1.0
|
||||
# (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
# Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
import quickbook ;
|
||||
using boostbook ;
|
||||
|
||||
doxygen reference : ../../../../boost/utility/identity_type.hpp
|
||||
: <reftitle>"Reference"
|
||||
<doxygen:param>PREDEFINED="DOXYGEN"
|
||||
<doxygen:param>QUIET=YES
|
||||
<doxygen:param>WARN_IF_UNDOCUMENTED=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>HIDE_UNDOC_CLASSES=YES
|
||||
<doxygen:param>ALIASES=" Params=\"<b>Parameters:</b> <table border="0">\" Param{2}=\"<tr><td><b><tt>\\1</tt></b></td><td>\\2</td></tr>\" EndParams=\"</table>\" Returns=\"<b>Returns:</b>\" Note=\"<b>Note:</b>\" Warning=\"<b>Warning:</b>\" See=\"<b>See:</b>\" RefSect{2}=\"\\xmlonly<link linkend='boost_utility_identitytype.\\1'>\\2</link>\\endxmlonly\" RefClass{1}=\"\\xmlonly<computeroutput><classname alt='\\1'>\\1</classname></computeroutput>\\endxmlonly\" RefFunc{1}=\"\\xmlonly<computeroutput><functionname alt='\\1'>\\1</functionname></computeroutput>\\endxmlonly\" RefMacro{1}=\"\\xmlonly<computeroutput><macroname alt='\\1'>\\1</macroname></computeroutput>\\endxmlonly\" "
|
||||
;
|
||||
|
||||
# This target must be called "index" so to generate "index.html" file.
|
||||
xml index : identity_type.qbk : <dependency>reference ;
|
||||
|
||||
boostbook doc : index
|
||||
: <location>html
|
||||
<format>onehtml
|
||||
<xsl:param>toc.section.depth=0
|
||||
<xsl:param>html.stylesheet=../../../../../doc/src/boostbook.css
|
||||
<xsl:param>boost.root=../../../../..
|
||||
;
|
||||
|
||||
#
|
||||
# This is very imperfect - it results in both html and pdf docs being built,
|
||||
# for some reason I can't get the "onehtml" format specified above to play nice
|
||||
# with the usual incantations for mixed pdf/html builds. JM 06/2012.
|
||||
#
|
||||
boostbook pdf_doc : index
|
||||
:
|
||||
<format>pdf
|
||||
<format>html:<build>no
|
||||
;
|
||||
|
||||
install pdf_doc_install : pdf_doc : <location>. <name>identity_type.pdf <install-type>PDF ;
|
||||
explicit pdf_doc_install ;
|
252
identity_type/doc/html/index.html
Normal file
252
identity_type/doc/html/index.html
Normal file
@ -0,0 +1,252 @@
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Boost.Utility/IdentityType 1.0.0</title><link rel="stylesheet" type="text/css" href="../../../../../doc/src/boostbook.css"><meta name="generator" content="DocBook XSL Stylesheets V1.76.1"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="chapter" title="Boost.Utility/IdentityType 1.0.0"><div class="titlepage"><div><div><h2 class="title"><a name="boost_utility_identitytype"></a>Boost.Utility/IdentityType 1.0.0</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Lorenzo</span> <span class="surname">Caminiti <code class="email"><<a class="email" href="mailto:lorcaminiti@gmail.com">lorcaminiti@gmail.com</a>></code></span></h3></div></div><div><p class="copyright">Copyright © 2009-2012 Lorenzo
|
||||
Caminiti</p></div><div><div class="legalnotice" title="Legal Notice"><a name="boost_utility_identitytype.legal"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0 (see accompanying
|
||||
file LICENSE_1_0.txt or a copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p></div></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#boost_utility_identitytype.motivation">Motivation</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.solution">Solution</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.templates">Templates</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.abstract_types">Abstract Types</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.annex__usage">Annex: Usage</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.annex__implementation">Annex:
|
||||
Implementation</a></span></dt><dt><span class="section"><a href="#reference">Reference</a></span></dt></dl></div><p>
|
||||
This library allows to wrap types within round parenthesis so they can always
|
||||
be passed as macro parameters.
|
||||
</p><div class="section boost_utility_identitytype_motivation" title="Motivation"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.motivation"></a><a class="link" href="#boost_utility_identitytype.motivation" title="Motivation">Motivation</a></h2></div></div></div><p>
|
||||
Consider the following macro which declares a variable named <code class="computeroutput"><span class="identifier">var</span></code><code class="literal"><span class="emphasis"><em>n</em></span></code>
|
||||
with the specified <code class="literal"><span class="emphasis"><em>type</em></span></code> (see also
|
||||
<a href="../../test/var_error.cpp" target="_top"><code class="literal">var_error.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">VAR</span><span class="special">(</span><span class="identifier">type</span><span class="special">,</span> <span class="identifier">n</span><span class="special">)</span> <span class="identifier">type</span> <span class="identifier">var</span> <span class="error">#</span><span class="preprocessor"># n</span>
|
||||
|
||||
<span class="identifier">VAR</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="number">1</span><span class="special">);</span> <span class="comment">// OK.</span>
|
||||
<span class="identifier">VAR</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">>,</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"><</span><span class="keyword">int</span></code>
|
||||
</li><li class="listitem">
|
||||
<code class="computeroutput"><span class="keyword">char</span><span class="special">></span></code>
|
||||
</li><li class="listitem">
|
||||
<code class="computeroutput"><span class="number">2</span></code>
|
||||
</li></ol></div><p>
|
||||
Note that, differently from the compiler, the preprocessor only recognizes
|
||||
round parenthesis <code class="computeroutput"><span class="special">()</span></code>. Angular
|
||||
<code class="computeroutput"><span class="special"><></span></code> and squared <code class="computeroutput"><span class="special">[]</span></code> parenthesis are not recognized by the preprocessor
|
||||
when parsing macro parameters.
|
||||
</p></div><div class="section boost_utility_identitytype_solution" title="Solution"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.solution"></a><a class="link" href="#boost_utility_identitytype.solution" title="Solution">Solution</a></h2></div></div></div><p>
|
||||
In some cases, it might be possible to workaround this issue by avoiding to
|
||||
pass the type expression to the macro all together. For example, in the case
|
||||
above a <code class="computeroutput"><span class="keyword">typedef</span></code> could have been
|
||||
used to specify the type expression with the commas outside the macro (see
|
||||
also <a href="../../test/var.cpp" target="_top"><code class="literal">var.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">></span> <span class="identifier">map_type</span><span class="special">;</span>
|
||||
<span class="identifier">VAR</span><span class="special">(</span><span class="identifier">map_type</span><span class="special">,</span> <span class="number">3</span><span class="special">);</span> <span class="comment">// OK.</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
When this is neither possible nor desired (e.g., see the function template
|
||||
<code class="computeroutput"><span class="identifier">f</span></code> in the section below), this
|
||||
library header <code class="computeroutput"><a class="link" href="#header.boost.utility.identity_type_hpp" title="Header <boost/utility/identity_type.hpp>">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"><</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">></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"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">>)),</span> <span class="number">4</span><span class="special">);</span> <span class="comment">// OK.</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
The <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> macro
|
||||
expands to an expression that evaluates (at compile-time) to the specified
|
||||
type. The specified type is never split into multiple macro parameters because
|
||||
it is always wrapped by a set of extra round parenthesis <code class="computeroutput"><span class="special">()</span></code>.
|
||||
In fact, a total of two sets of round parenthesis must be used: The parenthesis
|
||||
to invoke the macro <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(...)</span></code> plus the inner parenthesis to wrap the
|
||||
type passed to the macro <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((...))</span></code>.
|
||||
</p><p>
|
||||
This macro works on any <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/standards" target="_top">C++03</a>
|
||||
compiler (and it does not use <a href="http://en.wikipedia.org/wiki/Variadic_macro" target="_top">variadic
|
||||
macros</a>). <sup>[<a name="boost_utility_identitytype.solution.f0" href="#ftn.boost_utility_identitytype.solution.f0" class="footnote">1</a>]</sup> The authors originally developed and tested this library using
|
||||
GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features enabled
|
||||
<code class="computeroutput"><span class="special">-</span><span class="identifier">std</span><span class="special">=</span><span class="identifier">c</span><span class="special">++</span><span class="number">0</span><span class="identifier">x</span></code>) on Cygwin
|
||||
and Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7. See the library <a href="http://www.boost.org/development/tests/release/developer/utility-identity_type.html" target="_top">regressions
|
||||
test results</a> for more information on supported compilers and platforms.
|
||||
</p></div><div class="section boost_utility_identitytype_templates" title="Templates"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.templates"></a><a class="link" href="#boost_utility_identitytype.templates" title="Templates">Templates</a></h2></div></div></div><p>
|
||||
This macro must be prefixed by <code class="computeroutput"><span class="keyword">typename</span></code>
|
||||
when used within templates. For example, let's program a macro that declares
|
||||
a function parameter named <code class="computeroutput"><span class="identifier">arg</span></code><code class="literal"><span class="emphasis"><em>n</em></span></code>
|
||||
with the specified <code class="literal"><span class="emphasis"><em>type</em></span></code> (see also
|
||||
<a href="../../test/template.cpp" target="_top"><code class="literal">template.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">ARG</span><span class="special">(</span><span class="identifier">type</span><span class="special">,</span> <span class="identifier">n</span><span class="special">)</span> <span class="identifier">type</span> <span class="identifier">arg</span> <span class="error">#</span><span class="preprocessor"># n</span>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></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"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">T</span><span class="special">>)),</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"><<</span> <span class="identifier">arg1</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special"><<</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"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">></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"><</span><span class="keyword">char</span><span class="special">>(</span><span class="identifier">a</span><span class="special">);</span> <span class="comment">// OK...</span>
|
||||
<span class="comment">// f(a); // ... but error.</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
However, note that the template parameter <code class="computeroutput"><span class="keyword">char</span></code>
|
||||
must be manually specified when invoking the function as in <code class="computeroutput"><span class="identifier">f</span><span class="special"><</span><span class="keyword">char</span><span class="special">>(</span><span class="identifier">a</span><span class="special">)</span></code>. In fact,
|
||||
when the <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
macro is used to wrap a function template parameter, the template parameter
|
||||
can no longer be automatically deduced by the compiler form the function call
|
||||
as <code class="computeroutput"><span class="identifier">f</span><span class="special">(</span><span class="identifier">a</span><span class="special">)</span></code> would
|
||||
have done. <sup>[<a name="boost_utility_identitytype.templates.f0" href="#ftn.boost_utility_identitytype.templates.f0" class="footnote">2</a>]</sup> (This limitation does not apply to class templates because class
|
||||
template parameters must always be explicitly specified.) In other words, without
|
||||
using the <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
macro, C++ would normally be able to automatically deduce the function template
|
||||
parameter as shown below:
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></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"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">T</span><span class="special">></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"><<</span> <span class="identifier">arg1</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special"><<</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"><</span><span class="keyword">char</span><span class="special">>(</span><span class="identifier">a</span><span class="special">);</span> <span class="comment">// OK...</span>
|
||||
<span class="identifier">g</span><span class="special">(</span><span class="identifier">a</span><span class="special">);</span> <span class="comment">// ... and also OK.</span>
|
||||
</pre><p>
|
||||
</p></div><div class="section boost_utility_identitytype_abstract_types" title="Abstract Types"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.abstract_types"></a><a class="link" href="#boost_utility_identitytype.abstract_types" title="Abstract Types">Abstract Types</a></h2></div></div></div><p>
|
||||
On some compilers (e.g., GCC), using this macro on abstract types (i.e., classes
|
||||
with one or more pure virtual functions) generates a compiler error. This can
|
||||
be avoided by manipulating the type adding and removing a reference to it.
|
||||
</p><p>
|
||||
Let's program a macro that performs a static assertion on a <a href="http://en.wikipedia.org/wiki/Template_metaprogramming" target="_top">Template
|
||||
Meta-Programming</a> (TMP) meta-function (similarly to Boost.MPL <a href="http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/assert.html" target="_top"><code class="computeroutput"><span class="identifier">BOOST_MPL_ASSERT</span></code></a>). The <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> macro can be used
|
||||
to pass a meta-function with multiple template parameters to the assert macro
|
||||
(so to handle the commas separating the template parameters). In this case,
|
||||
if the meta-function is an abstract type, it needs to be manipulated adding
|
||||
and removing a reference to it (see also <a href="../../test/abstract.cpp" target="_top"><code class="literal">abstract.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TMP_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">)</span> <span class="special">\</span>
|
||||
<span class="identifier">BOOST_STATIC_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">::</span><span class="identifier">value</span><span class="special">)</span>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</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">></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">&</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"><</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"><</span> <span class="comment">// abstract type.</span>
|
||||
<span class="identifier">abstract</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">true</span><span class="special">></span>
|
||||
<span class="special">>::</span><span class="identifier">type</span>
|
||||
<span class="special">))</span>
|
||||
<span class="special">>::</span><span class="identifier">type</span>
|
||||
<span class="special">);</span>
|
||||
</pre><p>
|
||||
</p></div><div class="section boost_utility_identitytype_annex__usage" title="Annex: Usage"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.annex__usage"></a><a class="link" href="#boost_utility_identitytype.annex__usage" title="Annex: Usage">Annex: Usage</a></h2></div></div></div><p>
|
||||
The <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> macro
|
||||
can be used either when calling a user-defined macro (as shown by the examples
|
||||
so far), or internally when implementing a user-defined macro (as shown below).
|
||||
When <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> is
|
||||
used in the implementation of the user-defined macro, the caller of the user
|
||||
macro will have to specify the extra parenthesis (see also <a href="../../test/paren.cpp" target="_top"><code class="literal">paren.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TMP_ASSERT_PAREN</span><span class="special">(</span><span class="identifier">parenthesized_metafunction</span><span class="special">)</span> <span class="special">\</span>
|
||||
<span class="comment">/* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */</span> <span class="special">\</span>
|
||||
<span class="identifier">BOOST_STATIC_ASSERT</span><span class="special">(</span><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(</span><span class="identifier">parenthesized_metafunction</span><span class="special">)::</span><span class="identifier">value</span><span class="special">)</span>
|
||||
|
||||
<span class="preprocessor">#define</span> <span class="identifier">TMP_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">)</span> <span class="special">\</span>
|
||||
<span class="identifier">BOOST_STATIC_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">::</span><span class="identifier">value</span><span class="special">)</span>
|
||||
|
||||
<span class="comment">// Specify only extra parenthesis `((...))`.</span>
|
||||
<span class="identifier">TMP_ASSERT_PAREN</span><span class="special">((</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">></span> <span class="keyword">const</span><span class="special">>));</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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">></span> <span class="keyword">const</span><span class="special">>)));</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
However, note that the caller will <span class="emphasis"><em>always</em></span> have to specify
|
||||
the extra parenthesis even when the macro parameters contain no comma:
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="identifier">TMP_ASSERT_PAREN</span><span class="special">((</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special"><</span><span class="keyword">int</span> <span class="keyword">const</span><span class="special">>));</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"><</span><span class="keyword">int</span> <span class="keyword">const</span><span class="special">>);</span> <span class="comment">// No extra `((...))` and no macro.</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
In some cases, using <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
in the implementation of the user-defined macro might provide the best syntax
|
||||
for the caller. For example, this is the case for <code class="computeroutput"><span class="identifier">BOOST_MPL_ASSERT</span></code>
|
||||
because the majority of template meta-programming expressions contain unwrapped
|
||||
commas so it is less confusing for the user to always specify the extra parenthesis
|
||||
<code class="computeroutput"><span class="special">((...))</span></code> instead of using <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>:
|
||||
</p><pre class="programlisting"><span class="identifier">BOOST_MPL_ASSERT</span><span class="special">((</span> <span class="comment">// Natural syntax.</span>
|
||||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">and_</span><span class="special"><</span>
|
||||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span>
|
||||
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span>
|
||||
<span class="special">></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">&))</span> <span class="identifier">x</span><span class="special">,</span> <span class="special">((</span><span class="keyword">int</span><span class="special">&))</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">&</span>
|
||||
<span class="identifier">x</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&</span> <span class="identifier">y</span><span class="special">)</span></code> in the common cases when the parameter types
|
||||
contain no comma (while still allowing to specify parameter types with commas
|
||||
as special cases using <code class="computeroutput"><span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">>))&</span>
|
||||
<span class="identifier">x</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&</span> <span class="identifier">y</span><span class="special">)</span></code>).
|
||||
</p></div><div class="section boost_utility_identitytype_annex__implementation" title="Annex: Implementation"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.annex__implementation"></a><a class="link" href="#boost_utility_identitytype.annex__implementation" title="Annex: Implementation">Annex:
|
||||
Implementation</a></h2></div></div></div><p>
|
||||
The implementation of this library macro is equivalent to the following: <sup>[<a name="boost_utility_identitytype.annex__implementation.f0" href="#ftn.boost_utility_identitytype.annex__implementation.f0" class="footnote">3</a>]</sup>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</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">></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"><</span><span class="keyword">void</span> <span class="identifier">parenthesized_type</span><span class="special">>::</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"><</span><span class="keyword">int</span><span class="special">,</span>
|
||||
<span class="keyword">char</span><span class="special">>)</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"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">>)</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 <boost/utility/identity_type.hpp>"><div class="titlepage"><div><div><h3 class="title"><a name="header.boost.utility.identity_type_hpp"></a>Header <<a href="../../../../../boost/utility/identity_type.hpp" target="_top">boost/utility/identity_type.hpp</a>></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: <<a class="link" href="#header.boost.utility.identity_type_hpp" title="Header <boost/utility/identity_type.hpp>">boost/utility/identity_type.hpp</a>>
|
||||
|
||||
</span>BOOST_IDENTITY_TYPE(parenthesized_type)</pre></div><div class="refsect1" title="Description"><a name="id554262"></a><h2>Description</h2><p><span class="bold"><strong>Parameters:</strong></span> </p><div class="informaltable"><table class="table"><colgroup><col><col></colgroup><tbody><tr><td><span class="bold"><strong><code class="computeroutput">parenthesized_type</code></strong></span></td><td>The type expression to be passed as macro parameter wrapped by a single set of round parenthesis <code class="computeroutput">(...)</code>. This type expression can contain an arbitrary number of commas. </td></tr></tbody></table></div><p>
|
||||
</p><p>This macro works on any C++03 compiler (it does not use variadic macros).</p><p>This macro must be prefixed by <code class="computeroutput">typename</code> when used within templates. Note that the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to be explicitly specified when calling the function template).</p><p>On some compilers (like GCC), using this macro on abstract types requires to add and remove a reference to the specified type. </p></div></div></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a id="ftn.boost_utility_identitytype.solution.f0" href="#boost_utility_identitytype.solution.f0" class="para">1</a>] </sup>
|
||||
Using variadic macros, it would be possible to require a single set of extra
|
||||
parenthesis <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(</span></code><code class="literal"><span class="emphasis"><em>type</em></span></code><code class="computeroutput"><span class="special">)</span></code> instead of two <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span></code><code class="literal"><span class="emphasis"><em>type</em></span></code><code class="computeroutput"><span class="special">))</span></code> but variadic macros are not part of C++03
|
||||
(even if nowadays they are supported by most modern compilers and they are
|
||||
also part of C++11).
|
||||
</p></div><div class="footnote"><p><sup>[<a id="ftn.boost_utility_identitytype.templates.f0" href="#boost_utility_identitytype.templates.f0" class="para">2</a>] </sup>
|
||||
This is because the implementation of <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
wraps the specified type within a meta-function.
|
||||
</p></div><div class="footnote"><p><sup>[<a id="ftn.boost_utility_identitytype.annex__implementation.f0" href="#boost_utility_identitytype.annex__implementation.f0" class="para">3</a>] </sup>
|
||||
There is absolutely no guarantee that the macro is actually implemented using
|
||||
the code listed in this documentation. The listed code is for explanatory
|
||||
purposes only.
|
||||
</p></div></div></div></body></html>
|
165
identity_type/doc/identity_type.qbk
Normal file
165
identity_type/doc/identity_type.qbk
Normal file
@ -0,0 +1,165 @@
|
||||
|
||||
[/ Copyright (C) 2009-2012 Lorenzo Caminiti ]
|
||||
[/ Distributed under the Boost Software License, Version 1.0 ]
|
||||
[/ (see accompanying file LICENSE_1_0.txt or a copy at ]
|
||||
[/ http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
[/ Home at http://www.boost.org/libs/utility/identity_type ]
|
||||
|
||||
[library Boost.Utility/IdentityType
|
||||
[quickbook 1.5]
|
||||
[version 1.0.0]
|
||||
[copyright 2009-2012 Lorenzo Caminiti]
|
||||
[purpose wraps types with round parenthesis]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0
|
||||
(see accompanying file LICENSE_1_0.txt or a copy at
|
||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
||||
]
|
||||
[authors [Caminiti <email>lorcaminiti@gmail.com</email>, Lorenzo]]
|
||||
[category Utilities]
|
||||
]
|
||||
|
||||
This library allows to wrap types within round parenthesis so they can always be passed as macro parameters.
|
||||
|
||||
[import ../test/var_error.cpp]
|
||||
[import ../test/var.cpp]
|
||||
[import ../test/template.cpp]
|
||||
[import ../test/abstract.cpp]
|
||||
[import ../test/paren.cpp]
|
||||
|
||||
[section Motivation]
|
||||
|
||||
Consider the following macro which declares a variable named `var`[^['n]] with the specified [^['type]] (see also [@../../test/var_error.cpp =var_error.cpp=]):
|
||||
|
||||
[var_error]
|
||||
|
||||
The first macro invocation works correctly declaring a variable named `var1` of type `int`.
|
||||
However, the second macro invocation fails generating a preprocessor error similar to the following:
|
||||
|
||||
[pre
|
||||
error: macro "VAR" passed 3 arguments, but takes just 2
|
||||
]
|
||||
|
||||
That is because the `std::map` type passed as the first macro parameter contains a comma `,` not wrapped by round parenthesis `()`.
|
||||
The preprocessor interprets that unwrapped comma as a separation between macro parameters concluding that a total of three (and not two) parameters are passed to the macro in the following order:
|
||||
|
||||
# `std::map<int`
|
||||
# `char>`
|
||||
# `2`
|
||||
|
||||
Note that, differently from the compiler, the preprocessor only recognizes round parenthesis `()`.
|
||||
Angular `<>` and squared `[]` parenthesis are not recognized by the preprocessor when parsing macro parameters.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Solution]
|
||||
|
||||
In some cases, it might be possible to workaround this issue by avoiding to pass the type expression to the macro all together.
|
||||
For example, in the case above a `typedef` could have been used to specify the type expression with the commas outside the macro (see also [@../../test/var.cpp =var.cpp=]):
|
||||
|
||||
[var_typedef]
|
||||
|
||||
When this is neither possible nor desired (e.g., see the function template `f` in the section below), this library header [headerref boost/utility/identity_type.hpp] defines a macro [macroref BOOST_IDENTITY_TYPE] which can be used to workaround the issue while keeping the type expression as one of the macro parameters (see also [@../../test/var.cpp =var.cpp=]).
|
||||
|
||||
[var_ok]
|
||||
|
||||
The [macroref BOOST_IDENTITY_TYPE] macro expands to an expression that evaluates (at compile-time) to the specified type.
|
||||
The specified type is never split into multiple macro parameters because it is always wrapped by a set of extra round parenthesis `()`.
|
||||
In fact, a total of two sets of round parenthesis must be used: The parenthesis to invoke the macro `BOOST_IDENTITY_TYPE(...)` plus the inner parenthesis to wrap the type passed to the macro `BOOST_IDENTITY_TYPE((...))`.
|
||||
|
||||
This macro works on any [@http://www.open-std.org/JTC1/SC22/WG21/docs/standards C++03] compiler (and it does not use [@http://en.wikipedia.org/wiki/Variadic_macro variadic macros]).
|
||||
[footnote
|
||||
Using variadic macros, it would be possible to require a single set of extra parenthesis `BOOST_IDENTITY_TYPE(`[^['type]]`)` instead of two `BOOST_IDENTITY_TYPE((`[^['type]]`))` but variadic macros are not part of C++03 (even if nowadays they are supported by most modern compilers and they are also part of C++11).
|
||||
]
|
||||
The authors originally developed and tested this library using GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features enabled `-std=c++0x`) on Cygwin and Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7.
|
||||
See the library [@http://www.boost.org/development/tests/release/developer/utility-identity_type.html regressions test results] for more information on supported compilers and platforms.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Templates]
|
||||
|
||||
This macro must be prefixed by `typename` when used within templates.
|
||||
For example, let's program a macro that declares a function parameter named `arg`[^['n]] with the specified [^['type]] (see also [@../../test/template.cpp =template.cpp=]):
|
||||
|
||||
[template_f_decl]
|
||||
[template_f_call]
|
||||
|
||||
However, note that the template parameter `char` must be manually specified when invoking the function as in `f<char>(a)`.
|
||||
In fact, when the [macroref BOOST_IDENTITY_TYPE] macro is used to wrap a function template parameter, the template parameter can no longer be automatically deduced by the compiler form the function call as `f(a)` would have done.
|
||||
[footnote
|
||||
This is because the implementation of [macroref BOOST_IDENTITY_TYPE] wraps the specified type within a meta-function.
|
||||
]
|
||||
(This limitation does not apply to class templates because class template parameters must always be explicitly specified.)
|
||||
In other words, without using the [macroref BOOST_IDENTITY_TYPE] macro, C++ would normally be able to automatically deduce the function template parameter as shown below:
|
||||
|
||||
[template_g_decl]
|
||||
[template_g_call]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Abstract Types]
|
||||
|
||||
On some compilers (e.g., GCC), using this macro on abstract types (i.e., classes with one or more pure virtual functions) generates a compiler error.
|
||||
This can be avoided by manipulating the type adding and removing a reference to it.
|
||||
|
||||
Let's program a macro that performs a static assertion on a [@http://en.wikipedia.org/wiki/Template_metaprogramming Template Meta-Programming] (TMP) meta-function (similarly to Boost.MPL [@http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/assert.html `BOOST_MPL_ASSERT`]).
|
||||
The [macroref BOOST_IDENTITY_TYPE] macro can be used to pass a meta-function with multiple template parameters to the assert macro (so to handle the commas separating the template parameters).
|
||||
In this case, if the meta-function is an abstract type, it needs to be manipulated adding and removing a reference to it (see also [@../../test/abstract.cpp =abstract.cpp=]):
|
||||
|
||||
[abstract]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Annex: Usage]
|
||||
|
||||
The [macroref BOOST_IDENTITY_TYPE] macro can be used either when calling a user-defined macro (as shown by the examples so far), or internally when implementing a user-defined macro (as shown below).
|
||||
When [macroref BOOST_IDENTITY_TYPE] is used in the implementation of the user-defined macro, the caller of the user macro will have to specify the extra parenthesis (see also [@../../test/paren.cpp =paren.cpp=]):
|
||||
|
||||
[paren]
|
||||
|
||||
However, note that the caller will /always/ have to specify the extra parenthesis even when the macro parameters contain no comma:
|
||||
|
||||
[paren_always]
|
||||
|
||||
In some cases, using [macroref BOOST_IDENTITY_TYPE] in the implementation of the user-defined macro might provide the best syntax for the caller.
|
||||
For example, this is the case for `BOOST_MPL_ASSERT` because the majority of template meta-programming expressions contain unwrapped commas so it is less confusing for the user to always specify the extra parenthesis `((...))` instead of using [macroref BOOST_IDENTITY_TYPE]:
|
||||
|
||||
BOOST_MPL_ASSERT(( // Natural syntax.
|
||||
boost::mpl::and_<
|
||||
boost::is_const<T>
|
||||
, boost::is_reference<T>
|
||||
>
|
||||
));
|
||||
|
||||
However, in other situations it might be preferable to not require the extra parenthesis in the common cases and handle commas as special cases using [macroref BOOST_IDENTITY_TYPE].
|
||||
For example, this is the case for [@http://www.boost.org/libs/local_function `BOOST_LOCAL_FUNCTION`] for which always requiring the extra parenthesis `((...))` around the types would lead to an unnatural syntax for the local function signature:
|
||||
|
||||
int BOOST_LOCAL_FUNCTION( ((int&)) x, ((int&)) y ) { // Unnatural syntax.
|
||||
return x + y;
|
||||
} BOOST_LOCAL_FUNCTION_NAME(add)
|
||||
|
||||
Instead requiring the user to specify [macroref BOOST_IDENTITY_TYPE] only when needed allows for the more natural syntax `BOOST_LOCAL_FUNCTION(int& x, int& y)` in the common cases when the parameter types contain no comma (while still allowing to specify parameter types with commas as special cases using `BOOST_LOCAL_FUNCTION(BOOST_IDENTITY_TYPE((std::map<int, char>))& x, int& y)`).
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Annex: Implementation]
|
||||
|
||||
The implementation of this library macro is equivalent to the following:
|
||||
[footnote
|
||||
There is absolutely no guarantee that the macro is actually implemented using the code listed in this documentation.
|
||||
The listed code is for explanatory purposes only.
|
||||
]
|
||||
|
||||
#include <boost/type_traits/function_traits.hpp>
|
||||
|
||||
#define BOOST_IDENTITY_TYPE(parenthesized_type) \
|
||||
boost::function_traits<void parenthesized_type>::arg1_type
|
||||
|
||||
Essentially, the type is wrapped between round parenthesis `(std::map<int, char>)` so it can be passed as a single macro parameter even if it contains commas.
|
||||
Then the parenthesized type is transformed into the type of a function returning `void` and with the specified type as the type of the first and only argument `void (std::map<int, char>)`.
|
||||
Finally, the type of the first argument `arg1_type` is extracted at compile-time using the `function_traits` meta-function therefore obtaining the original type from the parenthesized type (effectively stripping the extra parenthesis from around the specified type).
|
||||
|
||||
[endsect]
|
||||
|
||||
[xinclude reference.xml]
|
||||
|
15
identity_type/index.html
Normal file
15
identity_type/index.html
Normal 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> <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>
|
16
identity_type/test/Jamfile.v2
Normal file
16
identity_type/test/Jamfile.v2
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
# Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
# Distributed under the Boost Software License, Version 1.0
|
||||
# (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
# Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
import testing ;
|
||||
|
||||
compile-fail var_error.cpp ;
|
||||
run var.cpp ;
|
||||
run template.cpp ;
|
||||
run abstract.cpp ;
|
||||
run noncopyable.cpp ;
|
||||
run paren.cpp ;
|
||||
|
35
identity_type/test/abstract.cpp
Normal file
35
identity_type/test/abstract.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
|
||||
//[abstract
|
||||
#define TMP_ASSERT(metafunction) \
|
||||
BOOST_STATIC_ASSERT(metafunction::value)
|
||||
|
||||
template<typename T, bool b>
|
||||
struct abstract {
|
||||
static const bool value = b;
|
||||
virtual void f(T const& x) = 0; // Pure virtual function.
|
||||
};
|
||||
|
||||
TMP_ASSERT(
|
||||
boost::remove_reference< // Add and remove
|
||||
BOOST_IDENTITY_TYPE(( // reference for
|
||||
boost::add_reference< // abstract type.
|
||||
abstract<int, true>
|
||||
>::type
|
||||
))
|
||||
>::type
|
||||
);
|
||||
//]
|
||||
|
||||
int main() { return 0; }
|
||||
|
25
identity_type/test/noncopyable.cpp
Normal file
25
identity_type/test/noncopyable.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
//[noncopyable
|
||||
#define TMP_ASSERT(metafunction) \
|
||||
BOOST_STATIC_ASSERT(metafunction::value)
|
||||
|
||||
template<typename T, T init>
|
||||
struct noncopyable : boost::noncopyable {
|
||||
static const T value = init;
|
||||
};
|
||||
|
||||
TMP_ASSERT(BOOST_IDENTITY_TYPE((noncopyable<bool, true>)));
|
||||
//]
|
||||
|
||||
int main() { return 0; }
|
||||
|
35
identity_type/test/paren.cpp
Normal file
35
identity_type/test/paren.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <map>
|
||||
|
||||
//[paren
|
||||
#define TMP_ASSERT_PAREN(parenthesized_metafunction) \
|
||||
/* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \
|
||||
BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value)
|
||||
|
||||
#define TMP_ASSERT(metafunction) \
|
||||
BOOST_STATIC_ASSERT(metafunction::value)
|
||||
|
||||
// Specify only extra parenthesis `((...))`.
|
||||
TMP_ASSERT_PAREN((boost::is_const<std::map<int, char> const>));
|
||||
|
||||
// Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro.
|
||||
TMP_ASSERT(BOOST_IDENTITY_TYPE((boost::is_const<std::map<int, char> const>)));
|
||||
//]
|
||||
|
||||
//[paren_always
|
||||
TMP_ASSERT_PAREN((boost::is_const<int const>)); // Always extra `((...))`.
|
||||
|
||||
TMP_ASSERT(boost::is_const<int const>); // No extra `((...))` and no macro.
|
||||
//]
|
||||
|
||||
int main() { return 0; }
|
||||
|
48
identity_type/test/template.cpp
Normal file
48
identity_type/test/template.cpp
Normal 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;
|
||||
}
|
||||
|
26
identity_type/test/var.cpp
Normal file
26
identity_type/test/var.cpp
Normal 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; }
|
||||
|
18
identity_type/test/var_error.cpp
Normal file
18
identity_type/test/var_error.cpp
Normal 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; }
|
||||
|
@ -46,7 +46,7 @@ HREF="../../boost/utility/typed_in_place_factory.hpp">boost/utility/typed_in_pla
|
||||
<p>Suppose we have a class</p>
|
||||
<pre>struct X
|
||||
{
|
||||
X ( int, std:::string ) ;
|
||||
X ( int, std::string ) ;
|
||||
} ;</pre>
|
||||
<p>And a container for it which supports an empty state (that is, which can contain zero objects):</p>
|
||||
<pre>struct C
|
||||
|
@ -1,8 +1,11 @@
|
||||
//
|
||||
// boost/assert.hpp - BOOST_ASSERT(expr)
|
||||
// BOOST_ASSERT_MSG(expr, msg)
|
||||
// BOOST_VERIFY(expr)
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright (c) 2007 Peter Dimov
|
||||
// Copyright (c) Beman Dawes 2011
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -13,6 +16,16 @@
|
||||
// See http://www.boost.org/libs/utility/assert.html for documentation.
|
||||
//
|
||||
|
||||
//
|
||||
// Stop inspect complaining about use of 'assert':
|
||||
//
|
||||
// boostinspect:naassert_macro
|
||||
//
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// BOOST_ASSERT //
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#undef BOOST_ASSERT
|
||||
|
||||
#if defined(BOOST_DISABLE_ASSERTS)
|
||||
@ -21,22 +34,100 @@
|
||||
|
||||
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/current_function.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined
|
||||
|
||||
void assertion_failed(char const * expr,
|
||||
char const * function, char const * file, long line); // user defined
|
||||
} // namespace boost
|
||||
|
||||
#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
|
||||
#define BOOST_ASSERT(expr) (BOOST_LIKELY(!!(expr)) \
|
||||
? ((void)0) \
|
||||
: ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
|
||||
|
||||
#else
|
||||
# include <assert.h> // .h to support old libraries w/o <cassert> - effect is the same
|
||||
# define BOOST_ASSERT(expr) assert(expr)
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// BOOST_ASSERT_MSG //
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# undef BOOST_ASSERT_MSG
|
||||
|
||||
#if defined(BOOST_DISABLE_ASSERTS) || defined(NDEBUG)
|
||||
|
||||
#define BOOST_ASSERT_MSG(expr, msg) ((void)0)
|
||||
|
||||
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/current_function.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
void assertion_failed_msg(char const * expr, char const * msg,
|
||||
char const * function, char const * file, long line); // user defined
|
||||
} // namespace boost
|
||||
|
||||
#define BOOST_ASSERT_MSG(expr, msg) (BOOST_LIKELY(!!(expr)) \
|
||||
? ((void)0) \
|
||||
: ::boost::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
|
||||
|
||||
#else
|
||||
#ifndef BOOST_ASSERT_HPP
|
||||
#define BOOST_ASSERT_HPP
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/current_function.hpp>
|
||||
|
||||
// IDE's like Visual Studio perform better if output goes to std::cout or
|
||||
// some other stream, so allow user to configure output stream:
|
||||
#ifndef BOOST_ASSERT_MSG_OSTREAM
|
||||
# define BOOST_ASSERT_MSG_OSTREAM std::cerr
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace assertion
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// Note: The template is needed to make the function non-inline and avoid linking errors
|
||||
template< typename CharT >
|
||||
BOOST_NOINLINE void assertion_failed_msg(CharT const * expr, char const * msg, char const * function,
|
||||
char const * file, long line)
|
||||
{
|
||||
BOOST_ASSERT_MSG_OSTREAM
|
||||
<< "***** Internal Program Error - assertion (" << expr << ") failed in "
|
||||
<< function << ":\n"
|
||||
<< file << '(' << line << "): " << msg << std::endl;
|
||||
#ifdef UNDER_CE
|
||||
// The Windows CE CRT library does not have abort() so use exit(-1) instead.
|
||||
std::exit(-1);
|
||||
#else
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
} // detail
|
||||
} // assertion
|
||||
} // detail
|
||||
#endif
|
||||
|
||||
#define BOOST_ASSERT_MSG(expr, msg) (BOOST_LIKELY(!!(expr)) \
|
||||
? ((void)0) \
|
||||
: ::boost::assertion::detail::assertion_failed_msg(#expr, msg, \
|
||||
BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// BOOST_VERIFY //
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#undef BOOST_VERIFY
|
||||
|
||||
#if defined(BOOST_DISABLE_ASSERTS) || ( !defined(BOOST_ENABLE_ASSERT_HANDLER) && defined(NDEBUG) )
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc.
|
||||
|
||||
//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)
|
||||
|
||||
#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>
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
#include <boost/exception_ptr.hpp>
|
||||
#endif
|
||||
|
||||
#endif
|
@ -9,6 +9,8 @@
|
||||
#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
|
||||
#define BOOST_NONCOPYABLE_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// Private copy constructor and copy assignment ensure classes derived from
|
||||
@ -21,11 +23,21 @@ namespace noncopyable_ // protection from unintended ADL
|
||||
class noncopyable
|
||||
{
|
||||
protected:
|
||||
noncopyable() {}
|
||||
#ifndef BOOST_NO_DEFAULTED_FUNCTIONS
|
||||
BOOST_CONSTEXPR noncopyable() = default;
|
||||
~noncopyable() = default;
|
||||
#else
|
||||
noncopyable() {}
|
||||
~noncopyable() {}
|
||||
private: // emphasize the following members are private
|
||||
#endif
|
||||
#ifndef BOOST_NO_DELETED_FUNCTIONS
|
||||
noncopyable( const noncopyable& ) = delete;
|
||||
noncopyable& operator=( const noncopyable& ) = delete;
|
||||
#else
|
||||
private: // emphasize the following members are private
|
||||
noncopyable( const noncopyable& );
|
||||
const noncopyable& operator=( const noncopyable& );
|
||||
noncopyable& operator=( const noncopyable& );
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
#include <boost/utility/binary.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
#include <boost/checked_delete.hpp>
|
||||
#include <boost/next_prior.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
|
||||
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
|
||||
// Douglas Gregor (gregod@cs.rpi.edu)
|
||||
//
|
||||
// Copyright (C) 2002, 2008 Peter Dimov
|
||||
@ -50,7 +50,7 @@ template<class T> struct addressof_impl
|
||||
|
||||
template<class T> T * addressof( T & v )
|
||||
{
|
||||
#if defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) )
|
||||
#if (defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) ) ) || defined( __SUNPRO_CC )
|
||||
|
||||
return boost::detail::addressof_impl<T>::f( v, 0 );
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// boost utility/base_from_member.hpp header file --------------------------//
|
||||
|
||||
// Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and
|
||||
// Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and
|
||||
// distribution are subject to the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or a copy at
|
||||
// <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
@ -10,10 +10,15 @@
|
||||
#ifndef BOOST_UTILITY_BASE_FROM_MEMBER_HPP
|
||||
#define BOOST_UTILITY_BASE_FROM_MEMBER_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/preprocessor/arithmetic/inc.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
|
||||
// Base-from-member arity configuration macro ------------------------------//
|
||||
@ -53,6 +58,59 @@
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Type-unmarking class template -------------------------------------------//
|
||||
|
||||
// Type-trait to get the raw type, i.e. the type without top-level reference nor
|
||||
// cv-qualification, from a type expression. Mainly for function arguments, any
|
||||
// reference part is stripped first.
|
||||
|
||||
// Contributed by Daryle Walker
|
||||
|
||||
template < typename T >
|
||||
struct remove_cv_ref
|
||||
{
|
||||
typedef typename ::boost::remove_cv<typename
|
||||
::boost::remove_reference<T>::type>::type type;
|
||||
|
||||
}; // boost::detail::remove_cv_ref
|
||||
|
||||
// Unmarked-type comparison class template ---------------------------------//
|
||||
|
||||
// Type-trait to check if two type expressions have the same raw type.
|
||||
|
||||
// Contributed by Daryle Walker, based on a work-around by Luc Danton
|
||||
|
||||
template < typename T, typename U >
|
||||
struct is_related
|
||||
: public ::boost::is_same<
|
||||
typename ::boost::detail::remove_cv_ref<T>::type,
|
||||
typename ::boost::detail::remove_cv_ref<U>::type >
|
||||
{};
|
||||
|
||||
// Enable-if-on-unidentical-unmarked-type class template -------------------//
|
||||
|
||||
// Enable-if on the first two type expressions NOT having the same raw type.
|
||||
|
||||
// Contributed by Daryle Walker, based on a work-around by Luc Danton
|
||||
|
||||
#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
template<typename ...T>
|
||||
struct enable_if_unrelated
|
||||
: public ::boost::enable_if_c<true>
|
||||
{};
|
||||
|
||||
template<typename T, typename U, typename ...U2>
|
||||
struct enable_if_unrelated<T, U, U2...>
|
||||
: public ::boost::disable_if< ::boost::detail::is_related<T, U> >
|
||||
{};
|
||||
#endif
|
||||
|
||||
} // namespace boost::detail
|
||||
|
||||
|
||||
// Base-from-member class template -----------------------------------------//
|
||||
|
||||
// Helper to initialize a base object so a derived class can use this
|
||||
@ -68,12 +126,25 @@ class base_from_member
|
||||
protected:
|
||||
MemberType member;
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
|
||||
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
|
||||
!defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && \
|
||||
!(defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 4))
|
||||
template <typename ...T, typename EnableIf = typename
|
||||
::boost::detail::enable_if_unrelated<base_from_member, T...>::type>
|
||||
explicit BOOST_CONSTEXPR base_from_member( T&& ...x )
|
||||
BOOST_NOEXCEPT_IF( BOOST_NOEXCEPT_EXPR(::new ((void*) 0) MemberType(
|
||||
static_cast<T&&>(x)... )) ) // no std::is_nothrow_constructible...
|
||||
: member( static_cast<T&&>(x)... ) // ...nor std::forward needed
|
||||
{}
|
||||
#else
|
||||
base_from_member()
|
||||
: member()
|
||||
{}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO( 1, BOOST_PP_INC(BOOST_BASE_FROM_MEMBER_MAX_ARITY),
|
||||
BOOST_PRIVATE_CTR_DEF, _ )
|
||||
#endif
|
||||
|
||||
}; // boost::base_from_member
|
||||
|
||||
|
@ -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
|
||||
|
44
include/boost/utility/declval.hpp
Normal file
44
include/boost/utility/declval.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
// declval.hpp -------------------------------------------------------------//
|
||||
|
||||
// Copyright 2010 Vicente J. Botet Escriba
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_UTILITY_DECLVAL_HPP
|
||||
#define BOOST_UTILITY_DECLVAL_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#include <boost/type_traits/add_rvalue_reference.hpp>
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// C++03 implementation of //
|
||||
// 20.2.4 Function template declval [declval] //
|
||||
// Written by Vicente J. Botet Escriba //
|
||||
// //
|
||||
// 1 The library provides the function template declval to simplify the
|
||||
// definition of expressions which occur as unevaluated operands.
|
||||
// 2 Remarks: If this function is used, the program is ill-formed.
|
||||
// 3 Remarks: The template parameter T of declval may be an incomplete type.
|
||||
// [ Example:
|
||||
//
|
||||
// template <class To, class From>
|
||||
// decltype(static_cast<To>(declval<From>())) convert(From&&);
|
||||
//
|
||||
// declares a function template convert which only participates in overloading
|
||||
// if the type From can be explicitly converted to type To. For another example
|
||||
// see class template common_type (20.9.7.6). -end example ]
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename T>
|
||||
typename add_rvalue_reference<T>::type declval() BOOST_NOEXCEPT; // as unevaluated operand
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_UTILITY_DECLVAL_HPP
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -5,52 +5,16 @@
|
||||
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Copyright Daniel Walker, Eric Niebler, Michel Morin 2008-2012.
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or
|
||||
// copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// For more information, see http://www.boost.org/libs/utility
|
||||
#if !defined(BOOST_PP_IS_ITERATING)
|
||||
# error Boost result_of - do not include this file!
|
||||
#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
|
||||
@ -59,56 +23,174 @@ public:
|
||||
#endif
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
: mpl::if_<
|
||||
mpl::or_< is_pointer<F>, is_member_function_pointer<F> >
|
||||
, boost::detail::result_of_impl<
|
||||
typename remove_cv<F>::type,
|
||||
typename remove_cv<F>::type(BOOST_RESULT_OF_ARGS),
|
||||
, 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),
|
||||
F(BOOST_RESULT_OF_ARGS),
|
||||
(boost::detail::has_result_type<F>::value)> >::type { };
|
||||
#endif
|
||||
|
||||
#undef BOOST_RESULT_OF_ARGS
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
: detail::cpp0x_result_of<F(BOOST_RESULT_OF_ARGS)> { };
|
||||
#endif // BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
#endif // defined(BOOST_HAS_DECLTYPE)
|
||||
#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
: mpl::if_<mpl::or_<detail::has_result_type<F>, detail::has_result<F> >,
|
||||
tr1_result_of<F(BOOST_RESULT_OF_ARGS)>,
|
||||
detail::cpp0x_result_of<F(BOOST_RESULT_OF_ARGS)> >::type { };
|
||||
#endif // BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
|
||||
#if BOOST_PP_ITERATION() >= 1
|
||||
#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
|
||||
|
||||
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>
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct cpp0x_result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
|
||||
: mpl::if_<
|
||||
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
|
||||
{};
|
||||
|
||||
#ifdef BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION());
|
||||
|
||||
template<typename R BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<R(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T))> {
|
||||
R operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T)) const;
|
||||
typedef result_of_private_type const &(*pfn_t)(...);
|
||||
operator pfn_t() const volatile;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION());
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<F *>
|
||||
: BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<F>
|
||||
{};
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<F &>
|
||||
: BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<F>
|
||||
{};
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())
|
||||
: mpl::eval_if<
|
||||
is_class<typename remove_reference<F>::type>,
|
||||
result_of_wrap_callable_class<F>,
|
||||
mpl::identity<BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<typename remove_cv<F>::type> >
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
|
||||
struct BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) {
|
||||
typedef typename BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())<F>::type wrapper_t;
|
||||
static const bool value = (
|
||||
sizeof(result_of_no_type) == sizeof(detail::result_of_is_private_type(
|
||||
(boost::declval<wrapper_t>()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)), result_of_weird_type())
|
||||
))
|
||||
);
|
||||
typedef mpl::bool_<value> type;
|
||||
};
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), true>
|
||||
: lazy_enable_if<
|
||||
BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION())<F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), T)>
|
||||
, cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
|
||||
{
|
||||
typedef decltype(
|
||||
boost::declval<F>()(
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
|
||||
)
|
||||
) type;
|
||||
};
|
||||
|
||||
#else // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)),
|
||||
typename result_of_always_void<decltype(
|
||||
boost::declval<F>()(
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
|
||||
)
|
||||
)>::type> {
|
||||
typedef decltype(
|
||||
boost::declval<F>()(
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
|
||||
)
|
||||
) type;
|
||||
};
|
||||
|
||||
#endif // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
: tr1_result_of<F(BOOST_RESULT_OF_ARGS)> { };
|
||||
#endif
|
||||
|
||||
#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
||||
|
||||
#undef BOOST_RESULT_OF_ARGS
|
||||
|
||||
#if BOOST_PP_ITERATION() >= 1
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of_impl<R (&)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (&)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of_impl<R (T0::*)
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (T0::*)
|
||||
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T)),
|
||||
FArgs, false>
|
||||
{
|
||||
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 (T0::*)
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (T0::*)
|
||||
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
|
||||
const,
|
||||
FArgs, false>
|
||||
@ -116,9 +198,8 @@ struct result_of_impl<R (T0::*)
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of_impl<R (T0::*)
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (T0::*)
|
||||
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
|
||||
volatile,
|
||||
FArgs, false>
|
||||
@ -126,9 +207,8 @@ struct result_of_impl<R (T0::*)
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of_impl<R (T0::*)
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (T0::*)
|
||||
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
|
||||
const volatile,
|
||||
FArgs, false>
|
||||
|
43
include/boost/utility/empty_deleter.hpp
Normal file
43
include/boost/utility/empty_deleter.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright Andrey Semashev 2007 - 2013.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
/*!
|
||||
* \file empty_deleter.hpp
|
||||
* \author Andrey Semashev
|
||||
* \date 22.04.2007
|
||||
*
|
||||
* This header contains an \c empty_deleter implementation. This is an empty
|
||||
* function object that receives a pointer and does nothing with it.
|
||||
* Such empty deletion strategy may be convenient, for example, when
|
||||
* constructing <tt>shared_ptr</tt>s that point to some object that should not be
|
||||
* deleted (i.e. a variable on the stack or some global singleton, like <tt>std::cout</tt>).
|
||||
*/
|
||||
|
||||
#ifndef BOOST_UTILITY_EMPTY_DELETER_HPP_INCLUDED_
|
||||
#define BOOST_UTILITY_EMPTY_DELETER_HPP_INCLUDED_
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
//! A function object that does nothing and can be used as an empty deleter for \c shared_ptr
|
||||
struct empty_deleter
|
||||
{
|
||||
//! Function object result type
|
||||
typedef void result_type;
|
||||
/*!
|
||||
* Does nothing
|
||||
*/
|
||||
void operator() (const volatile void*) const BOOST_NOEXCEPT {}
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_UTILITY_EMPTY_DELETER_HPP_INCLUDED_
|
128
include/boost/utility/explicit_operator_bool.hpp
Normal file
128
include/boost/utility/explicit_operator_bool.hpp
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright Andrey Semashev 2007 - 2013.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
/*!
|
||||
* \file explicit_operator_bool.hpp
|
||||
* \author Andrey Semashev
|
||||
* \date 08.03.2009
|
||||
*
|
||||
* This header defines a compatibility macro that implements an unspecified
|
||||
* \c bool operator idiom, which is superseded with explicit conversion operators in
|
||||
* C++11.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_
|
||||
#define BOOST_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
|
||||
|
||||
/*!
|
||||
* \brief The macro defines an explicit operator of conversion to \c bool
|
||||
*
|
||||
* The macro should be used inside the definition of a class that has to
|
||||
* support the conversion. The class should also implement <tt>operator!</tt>,
|
||||
* in terms of which the conversion operator will be implemented.
|
||||
*/
|
||||
#define BOOST_EXPLICIT_OPERATOR_BOOL()\
|
||||
BOOST_FORCEINLINE explicit operator bool () const\
|
||||
{\
|
||||
return !this->operator! ();\
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief The macro defines a constexpr explicit operator of conversion to \c bool
|
||||
*
|
||||
* The macro should be used inside the definition of a class that has to
|
||||
* support the conversion. The class should also implement <tt>operator!</tt>,
|
||||
* in terms of which the conversion operator will be implemented.
|
||||
*/
|
||||
#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\
|
||||
BOOST_FORCEINLINE BOOST_CONSTEXPR explicit operator bool () const\
|
||||
{\
|
||||
return !this->operator! ();\
|
||||
}
|
||||
|
||||
#else // !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
|
||||
|
||||
#if (defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) && !defined(BOOST_NO_COMPILER_CONFIG)
|
||||
// Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
|
||||
#define BOOST_NO_UNSPECIFIED_BOOL
|
||||
#endif // (defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) && !defined(BOOST_NO_COMPILER_CONFIG)
|
||||
|
||||
#if !defined(BOOST_NO_UNSPECIFIED_BOOL)
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
#if !defined(_MSC_VER) && !defined(__IBMCPP__)
|
||||
|
||||
struct unspecified_bool
|
||||
{
|
||||
// NOTE TO THE USER: If you see this in error messages then you tried
|
||||
// to apply an unsupported operator on the object that supports
|
||||
// explicit conversion to bool.
|
||||
struct OPERATORS_NOT_ALLOWED;
|
||||
static void true_value(OPERATORS_NOT_ALLOWED*) {}
|
||||
};
|
||||
typedef void (*unspecified_bool_type)(unspecified_bool::OPERATORS_NOT_ALLOWED*);
|
||||
|
||||
#else
|
||||
|
||||
// MSVC and VACPP are too eager to convert pointer to function to void* even though they shouldn't
|
||||
struct unspecified_bool
|
||||
{
|
||||
// NOTE TO THE USER: If you see this in error messages then you tried
|
||||
// to apply an unsupported operator on the object that supports
|
||||
// explicit conversion to bool.
|
||||
struct OPERATORS_NOT_ALLOWED;
|
||||
void true_value(OPERATORS_NOT_ALLOWED*) {}
|
||||
};
|
||||
typedef void (unspecified_bool::*unspecified_bool_type)(unspecified_bool::OPERATORS_NOT_ALLOWED*);
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#define BOOST_EXPLICIT_OPERATOR_BOOL()\
|
||||
BOOST_FORCEINLINE operator boost::detail::unspecified_bool_type () const\
|
||||
{\
|
||||
return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\
|
||||
}
|
||||
|
||||
#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\
|
||||
BOOST_FORCEINLINE BOOST_CONSTEXPR operator boost::detail::unspecified_bool_type () const\
|
||||
{\
|
||||
return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\
|
||||
}
|
||||
|
||||
#else // !defined(BOOST_NO_UNSPECIFIED_BOOL)
|
||||
|
||||
#define BOOST_EXPLICIT_OPERATOR_BOOL()\
|
||||
BOOST_FORCEINLINE operator bool () const\
|
||||
{\
|
||||
return !this->operator! ();\
|
||||
}
|
||||
|
||||
#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\
|
||||
BOOST_FORCEINLINE BOOST_CONSTEXPR operator bool () const\
|
||||
{\
|
||||
return !this->operator! ();\
|
||||
}
|
||||
|
||||
#endif // !defined(BOOST_NO_UNSPECIFIED_BOOL)
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
|
||||
|
||||
#endif // BOOST_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_
|
46
include/boost/utility/identity_type.hpp
Normal file
46
include/boost/utility/identity_type.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
/** @file
|
||||
Wrap type expressions with round parenthesis so they can be passed to macros
|
||||
even if they contain commas.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_IDENTITY_TYPE_HPP_
|
||||
#define BOOST_IDENTITY_TYPE_HPP_
|
||||
|
||||
#include <boost/type_traits/function_traits.hpp>
|
||||
|
||||
/**
|
||||
@brief This macro allows to wrap the specified type expression within extra
|
||||
round parenthesis so the type can be passed as a single macro parameter even if
|
||||
it contains commas (not already wrapped within round parenthesis).
|
||||
|
||||
@Params
|
||||
@Param{parenthesized_type,
|
||||
The type expression to be passed as macro parameter wrapped by a single set
|
||||
of round parenthesis <c>(...)</c>.
|
||||
This type expression can contain an arbitrary number of commas.
|
||||
}
|
||||
@EndParams
|
||||
|
||||
This macro works on any C++03 compiler (it does not use variadic macros).
|
||||
|
||||
This macro must be prefixed by <c>typename</c> when used within templates.
|
||||
Note that the compiler will not be able to automatically determine function
|
||||
template parameters when they are wrapped with this macro (these parameters
|
||||
need to be explicitly specified when calling the function template).
|
||||
|
||||
On some compilers (like GCC), using this macro on abstract types requires to
|
||||
add and remove a reference to the specified type.
|
||||
*/
|
||||
#define BOOST_IDENTITY_TYPE(parenthesized_type) \
|
||||
/* must NOT prefix this with `::` to work with parenthesized syntax */ \
|
||||
boost::function_traits< void parenthesized_type >::arg1_type
|
||||
|
||||
#endif // #include guard
|
||||
|
@ -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
|
||||
|
@ -10,34 +10,142 @@
|
||||
#define BOOST_RESULT_OF_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/preprocessor/iteration/iterate.hpp>
|
||||
#include <boost/preprocessor/punctuation/comma_if.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/iteration/iterate.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
|
||||
#include <boost/preprocessor/facilities/intercept.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/mpl/has_xxx.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/type_traits/is_class.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/type_traits/is_member_function_pointer.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/utility/declval.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#ifndef BOOST_RESULT_OF_NUM_ARGS
|
||||
# define BOOST_RESULT_OF_NUM_ARGS 10
|
||||
# define BOOST_RESULT_OF_NUM_ARGS 16
|
||||
#endif
|
||||
|
||||
// Use the decltype-based version of result_of by default if the compiler
|
||||
// supports N3276 <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2011/n3276.pdf>.
|
||||
// The user can force the choice by defining BOOST_RESULT_OF_USE_DECLTYPE,
|
||||
// BOOST_RESULT_OF_USE_TR1, or BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK but not more than one!
|
||||
#if (defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1)) || \
|
||||
(defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)) || \
|
||||
(defined(BOOST_RESULT_OF_USE_TR1) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK))
|
||||
# error More than one of BOOST_RESULT_OF_USE_DECLTYPE, BOOST_RESULT_OF_USE_TR1 and \
|
||||
BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK cannot be defined at the same time.
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) && defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE)
|
||||
# error Cannot fallback to decltype if BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE is not defined.
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_RESULT_OF_USE_TR1
|
||||
# ifndef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
# ifndef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
# ifndef BOOST_NO_CXX11_DECLTYPE_N3276 // this implies !defined(BOOST_NO_CXX11_DECLTYPE)
|
||||
# define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
# else
|
||||
# define BOOST_RESULT_OF_USE_TR1
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
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;
|
||||
BOOST_MPL_HAS_XXX_TEMPLATE_DEF(result)
|
||||
|
||||
template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_impl;
|
||||
|
||||
template<typename F> struct cpp0x_result_of;
|
||||
|
||||
#ifdef BOOST_NO_SFINAE_EXPR
|
||||
|
||||
// There doesn't seem to be any other way to turn this off such that the presence of
|
||||
// the user-defined operator,() below doesn't cause spurious warning all over the place,
|
||||
// so unconditionally turn it off.
|
||||
#if BOOST_MSVC
|
||||
# pragma warning(disable: 4913) // user defined binary operator ',' exists but no overload could convert all operands, default built-in binary operator ',' used
|
||||
#endif
|
||||
|
||||
struct result_of_private_type {};
|
||||
|
||||
struct result_of_weird_type {
|
||||
friend result_of_private_type operator,(result_of_private_type, result_of_weird_type);
|
||||
};
|
||||
|
||||
typedef char result_of_yes_type; // sizeof(result_of_yes_type) == 1
|
||||
typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type) == 2
|
||||
|
||||
template<typename T>
|
||||
result_of_no_type result_of_is_private_type(T const &);
|
||||
result_of_yes_type result_of_is_private_type(result_of_private_type);
|
||||
|
||||
template<typename C>
|
||||
struct result_of_callable_class : C {
|
||||
result_of_callable_class();
|
||||
typedef result_of_private_type const &(*pfn_t)(...);
|
||||
operator pfn_t() const volatile;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class {
|
||||
typedef result_of_callable_class<C> type;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class<C const> {
|
||||
typedef result_of_callable_class<C> const type;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class<C volatile> {
|
||||
typedef result_of_callable_class<C> volatile type;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class<C const volatile> {
|
||||
typedef result_of_callable_class<C> const volatile type;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class<C &> {
|
||||
typedef typename result_of_wrap_callable_class<C>::type &type;
|
||||
};
|
||||
|
||||
template<typename F, bool TestCallability = true> struct cpp0x_result_of_impl;
|
||||
|
||||
#else // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename T>
|
||||
struct result_of_always_void
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template<typename F, typename Enable = void> struct cpp0x_result_of_impl {};
|
||||
|
||||
#endif // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename F>
|
||||
struct result_of_void_impl
|
||||
@ -60,10 +168,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,7 +187,7 @@ 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
|
||||
|
536
include/boost/utility/string_ref.hpp
Normal file
536
include/boost/utility/string_ref.hpp
Normal file
@ -0,0 +1,536 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2012-2012.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
For more information, see http://www.boost.org
|
||||
|
||||
Based on the StringRef implementation in LLVM (http://llvm.org) and
|
||||
N3422 by Jeffrey Yasskin
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BOOST_STRING_REF_HPP
|
||||
#define BOOST_STRING_REF_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/utility/string_ref_fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
// A helper functor because sometimes we don't have lambdas
|
||||
template <typename charT, typename traits>
|
||||
class string_ref_traits_eq {
|
||||
public:
|
||||
string_ref_traits_eq ( charT ch ) : ch_(ch) {}
|
||||
bool operator () ( charT val ) const { return traits::eq ( ch_, val ); }
|
||||
charT ch_;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
class basic_string_ref {
|
||||
public:
|
||||
// types
|
||||
typedef charT value_type;
|
||||
typedef const charT* pointer;
|
||||
typedef const charT& reference;
|
||||
typedef const charT& const_reference;
|
||||
typedef pointer const_iterator; // impl-defined
|
||||
typedef const_iterator iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
typedef const_reverse_iterator reverse_iterator;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);
|
||||
|
||||
// construct/copy
|
||||
BOOST_CONSTEXPR basic_string_ref ()
|
||||
: ptr_(NULL), len_(0) {}
|
||||
|
||||
BOOST_CONSTEXPR basic_string_ref (const basic_string_ref &rhs)
|
||||
: ptr_(rhs.ptr_), len_(rhs.len_) {}
|
||||
|
||||
basic_string_ref& operator=(const basic_string_ref &rhs) {
|
||||
ptr_ = rhs.ptr_;
|
||||
len_ = rhs.len_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_string_ref(const charT* str)
|
||||
: ptr_(str), len_(traits::length(str)) {}
|
||||
|
||||
template<typename Allocator>
|
||||
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str)
|
||||
: ptr_(str.data()), len_(str.length()) {}
|
||||
|
||||
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len)
|
||||
: ptr_(str), len_(len) {}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
|
||||
template<typename Allocator>
|
||||
explicit operator std::basic_string<charT, traits, Allocator>() const {
|
||||
return std::basic_string<charT, traits, Allocator> ( ptr_, len_ );
|
||||
}
|
||||
#endif
|
||||
|
||||
std::basic_string<charT, traits> to_string () const {
|
||||
return std::basic_string<charT, traits> ( ptr_, len_ );
|
||||
}
|
||||
|
||||
// iterators
|
||||
BOOST_CONSTEXPR const_iterator begin() const { return ptr_; }
|
||||
BOOST_CONSTEXPR const_iterator cbegin() const { return ptr_; }
|
||||
BOOST_CONSTEXPR const_iterator end() const { return ptr_ + len_; }
|
||||
BOOST_CONSTEXPR const_iterator cend() const { return ptr_ + len_; }
|
||||
const_reverse_iterator rbegin() const { return const_reverse_iterator (end()); }
|
||||
const_reverse_iterator crbegin() const { return const_reverse_iterator (end()); }
|
||||
const_reverse_iterator rend() const { return const_reverse_iterator (begin()); }
|
||||
const_reverse_iterator crend() const { return const_reverse_iterator (begin()); }
|
||||
|
||||
// capacity
|
||||
BOOST_CONSTEXPR size_type size() const { return len_; }
|
||||
BOOST_CONSTEXPR size_type length() const { return len_; }
|
||||
BOOST_CONSTEXPR size_type max_size() const { return len_; }
|
||||
BOOST_CONSTEXPR bool empty() const { return len_ == 0; }
|
||||
|
||||
// element access
|
||||
BOOST_CONSTEXPR const charT& operator[](size_type pos) const { return ptr_[pos]; }
|
||||
|
||||
const charT& at(size_t pos) const {
|
||||
if ( pos >= len_ )
|
||||
BOOST_THROW_EXCEPTION( std::out_of_range ( "boost::string_ref::at" ) );
|
||||
return ptr_[pos];
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR const charT& front() const { return ptr_[0]; }
|
||||
BOOST_CONSTEXPR const charT& back() const { return ptr_[len_-1]; }
|
||||
BOOST_CONSTEXPR const charT* data() const { return ptr_; }
|
||||
|
||||
// modifiers
|
||||
void clear() { len_ = 0; }
|
||||
void remove_prefix(size_type n) {
|
||||
if ( n > len_ )
|
||||
n = len_;
|
||||
ptr_ += n;
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
void remove_suffix(size_type n) {
|
||||
if ( n > len_ )
|
||||
n = len_;
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
|
||||
// basic_string_ref string operations
|
||||
basic_string_ref substr(size_type pos, size_type n=npos) const {
|
||||
if ( pos > size())
|
||||
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_ref::substr" ) );
|
||||
if ( n == npos || pos + n > size())
|
||||
n = size () - pos;
|
||||
return basic_string_ref ( data() + pos, n );
|
||||
}
|
||||
|
||||
int compare(basic_string_ref x) const {
|
||||
const int cmp = traits::compare ( ptr_, x.ptr_, (std::min)(len_, x.len_));
|
||||
return cmp != 0 ? cmp : ( len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1 );
|
||||
}
|
||||
|
||||
bool starts_with(charT c) const { return !empty() && traits::eq ( c, front()); }
|
||||
bool starts_with(basic_string_ref x) const {
|
||||
return len_ >= x.len_ && traits::compare ( ptr_, x.ptr_, x.len_ ) == 0;
|
||||
}
|
||||
|
||||
bool ends_with(charT c) const { return !empty() && traits::eq ( c, back()); }
|
||||
bool ends_with(basic_string_ref x) const {
|
||||
return len_ >= x.len_ && traits::compare ( ptr_ + len_ - x.len_, x.ptr_, x.len_ ) == 0;
|
||||
}
|
||||
|
||||
size_type find(basic_string_ref s) const {
|
||||
const_iterator iter = std::search ( this->cbegin (), this->cend (),
|
||||
s.cbegin (), s.cend (), traits::eq );
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
|
||||
size_type find(charT c) const {
|
||||
const_iterator iter = std::find_if ( this->cbegin (), this->cend (),
|
||||
detail::string_ref_traits_eq<charT, traits> ( c ));
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
|
||||
size_type rfind(basic_string_ref s) const {
|
||||
const_reverse_iterator iter = std::search ( this->crbegin (), this->crend (),
|
||||
s.crbegin (), s.crend (), traits::eq );
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
|
||||
}
|
||||
|
||||
size_type rfind(charT c) const {
|
||||
const_reverse_iterator iter = std::find_if ( this->crbegin (), this->crend (),
|
||||
detail::string_ref_traits_eq<charT, traits> ( c ));
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
|
||||
}
|
||||
|
||||
size_type find_first_of(charT c) const { return find (c); }
|
||||
size_type find_last_of (charT c) const { return rfind (c); }
|
||||
|
||||
size_type find_first_of(basic_string_ref s) const {
|
||||
const_iterator iter = std::find_first_of
|
||||
( this->cbegin (), this->cend (), s.cbegin (), s.cend (), traits::eq );
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
|
||||
size_type find_last_of(basic_string_ref s) const {
|
||||
const_reverse_iterator iter = std::find_first_of
|
||||
( this->crbegin (), this->crend (), s.cbegin (), s.cend (), traits::eq );
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter);
|
||||
}
|
||||
|
||||
size_type find_first_not_of(basic_string_ref s) const {
|
||||
const_iterator iter = find_not_of ( this->cbegin (), this->cend (), s );
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
|
||||
size_type find_first_not_of(charT c) const {
|
||||
for ( const_iterator iter = this->cbegin (); iter != this->cend (); ++iter )
|
||||
if ( !traits::eq ( c, *iter ))
|
||||
return std::distance ( this->cbegin (), iter );
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_type find_last_not_of(basic_string_ref s) const {
|
||||
const_reverse_iterator iter = find_not_of ( this->crbegin (), this->crend (), s );
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
|
||||
}
|
||||
|
||||
size_type find_last_not_of(charT c) const {
|
||||
for ( const_reverse_iterator iter = this->crbegin (); iter != this->crend (); ++iter )
|
||||
if ( !traits::eq ( c, *iter ))
|
||||
return reverse_distance ( this->crbegin (), iter );
|
||||
return npos;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename r_iter>
|
||||
size_type reverse_distance ( r_iter first, r_iter last ) const {
|
||||
return len_ - 1 - std::distance ( first, last );
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
Iterator find_not_of ( Iterator first, Iterator last, basic_string_ref s ) const {
|
||||
for ( ; first != last ; ++first )
|
||||
if ( 0 == traits::find ( s.ptr_, s.len_, *first ))
|
||||
return first;
|
||||
return last;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const charT *ptr_;
|
||||
std::size_t len_;
|
||||
};
|
||||
|
||||
|
||||
// Comparison operators
|
||||
// Equality
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator==(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
|
||||
if ( x.size () != y.size ()) return false;
|
||||
return x.compare(y) == 0;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator==(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
|
||||
return x == basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator==(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) == y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator==(basic_string_ref<charT, traits> x, const charT * y) {
|
||||
return x == basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator==(const charT * x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) == y;
|
||||
}
|
||||
|
||||
// Inequality
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator!=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
|
||||
if ( x.size () != y.size ()) return true;
|
||||
return x.compare(y) != 0;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator!=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
|
||||
return x != basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator!=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) != y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator!=(basic_string_ref<charT, traits> x, const charT * y) {
|
||||
return x != basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator!=(const charT * x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) != y;
|
||||
}
|
||||
|
||||
// Less than
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
|
||||
return x.compare(y) < 0;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
|
||||
return x < basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) < y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<(basic_string_ref<charT, traits> x, const charT * y) {
|
||||
return x < basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<(const charT * x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) < y;
|
||||
}
|
||||
|
||||
// Greater than
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
|
||||
return x.compare(y) > 0;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
|
||||
return x > basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) > y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>(basic_string_ref<charT, traits> x, const charT * y) {
|
||||
return x > basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>(const charT * x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) > y;
|
||||
}
|
||||
|
||||
// Less than or equal to
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
|
||||
return x.compare(y) <= 0;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
|
||||
return x <= basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) <= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<=(basic_string_ref<charT, traits> x, const charT * y) {
|
||||
return x <= basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<=(const charT * x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) <= y;
|
||||
}
|
||||
|
||||
// Greater than or equal to
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
|
||||
return x.compare(y) >= 0;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
|
||||
return x >= basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) >= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>=(basic_string_ref<charT, traits> x, const charT * y) {
|
||||
return x >= basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>=(const charT * x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) >= y;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class charT, class traits>
|
||||
inline void insert_fill_chars(std::basic_ostream<charT, traits>& os, std::size_t n) {
|
||||
enum { chunk_size = 8 };
|
||||
charT fill_chars[chunk_size];
|
||||
std::fill_n(fill_chars, static_cast< std::size_t >(chunk_size), os.fill());
|
||||
for (; n >= chunk_size && os.good(); n -= chunk_size)
|
||||
os.write(fill_chars, static_cast< std::size_t >(chunk_size));
|
||||
if (n > 0 && os.good())
|
||||
os.write(fill_chars, n);
|
||||
}
|
||||
|
||||
template<class charT, class traits>
|
||||
void insert_aligned(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) {
|
||||
const std::size_t size = str.size();
|
||||
const std::size_t alignment_size = static_cast< std::size_t >(os.width()) - size;
|
||||
const bool align_left = (os.flags() & std::basic_ostream<charT, traits>::adjustfield) == std::basic_ostream<charT, traits>::left;
|
||||
if (!align_left) {
|
||||
detail::insert_fill_chars(os, alignment_size);
|
||||
if (os.good())
|
||||
os.write(str.data(), size);
|
||||
}
|
||||
else {
|
||||
os.write(str.data(), size);
|
||||
if (os.good())
|
||||
detail::insert_fill_chars(os, alignment_size);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Inserter
|
||||
template<class charT, class traits>
|
||||
inline std::basic_ostream<charT, traits>&
|
||||
operator<<(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) {
|
||||
if (os.good()) {
|
||||
const std::size_t size = str.size();
|
||||
const std::size_t w = static_cast< std::size_t >(os.width());
|
||||
if (w <= size)
|
||||
os.write(str.data(), size);
|
||||
else
|
||||
detail::insert_aligned(os, str);
|
||||
os.width(0);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// numeric conversions
|
||||
//
|
||||
// These are short-term implementations.
|
||||
// In a production environment, I would rather avoid the copying.
|
||||
//
|
||||
inline int stoi (string_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoi ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline long stol (string_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stol ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long stoul (string_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoul ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline long long stoll (string_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoll ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long long stoull (string_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoull ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline float stof (string_ref str, size_t* idx=0) {
|
||||
return std::stof ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline double stod (string_ref str, size_t* idx=0) {
|
||||
return std::stod ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline long double stold (string_ref str, size_t* idx=0) {
|
||||
return std::stold ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline int stoi (wstring_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoi ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline long stol (wstring_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stol ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long stoul (wstring_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoul ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline long long stoll (wstring_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoll ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long long stoull (wstring_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoull ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline float stof (wstring_ref str, size_t* idx=0) {
|
||||
return std::stof ( std::wstring(str), idx );
|
||||
}
|
||||
|
||||
inline double stod (wstring_ref str, size_t* idx=0) {
|
||||
return std::stod ( std::wstring(str), idx );
|
||||
}
|
||||
|
||||
inline long double stold (wstring_ref str, size_t* idx=0) {
|
||||
return std::stold ( std::wstring(str), idx );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
namespace std {
|
||||
// Hashing
|
||||
template<> struct hash<boost::string_ref>;
|
||||
template<> struct hash<boost::u16string_ref>;
|
||||
template<> struct hash<boost::u32string_ref>;
|
||||
template<> struct hash<boost::wstring_ref>;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
37
include/boost/utility/string_ref_fwd.hpp
Normal file
37
include/boost/utility/string_ref_fwd.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2012-2012.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
For more information, see http://www.boost.org
|
||||
|
||||
Based on the StringRef implementation in LLVM (http://llvm.org) and
|
||||
N3422 by Jeffrey Yasskin
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BOOST_STRING_REF_FWD_HPP
|
||||
#define BOOST_STRING_REF_FWD_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<typename charT, typename traits = std::char_traits<charT> > class basic_string_ref;
|
||||
typedef basic_string_ref<char, std::char_traits<char> > string_ref;
|
||||
typedef basic_string_ref<wchar_t, std::char_traits<wchar_t> > wstring_ref;
|
||||
|
||||
#ifndef BOOST_NO_CXX11_CHAR16_T
|
||||
typedef basic_string_ref<char16_t, std::char_traits<char16_t> > u16string_ref;
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_CHAR32_T
|
||||
typedef basic_string_ref<char32_t, std::char_traits<char32_t> > u32string_ref;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -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
|
||||
|
@ -9,6 +9,8 @@
|
||||
// 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
|
||||
@ -20,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>
|
||||
@ -28,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
|
||||
@ -40,6 +72,18 @@ class value_initialized
|
||||
typename
|
||||
#endif
|
||||
remove_const<T>::type data;
|
||||
|
||||
wrapper()
|
||||
:
|
||||
data()
|
||||
{
|
||||
}
|
||||
|
||||
wrapper(T const & arg)
|
||||
:
|
||||
data(arg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
mutable
|
||||
@ -55,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 );
|
||||
@ -86,7 +125,7 @@ class value_initialized
|
||||
return *this;
|
||||
}
|
||||
|
||||
~value_initialized()
|
||||
~initialized()
|
||||
{
|
||||
wrapper_address()->wrapper::~wrapper();
|
||||
}
|
||||
@ -101,17 +140,81 @@ class value_initialized
|
||||
return wrapper_address()->data;
|
||||
}
|
||||
|
||||
void swap(value_initialized & arg)
|
||||
void swap(initialized & arg)
|
||||
{
|
||||
::boost::swap( this->data(), arg.data() );
|
||||
}
|
||||
|
||||
operator T const &() const { return this->data(); }
|
||||
operator T const &() const
|
||||
{
|
||||
return wrapper_address()->data;
|
||||
}
|
||||
|
||||
operator T&() { return this->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>
|
||||
@ -119,6 +222,7 @@ T const& get ( value_initialized<T> const& x )
|
||||
{
|
||||
return x.data() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T& get ( value_initialized<T>& x )
|
||||
{
|
||||
@ -138,7 +242,7 @@ class initialized_value_t
|
||||
|
||||
template <class T> operator T() const
|
||||
{
|
||||
return get( value_initialized<T>() );
|
||||
return initialized<T>().data();
|
||||
}
|
||||
};
|
||||
|
||||
@ -147,5 +251,8 @@ initialized_value_t const initialized_value = {} ;
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
16
index.html
16
index.html
@ -14,20 +14,30 @@
|
||||
<p>But that doesn't mean there isn't useful stuff here. Take a look:</p>
|
||||
<blockquote>
|
||||
<p>
|
||||
<a href="utility.htm#addressof">addressof</a><br>
|
||||
<a href="assert.html">assert</a><br>
|
||||
<a href="base_from_member.html">base_from_member</a><br>
|
||||
<a href="utility.htm#BOOST_BINARY">BOOST_BINARY</a><br>
|
||||
<a href="call_traits.htm">call_traits</a><br>
|
||||
<a href="checked_delete.html">checked_delete</a><br>
|
||||
<a href="compressed_pair.htm">compressed_pair</a><br>
|
||||
<a href="current_function.html">current_function</a><br>
|
||||
<a href="doc/html/declval.html">declval</a><br>
|
||||
<a href="enable_if.html">enable_if</a><br>
|
||||
<a href="iterator_adaptors.htm">iterator_adaptors</a><br>
|
||||
<a href="generator_iterator.htm">generator iterator adaptors</a><br>
|
||||
<a href="in_place_factories.html">in_place_factory</a><br>
|
||||
<a href="iterator_adaptors.htm">iterator_adaptors</a><br>
|
||||
<a href="generator_iterator.htm">generator iterator adaptors</a><br>
|
||||
<a href="utility.htm#functions_next_prior">next/prior</a><br>
|
||||
<a href="utility.htm#Class_noncopyable">noncopyable</a><br>
|
||||
<a href="operators.htm">operators</a><br>
|
||||
<a href="utility.htm#result_of">result_of</a><br>
|
||||
<a href="swap.html">swap</a><br>
|
||||
<a href="throw_exception.html">throw_exception</a><br>
|
||||
<a href="utility.htm">utility</a><br>
|
||||
<a href="value_init.htm">value_init</a></p>
|
||||
<a href="doc/html/string_ref.html">string_ref</a><br>
|
||||
<a href="value_init.htm">value_init</a>
|
||||
<a href="doc/html/explicit_operator_bool.html">BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL</a><br>
|
||||
</p>
|
||||
</blockquote>
|
||||
<hr>
|
||||
<p>© Copyright Beman Dawes, 2001</p>
|
||||
|
116
initialized_test.cpp
Normal file
116
initialized_test.cpp
Normal 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();
|
||||
}
|
33
initialized_test_fail1.cpp
Normal file
33
initialized_test_fail1.cpp
Normal 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;
|
||||
}
|
37
initialized_test_fail2.cpp
Normal file
37
initialized_test_fail2.cpp
Normal 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;
|
||||
}
|
@ -1 +0,0 @@
|
||||
boost_module(utility DEPENDS iterator exception detail )
|
@ -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() {}
|
||||
|
@ -7,7 +7,11 @@
|
||||
</head>
|
||||
<body>
|
||||
<!-- Page header -->
|
||||
<h2>
|
||||
<img src="../../boost.png" alt="C++ Boost" align="middle" width="277" height="86"/>
|
||||
Header <<a href="../../boost/swap.hpp">boost/swap.hpp</a>>
|
||||
</h2>
|
||||
|
||||
<h1>Swap</h1>
|
||||
|
||||
<p>
|
||||
@ -84,9 +88,9 @@
|
||||
|
||||
<!-- Copyright info -->
|
||||
<hr/>
|
||||
<p>Revised: 15 November 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 <<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>>.)
|
||||
</p>
|
||||
|
||||
|
@ -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,8 +17,8 @@
|
||||
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;
|
||||
|
@ -1,38 +0,0 @@
|
||||
boost_additional_test_dependencies(utility BOOST_DEPENDS test)
|
||||
|
||||
boost_test_run(addressof_test ../addressof_test.cpp)
|
||||
boost_test_run(assert_test ../assert_test.cpp)
|
||||
boost_test_run(base_from_member_test ../base_from_member_test.cpp)
|
||||
boost_test_run(binary_search_test ../binary_search_test.cpp)
|
||||
boost_test_run(call_traits_test ../call_traits_test.cpp ARGS -u)
|
||||
boost_test_compile_fail(checked_delete_test ../checked_delete_test.cpp)
|
||||
boost_test_run(compressed_pair_test
|
||||
../compressed_pair_test
|
||||
DEPENDS boost_test_exec_monitor)
|
||||
boost_test_run(current_function_test ../current_function_test.cpp)
|
||||
boost_test_run(iterators_test
|
||||
../iterators_test.cpp
|
||||
DEPENDS boost_test_exec_monitor)
|
||||
boost_test_run(next_prior_test DEPENDS boost_test_exec_monitor)
|
||||
boost_test_compile_fail(noncopyable_test ../noncopyable_test.cpp)
|
||||
boost_test_run(numeric_traits_test ../numeric_traits_test.cpp)
|
||||
if (${CMAKE_SYSTEM} MATCHES "FreeBSD-.*")
|
||||
boost_test_compile_fail("operators_test_compilerbug")
|
||||
elseif(${CMAKE_SYSTEM} MATCHES "FreeBSD-.*")
|
||||
boost_test_run(operators_test
|
||||
../operators_test.cpp
|
||||
DEPENDS boost_test_exec_monitor)
|
||||
endif(${CMAKE_SYSTEM} MATCHES "FreeBSD-.*")
|
||||
boost_test_compile(ref_ct_test ../ref_ct_test.cpp)
|
||||
boost_test_run(ref_test
|
||||
../ref_test.cpp
|
||||
DEPENDS boost_test_exec_monitor)
|
||||
boost_test_compile(result_of_test)
|
||||
boost_test_run(shared_iterator_test ../shared_iterator_test.cpp)
|
||||
boost_test_run(value_init_test ../value_init_test.cpp)
|
||||
boost_test_compile_fail(value_init_test_fail1
|
||||
../value_init_test_fail1.cpp)
|
||||
boost_test_compile_fail(value_init_test_fail2
|
||||
../value_init_test_fail2.cpp)
|
||||
boost_test_compile_fail(value_init_test_fail3
|
||||
../value_init_test_fail3.cpp)
|
@ -8,6 +8,11 @@
|
||||
# bring in rules for testing
|
||||
import testing ;
|
||||
|
||||
alias unit_test_framework
|
||||
: # sources
|
||||
/boost//unit_test_framework
|
||||
;
|
||||
|
||||
# Please keep the tests ordered by filename
|
||||
test-suite utility
|
||||
:
|
||||
@ -31,10 +36,22 @@ test-suite utility
|
||||
[ run ../ref_test.cpp ../../test/build//boost_test_exec_monitor/<link>static ]
|
||||
[ compile result_of_test.cpp ]
|
||||
[ run ../shared_iterator_test.cpp ]
|
||||
[ run string_ref_test1.cpp unit_test_framework ]
|
||||
[ run string_ref_test2.cpp unit_test_framework ]
|
||||
[ run string_ref_test_io.cpp unit_test_framework ]
|
||||
[ run ../value_init_test.cpp ]
|
||||
[ run ../value_init_workaround_test.cpp ]
|
||||
[ run ../initialized_test.cpp ]
|
||||
[ compile-fail ../value_init_test_fail1.cpp ]
|
||||
[ compile-fail ../value_init_test_fail2.cpp ]
|
||||
[ compile-fail ../value_init_test_fail3.cpp ]
|
||||
[ compile-fail ../initialized_test_fail1.cpp ]
|
||||
[ compile-fail ../initialized_test_fail2.cpp ]
|
||||
[ run ../verify_test.cpp ]
|
||||
[ run explicit_operator_bool.cpp ]
|
||||
[ compile-fail explicit_operator_bool_compile_fail_conv_int.cpp ]
|
||||
[ compile-fail explicit_operator_bool_compile_fail_conv_pvoid.cpp ]
|
||||
[ compile-fail explicit_operator_bool_compile_fail_delete.cpp ]
|
||||
[ compile-fail explicit_operator_bool_compile_fail_shift.cpp ]
|
||||
;
|
||||
|
||||
|
54
test/explicit_operator_bool.cpp
Normal file
54
test/explicit_operator_bool.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright Andrey Semashev 2007 - 2013.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
/*!
|
||||
* \file explicit_operator_bool_compile.cpp
|
||||
* \author Andrey Semashev
|
||||
* \date 17.07.2010
|
||||
*
|
||||
* \brief This test checks that explicit operator bool can be used in
|
||||
* the valid contexts.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE explicit_operator_bool_compile
|
||||
|
||||
#include <boost/utility/explicit_operator_bool.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
// A test object that has the operator of explicit conversion to bool
|
||||
struct checkable1
|
||||
{
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()
|
||||
bool operator! () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct checkable2
|
||||
{
|
||||
BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()
|
||||
BOOST_CONSTEXPR bool operator! () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
checkable1 val1;
|
||||
if (val1)
|
||||
{
|
||||
checkable2 val2;
|
||||
if (val2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
40
test/explicit_operator_bool_compile_fail_conv_int.cpp
Normal file
40
test/explicit_operator_bool_compile_fail_conv_int.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright Andrey Semashev 2007 - 2013.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
/*!
|
||||
* \file explicit_operator_bool_compile_fail_conv_int.cpp
|
||||
* \author Andrey Semashev
|
||||
* \date 17.07.2010
|
||||
*
|
||||
* \brief This test checks that explicit operator bool cannot be used in
|
||||
* an unintended context.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE explicit_operator_bool_compile_fail_conv_int
|
||||
|
||||
#include <boost/utility/explicit_operator_bool.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
// A test object that has the operator of explicit conversion to bool
|
||||
struct checkable
|
||||
{
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()
|
||||
bool operator! () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
checkable val;
|
||||
int n = val;
|
||||
|
||||
return 0;
|
||||
}
|
40
test/explicit_operator_bool_compile_fail_conv_pvoid.cpp
Normal file
40
test/explicit_operator_bool_compile_fail_conv_pvoid.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright Andrey Semashev 2007 - 2013.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
/*!
|
||||
* \file explicit_operator_bool_compile_fail_conv_pvoid.cpp
|
||||
* \author Andrey Semashev
|
||||
* \date 17.07.2010
|
||||
*
|
||||
* \brief This test checks that explicit operator bool cannot be used in
|
||||
* an unintended context.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE explicit_operator_bool_compile_fail_conv_pvoid
|
||||
|
||||
#include <boost/utility/explicit_operator_bool.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
// A test object that has the operator of explicit conversion to bool
|
||||
struct checkable
|
||||
{
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()
|
||||
bool operator! () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
checkable val;
|
||||
void* p = val;
|
||||
|
||||
return 0;
|
||||
}
|
40
test/explicit_operator_bool_compile_fail_delete.cpp
Normal file
40
test/explicit_operator_bool_compile_fail_delete.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright Andrey Semashev 2007 - 2013.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
/*!
|
||||
* \file explicit_operator_bool_compile_fail_delete.cpp
|
||||
* \author Andrey Semashev
|
||||
* \date 17.07.2010
|
||||
*
|
||||
* \brief This test checks that explicit operator bool cannot be used in
|
||||
* an unintended context.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE util_explicit_operator_bool_delete
|
||||
|
||||
#include <boost/utility/explicit_operator_bool.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
// A test object that has the operator of explicit conversion to bool
|
||||
struct checkable
|
||||
{
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()
|
||||
bool operator! () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
checkable val;
|
||||
delete val;
|
||||
|
||||
return 0;
|
||||
}
|
40
test/explicit_operator_bool_compile_fail_shift.cpp
Normal file
40
test/explicit_operator_bool_compile_fail_shift.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright Andrey Semashev 2007 - 2013.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
/*!
|
||||
* \file explicit_operator_bool_compile_fail_shift.cpp
|
||||
* \author Andrey Semashev
|
||||
* \date 17.07.2010
|
||||
*
|
||||
* \brief This test checks that explicit operator bool cannot be used in
|
||||
* an unintended context.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE explicit_operator_bool_compile_fail_shift
|
||||
|
||||
#include <boost/utility/explicit_operator_bool.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
// A test object that has the operator of explicit conversion to bool
|
||||
struct checkable
|
||||
{
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()
|
||||
bool operator! () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
checkable val;
|
||||
val << 2;
|
||||
|
||||
return 0;
|
||||
}
|
0
test/next_prior_test.cpp
Executable file → Normal file
0
test/next_prior_test.cpp
Executable file → Normal file
@ -5,6 +5,14 @@
|
||||
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Examples:
|
||||
// To run the default test:
|
||||
// $ cd libs/utility/test && bjam
|
||||
// To test decltype on g++ 2.7:
|
||||
// $ cd libs/utility/test && bjam cxxflags="-std=c++11 -D BOOST_RESULT_OF_USE_DECLTYPE"
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// For more information, see http://www.boost.org/libs/utility
|
||||
#include <boost/utility/result_of.hpp>
|
||||
#include <utility>
|
||||
@ -60,6 +68,9 @@ struct int_result_type_and_float_result_of_and_char_return_template
|
||||
char operator()(char);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct cv_overload_check {};
|
||||
|
||||
struct result_of_member_function_template
|
||||
{
|
||||
template<typename F> struct result;
|
||||
@ -67,13 +78,13 @@ struct result_of_member_function_template
|
||||
template<typename This, typename That> struct result<This(That)> { typedef That type; };
|
||||
template<class T> typename result<result_of_member_function_template(T)>::type operator()(T);
|
||||
|
||||
template<typename This, typename That> struct result<const This(That)> { typedef const That type; };
|
||||
template<typename This, typename That> struct result<const This(That)> { typedef cv_overload_check<const That> type; };
|
||||
template<class T> typename result<const result_of_member_function_template(T)>::type operator()(T) const;
|
||||
|
||||
template<typename This, typename That> struct result<volatile This(That)> { typedef volatile That type; };
|
||||
template<typename This, typename That> struct result<volatile This(That)> { typedef cv_overload_check<volatile That> type; };
|
||||
template<class T> typename result<volatile result_of_member_function_template(T)>::type operator()(T) volatile;
|
||||
|
||||
template<typename This, typename That> struct result<const volatile This(That)> { typedef const volatile That type; };
|
||||
template<typename This, typename That> struct result<const volatile This(That)> { typedef cv_overload_check<const volatile That> type; };
|
||||
template<class T> typename result<const volatile result_of_member_function_template(T)>::type operator()(T) const volatile;
|
||||
|
||||
template<typename This, typename That> struct result<This(That &, That)> { typedef That & type; };
|
||||
@ -89,25 +100,62 @@ struct result_of_member_function_template
|
||||
template<class T> typename result<result_of_member_function_template(T const volatile &, T)>::type operator()(T const volatile &, T);
|
||||
};
|
||||
|
||||
struct no_result_type_or_result_of
|
||||
struct no_result_type_or_result
|
||||
{
|
||||
int operator()(double);
|
||||
short operator()(double) const;
|
||||
unsigned int operator()();
|
||||
unsigned short operator()() volatile;
|
||||
const unsigned short operator()() const volatile;
|
||||
short operator()(double);
|
||||
cv_overload_check<const short> operator()(double) const;
|
||||
cv_overload_check<volatile short> operator()(double) volatile;
|
||||
cv_overload_check<const volatile short> operator()(double) const volatile;
|
||||
int operator()();
|
||||
cv_overload_check<const int> operator()() const;
|
||||
cv_overload_check<volatile int> operator()() volatile;
|
||||
cv_overload_check<const volatile int> operator()() const volatile;
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
short operator()(int&&);
|
||||
int operator()(int&);
|
||||
long operator()(int const&);
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct no_result_type_or_result_of_template
|
||||
struct no_result_type_or_result_template
|
||||
{
|
||||
int operator()(double);
|
||||
short operator()(double) const;
|
||||
unsigned int operator()();
|
||||
unsigned short operator()() volatile;
|
||||
const unsigned short operator()() const volatile;
|
||||
short operator()(double);
|
||||
cv_overload_check<const short> operator()(double) const;
|
||||
cv_overload_check<volatile short> operator()(double) volatile;
|
||||
cv_overload_check<const volatile short> operator()(double) const volatile;
|
||||
int operator()();
|
||||
cv_overload_check<const int> operator()() const;
|
||||
cv_overload_check<volatile int> operator()() volatile;
|
||||
cv_overload_check<const volatile int> operator()() const volatile;
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
short operator()(int&&);
|
||||
int operator()(int&);
|
||||
long operator()(int const&);
|
||||
#endif
|
||||
};
|
||||
|
||||
// sfinae_tests are derived from example code from Joel de Guzman,
|
||||
// which demonstrated the interaction between result_of and SFINAE.
|
||||
template <typename F, typename Arg>
|
||||
typename boost::result_of<F(Arg const&)>::type
|
||||
sfinae_test(F f, Arg const& arg)
|
||||
{
|
||||
return f(arg);
|
||||
}
|
||||
|
||||
template <typename F, typename Arg>
|
||||
typename boost::result_of<F(Arg&)>::type
|
||||
sfinae_test(F f, Arg& arg)
|
||||
{
|
||||
return f(arg);
|
||||
}
|
||||
|
||||
int sfinae_test_f(int& i)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
struct X {};
|
||||
|
||||
int main()
|
||||
@ -118,6 +166,10 @@ int main()
|
||||
typedef int (&func_ref)(float, double);
|
||||
typedef int (*func_ptr_0)();
|
||||
typedef int (&func_ref_0)();
|
||||
typedef void (*func_ptr_void)(float, double);
|
||||
typedef void (&func_ref_void)(float, double);
|
||||
typedef void (*func_ptr_void_0)();
|
||||
typedef void (&func_ref_void_0)();
|
||||
typedef int (X::*mem_func_ptr)(float);
|
||||
typedef int (X::*mem_func_ptr_c)(float) const;
|
||||
typedef int (X::*mem_func_ptr_v)(float) volatile;
|
||||
@ -131,9 +183,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)
|
||||
// of nullary function objects unless they exposed a result_type.
|
||||
#if defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(void)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of(void)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<int_result_of_template<void>(void)>::type, int>::value));
|
||||
@ -149,7 +213,7 @@ int main()
|
||||
// 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_RESULT_OF_USE_DECLTYPE)
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, char>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, char>::value));
|
||||
#else
|
||||
@ -157,42 +221,96 @@ int main()
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
|
||||
#endif
|
||||
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr(char, float)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ref(char, float)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_0()>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ref_0()>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_void(char, float)>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ref_void(char, float)>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_void_0()>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ref_void_0()>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_c(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_v(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_cv(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_0(X)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr(void)>::type, int>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(char, float)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref(char, float)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_0()>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_0()>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_void(char, float)>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_void(char, float)>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_void_0()>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_void_0()>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_c(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_v(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_cv(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_0(X)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(void)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref(void)>::type, int>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(double)>::type, double>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const result_of_member_function_template(double)>::type, const double>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile result_of_member_function_template(double)>::type, volatile double>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile result_of_member_function_template(double)>::type, const volatile double>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const result_of_member_function_template(double)>::type, cv_overload_check<const double> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile result_of_member_function_template(double)>::type, cv_overload_check<volatile double> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile result_of_member_function_template(double)>::type, cv_overload_check<const volatile double> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int &, int)>::type, int &>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int const &, int)>::type, int const &>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int volatile &, int)>::type, int volatile &>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int const volatile &, int)>::type, int const volatile &>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(double)>::type, double>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<const result_of_member_function_template(double)>::type, cv_overload_check<const double> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile result_of_member_function_template(double)>::type, cv_overload_check<volatile double> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<const volatile result_of_member_function_template(double)>::type, cv_overload_check<const volatile double> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int &, int)>::type, int &>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int const &, int)>::type, int const &>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int volatile &, int)>::type, int volatile &>::value));
|
||||
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<result_of<no_result_type_or_result_of(double)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of(void)>::type, unsigned int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_of(double)>::type, short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_of(void)>::type, unsigned short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_of(void)>::type, const unsigned short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of_template<void>(double)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of_template<void>(void)>::type, unsigned int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_of_template<void>(double)>::type, short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_of_template<void>(void)>::type, unsigned short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_of_template<void>(void)>::type, const unsigned short>::value));
|
||||
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_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(double)>::type, short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result(double)>::type, cv_overload_check<const short> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result(double)>::type, cv_overload_check<volatile short> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result(double)>::type, cv_overload_check<const volatile short> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(void)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result(void)>::type, cv_overload_check<const int> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result(void)>::type, cv_overload_check<volatile int> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result(void)>::type, cv_overload_check<const volatile int> >::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(double)>::type, short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(double)>::type, cv_overload_check<const short> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(double)>::type, cv_overload_check<volatile short> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_template<void>(double)>::type, cv_overload_check<const volatile short> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(void)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const int> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<volatile int> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const volatile int> >::value));
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&&)>::type, short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int const&)>::type, long>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int&&)>::type, short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int&)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int const&)>::type, long>::value));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
|
||||
int i = 123;
|
||||
sfinae_test(sfinae_test_f, i);
|
||||
#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
109
test/string_ref_test1.cpp
Normal file
109
test/string_ref_test1.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2012-2012.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
For more information, see http://www.boost.org
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
typedef boost::string_ref string_ref;
|
||||
|
||||
// Should be equal
|
||||
void interop ( const std::string &str, string_ref ref ) {
|
||||
// BOOST_CHECK ( str == ref );
|
||||
BOOST_CHECK ( str.size () == ref.size ());
|
||||
BOOST_CHECK ( std::equal ( str.begin (), str.end (), ref.begin ()));
|
||||
BOOST_CHECK ( std::equal ( str.rbegin (), str.rend (), ref.rbegin ()));
|
||||
}
|
||||
|
||||
void null_tests ( const char *p ) {
|
||||
// All zero-length string-refs should be equal
|
||||
string_ref sr1; // NULL, 0
|
||||
string_ref sr2 ( NULL, 0 );
|
||||
string_ref sr3 ( p, 0 );
|
||||
string_ref sr4 ( p );
|
||||
sr4.clear ();
|
||||
|
||||
BOOST_CHECK ( sr1 == sr2 );
|
||||
BOOST_CHECK ( sr1 == sr3 );
|
||||
BOOST_CHECK ( sr2 == sr3 );
|
||||
BOOST_CHECK ( sr1 == sr4 );
|
||||
}
|
||||
|
||||
// make sure that substrings work just like strings
|
||||
void test_substr ( const std::string &str ) {
|
||||
const size_t sz = str.size ();
|
||||
string_ref ref ( str );
|
||||
|
||||
// Substrings at the end
|
||||
for ( size_t i = 0; i <= sz; ++ i )
|
||||
interop ( str.substr ( i ), ref.substr ( i ));
|
||||
|
||||
// Substrings at the beginning
|
||||
for ( size_t i = 0; i <= sz; ++ i )
|
||||
interop ( str.substr ( 0, i ), ref.substr ( 0, i ));
|
||||
|
||||
// All possible substrings
|
||||
for ( size_t i = 0; i < sz; ++i )
|
||||
for ( size_t j = i; j < sz; ++j )
|
||||
interop ( str.substr ( i, j ), ref.substr ( i, j ));
|
||||
}
|
||||
|
||||
// make sure that removing prefixes and suffixes work just like strings
|
||||
void test_remove ( const std::string &str ) {
|
||||
const size_t sz = str.size ();
|
||||
std::string work;
|
||||
string_ref ref;
|
||||
|
||||
for ( size_t i = 1; i <= sz; ++i ) {
|
||||
work = str;
|
||||
ref = str;
|
||||
while ( ref.size () >= i ) {
|
||||
interop ( work, ref );
|
||||
work.erase ( 0, i );
|
||||
ref.remove_prefix (i);
|
||||
}
|
||||
}
|
||||
|
||||
for ( size_t i = 1; i < sz; ++ i ) {
|
||||
work = str;
|
||||
ref = str;
|
||||
while ( ref.size () >= i ) {
|
||||
interop ( work, ref );
|
||||
work.erase ( work.size () - i, i );
|
||||
ref.remove_suffix (i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *test_strings [] = {
|
||||
"",
|
||||
"1",
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
"0123456789",
|
||||
NULL
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_main )
|
||||
{
|
||||
const char **p = &test_strings[0];
|
||||
|
||||
while ( *p != NULL ) {
|
||||
interop ( *p, *p );
|
||||
test_substr ( *p );
|
||||
test_remove ( *p );
|
||||
null_tests ( *p );
|
||||
|
||||
p++;
|
||||
}
|
||||
}
|
318
test/string_ref_test2.cpp
Normal file
318
test/string_ref_test2.cpp
Normal file
@ -0,0 +1,318 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2012-2012.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
For more information, see http://www.boost.org
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring> // for std::strchr
|
||||
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
typedef boost::string_ref string_ref;
|
||||
|
||||
void ends_with ( const char *arg ) {
|
||||
const size_t sz = strlen ( arg );
|
||||
string_ref sr ( arg );
|
||||
string_ref sr2 ( arg );
|
||||
const char *p = arg;
|
||||
|
||||
while ( *p ) {
|
||||
BOOST_CHECK ( sr.ends_with ( p ));
|
||||
++p;
|
||||
}
|
||||
|
||||
while ( !sr2.empty ()) {
|
||||
BOOST_CHECK ( sr.ends_with ( sr2 ));
|
||||
sr2.remove_prefix (1);
|
||||
}
|
||||
|
||||
sr2 = arg;
|
||||
while ( !sr2.empty ()) {
|
||||
BOOST_CHECK ( sr.ends_with ( sr2 ));
|
||||
sr2.remove_prefix (1);
|
||||
}
|
||||
|
||||
char ch = sz == 0 ? '\0' : arg [ sz - 1 ];
|
||||
sr2 = arg;
|
||||
if ( sz > 0 )
|
||||
BOOST_CHECK ( sr2.ends_with ( ch ));
|
||||
BOOST_CHECK ( !sr2.ends_with ( ++ch ));
|
||||
BOOST_CHECK ( sr2.ends_with ( string_ref ()));
|
||||
}
|
||||
|
||||
void starts_with ( const char *arg ) {
|
||||
const size_t sz = strlen ( arg );
|
||||
string_ref sr ( arg );
|
||||
string_ref sr2 ( arg );
|
||||
const char *p = arg + std::strlen ( arg ) - 1;
|
||||
while ( p >= arg ) {
|
||||
std::string foo ( arg, p + 1 );
|
||||
BOOST_CHECK ( sr.starts_with ( foo ));
|
||||
--p;
|
||||
}
|
||||
|
||||
while ( !sr2.empty ()) {
|
||||
BOOST_CHECK ( sr.starts_with ( sr2 ));
|
||||
sr2.remove_suffix (1);
|
||||
}
|
||||
|
||||
char ch = *arg;
|
||||
sr2 = arg;
|
||||
if ( sz > 0 )
|
||||
BOOST_CHECK ( sr2.starts_with ( ch ));
|
||||
BOOST_CHECK ( !sr2.starts_with ( ++ch ));
|
||||
BOOST_CHECK ( sr2.starts_with ( string_ref ()));
|
||||
}
|
||||
|
||||
void reverse ( const char *arg ) {
|
||||
// Round trip
|
||||
string_ref sr1 ( arg );
|
||||
std::string string1 ( sr1.rbegin (), sr1.rend ());
|
||||
string_ref sr2 ( string1 );
|
||||
std::string string2 ( sr2.rbegin (), sr2.rend ());
|
||||
|
||||
BOOST_CHECK ( std::equal ( sr2.rbegin (), sr2.rend (), arg ));
|
||||
BOOST_CHECK ( string2 == arg );
|
||||
BOOST_CHECK ( std::equal ( sr1.begin (), sr1.end (), string2.begin ()));
|
||||
}
|
||||
|
||||
// This helper function eliminates signed vs. unsigned warnings
|
||||
string_ref::size_type ptr_diff ( const char *res, const char *base ) {
|
||||
BOOST_CHECK ( res >= base );
|
||||
return static_cast<string_ref::size_type> ( res - base );
|
||||
}
|
||||
|
||||
void find ( const char *arg ) {
|
||||
string_ref sr1;
|
||||
string_ref sr2;
|
||||
const char *p;
|
||||
|
||||
// Look for each character in the string(searching from the start)
|
||||
p = arg;
|
||||
sr1 = arg;
|
||||
while ( *p ) {
|
||||
string_ref::size_type pos = sr1.find(*p);
|
||||
BOOST_CHECK ( pos != string_ref::npos && ( pos <= ptr_diff ( p, arg )));
|
||||
++p;
|
||||
}
|
||||
|
||||
// Look for each character in the string (searching from the end)
|
||||
p = arg;
|
||||
sr1 = arg;
|
||||
while ( *p ) {
|
||||
string_ref::size_type pos = sr1.rfind(*p);
|
||||
BOOST_CHECK ( pos != string_ref::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg )));
|
||||
++p;
|
||||
}
|
||||
|
||||
// Look for pairs on characters (searching from the start)
|
||||
sr1 = arg;
|
||||
p = arg;
|
||||
while ( *p && *(p+1)) {
|
||||
string_ref sr3 ( p, 2 );
|
||||
string_ref::size_type pos = sr1.find ( sr3 );
|
||||
BOOST_CHECK ( pos != string_ref::npos && pos <= static_cast<string_ref::size_type>( p - arg ));
|
||||
p++;
|
||||
}
|
||||
|
||||
sr1 = arg;
|
||||
p = arg;
|
||||
// for all possible chars, see if we find them in the right place.
|
||||
// Note that strchr will/might do the _wrong_ thing if we search for NULL
|
||||
for ( int ch = 1; ch < 256; ++ch ) {
|
||||
string_ref::size_type pos = sr1.find(ch);
|
||||
const char *strp = std::strchr ( arg, ch );
|
||||
BOOST_CHECK (( strp == NULL ) == ( pos == string_ref::npos ));
|
||||
if ( strp != NULL )
|
||||
BOOST_CHECK ( ptr_diff ( strp, arg ) == pos );
|
||||
}
|
||||
|
||||
sr1 = arg;
|
||||
p = arg;
|
||||
// for all possible chars, see if we find them in the right place.
|
||||
// Note that strchr will/might do the _wrong_ thing if we search for NULL
|
||||
for ( int ch = 1; ch < 256; ++ch ) {
|
||||
string_ref::size_type pos = sr1.rfind(ch);
|
||||
const char *strp = std::strrchr ( arg, ch );
|
||||
BOOST_CHECK (( strp == NULL ) == ( pos == string_ref::npos ));
|
||||
if ( strp != NULL )
|
||||
BOOST_CHECK ( ptr_diff ( strp, arg ) == pos );
|
||||
}
|
||||
|
||||
|
||||
// Find everything at the start
|
||||
p = arg;
|
||||
sr1 = arg;
|
||||
while ( !sr1.empty ()) {
|
||||
string_ref::size_type pos = sr1.find(*p);
|
||||
BOOST_CHECK ( pos == 0 );
|
||||
sr1.remove_prefix (1);
|
||||
++p;
|
||||
}
|
||||
|
||||
// Find everything at the end
|
||||
sr1 = arg;
|
||||
p = arg + strlen ( arg ) - 1;
|
||||
while ( !sr1.empty ()) {
|
||||
string_ref::size_type pos = sr1.rfind(*p);
|
||||
BOOST_CHECK ( pos == sr1.size () - 1 );
|
||||
sr1.remove_suffix (1);
|
||||
--p;
|
||||
}
|
||||
|
||||
// Find everything at the start
|
||||
sr1 = arg;
|
||||
p = arg;
|
||||
while ( !sr1.empty ()) {
|
||||
string_ref::size_type pos = sr1.find_first_of(*p);
|
||||
BOOST_CHECK ( pos == 0 );
|
||||
sr1.remove_prefix (1);
|
||||
++p;
|
||||
}
|
||||
|
||||
|
||||
// Find everything at the end
|
||||
sr1 = arg;
|
||||
p = arg + strlen ( arg ) - 1;
|
||||
while ( !sr1.empty ()) {
|
||||
string_ref::size_type pos = sr1.find_last_of(*p);
|
||||
BOOST_CHECK ( pos == sr1.size () - 1 );
|
||||
sr1.remove_suffix (1);
|
||||
--p;
|
||||
}
|
||||
|
||||
// Basic sanity checking for "find_first_of / find_first_not_of"
|
||||
sr1 = arg;
|
||||
sr2 = arg;
|
||||
while ( !sr1.empty() ) {
|
||||
BOOST_CHECK ( sr1.find_first_of ( sr2 ) == 0 );
|
||||
BOOST_CHECK ( sr1.find_first_not_of ( sr2 ) == string_ref::npos );
|
||||
sr1.remove_prefix ( 1 );
|
||||
}
|
||||
|
||||
p = arg;
|
||||
sr1 = arg;
|
||||
while ( *p ) {
|
||||
string_ref::size_type pos1 = sr1.find_first_of(*p);
|
||||
string_ref::size_type pos2 = sr1.find_first_not_of(*p);
|
||||
BOOST_CHECK ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 <= ptr_diff ( p, arg ));
|
||||
if ( pos2 != string_ref::npos ) {
|
||||
for ( size_t i = 0 ; i < pos2; ++i )
|
||||
BOOST_CHECK ( sr1[i] == *p );
|
||||
BOOST_CHECK ( sr1 [ pos2 ] != *p );
|
||||
}
|
||||
|
||||
BOOST_CHECK ( pos2 != pos1 );
|
||||
++p;
|
||||
}
|
||||
|
||||
// Basic sanity checking for "find_last_of / find_last_not_of"
|
||||
sr1 = arg;
|
||||
sr2 = arg;
|
||||
while ( !sr1.empty() ) {
|
||||
BOOST_CHECK ( sr1.find_last_of ( sr2 ) == ( sr1.size () - 1 ));
|
||||
BOOST_CHECK ( sr1.find_last_not_of ( sr2 ) == string_ref::npos );
|
||||
sr1.remove_suffix ( 1 );
|
||||
}
|
||||
|
||||
p = arg;
|
||||
sr1 = arg;
|
||||
while ( *p ) {
|
||||
string_ref::size_type pos1 = sr1.find_last_of(*p);
|
||||
string_ref::size_type pos2 = sr1.find_last_not_of(*p);
|
||||
BOOST_CHECK ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 >= ptr_diff ( p, arg ));
|
||||
BOOST_CHECK ( pos2 == string_ref::npos || pos1 < sr1.size ());
|
||||
if ( pos2 != string_ref::npos ) {
|
||||
for ( size_t i = sr1.size () -1 ; i > pos2; --i )
|
||||
BOOST_CHECK ( sr1[i] == *p );
|
||||
BOOST_CHECK ( sr1 [ pos2 ] != *p );
|
||||
}
|
||||
|
||||
BOOST_CHECK ( pos2 != pos1 );
|
||||
++p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void to_string ( const char *arg ) {
|
||||
string_ref sr1;
|
||||
std::string str1;
|
||||
std::string str2;
|
||||
|
||||
str1.assign ( arg );
|
||||
sr1 = arg;
|
||||
// str2 = sr1.to_string<std::allocator<char> > ();
|
||||
str2 = sr1.to_string ();
|
||||
BOOST_CHECK ( str1 == str2 );
|
||||
|
||||
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
|
||||
std::string str3 = static_cast<std::string> ( sr1 );
|
||||
BOOST_CHECK ( str1 == str3 );
|
||||
#endif
|
||||
}
|
||||
|
||||
void compare ( const char *arg ) {
|
||||
string_ref sr1;
|
||||
std::string str1;
|
||||
std::string str2 = str1;
|
||||
|
||||
str1.assign ( arg );
|
||||
sr1 = arg;
|
||||
BOOST_CHECK ( sr1 == sr1); // compare string_ref and string_ref
|
||||
BOOST_CHECK ( sr1 == str1); // compare string and string_ref
|
||||
BOOST_CHECK ( str1 == sr1 ); // compare string_ref and string
|
||||
BOOST_CHECK ( sr1 == arg ); // compare string_ref and pointer
|
||||
BOOST_CHECK ( arg == sr1 ); // compare pointer and string_ref
|
||||
|
||||
if ( sr1.size () > 0 ) {
|
||||
(*str1.rbegin())++;
|
||||
BOOST_CHECK ( sr1 != str1 );
|
||||
BOOST_CHECK ( str1 != sr1 );
|
||||
BOOST_CHECK ( sr1 < str1 );
|
||||
BOOST_CHECK ( sr1 <= str1 );
|
||||
BOOST_CHECK ( str1 > sr1 );
|
||||
BOOST_CHECK ( str1 >= sr1 );
|
||||
|
||||
(*str1.rbegin()) -= 2;
|
||||
BOOST_CHECK ( sr1 != str1 );
|
||||
BOOST_CHECK ( str1 != sr1 );
|
||||
BOOST_CHECK ( sr1 > str1 );
|
||||
BOOST_CHECK ( sr1 >= str1 );
|
||||
BOOST_CHECK ( str1 < sr1 );
|
||||
BOOST_CHECK ( str1 <= sr1 );
|
||||
}
|
||||
}
|
||||
|
||||
const char *test_strings [] = {
|
||||
"",
|
||||
"0",
|
||||
"abc",
|
||||
"AAA", // all the same
|
||||
"adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf",
|
||||
"abc\0asdfadsfasf",
|
||||
NULL
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_main )
|
||||
{
|
||||
const char **p = &test_strings[0];
|
||||
|
||||
while ( *p != NULL ) {
|
||||
starts_with ( *p );
|
||||
ends_with ( *p );
|
||||
reverse ( *p );
|
||||
find ( *p );
|
||||
to_string ( *p );
|
||||
compare ( *p );
|
||||
|
||||
p++;
|
||||
}
|
||||
}
|
183
test/string_ref_test_io.cpp
Normal file
183
test/string_ref_test_io.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright Andrey Semashev 2013.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
/*!
|
||||
* \file string_ref_test_io.cpp
|
||||
* \author Andrey Semashev
|
||||
* \date 26.05.2013
|
||||
*
|
||||
* \brief This header contains tests for stream operations of \c basic_string_ref.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE string_ref_test_io
|
||||
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
typedef boost::mpl::vector<
|
||||
char
|
||||
#if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_STD_WSTREAMBUF) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
, wchar_t
|
||||
#endif
|
||||
/* Current implementations seem to be missing codecvt facets to convert chars to char16_t and char32_t even though the types are available.
|
||||
#if !defined(BOOST_NO_CXX11_CHAR16_T)
|
||||
, char16_t
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_CHAR32_T)
|
||||
, char32_t
|
||||
#endif
|
||||
*/
|
||||
>::type char_types;
|
||||
|
||||
static const char* test_strings[] =
|
||||
{
|
||||
"begin",
|
||||
"abcd",
|
||||
"end"
|
||||
};
|
||||
|
||||
//! The context with test data for particular character type
|
||||
template< typename CharT >
|
||||
struct context
|
||||
{
|
||||
typedef CharT char_type;
|
||||
typedef std::basic_string< char_type > string_type;
|
||||
typedef std::basic_ostringstream< char_type > ostream_type;
|
||||
|
||||
string_type begin, abcd, end;
|
||||
|
||||
context()
|
||||
{
|
||||
boost::string_ref str = test_strings[0];
|
||||
std::copy(str.begin(), str.end(), std::back_inserter(begin));
|
||||
|
||||
str = test_strings[1];
|
||||
std::copy(str.begin(), str.end(), std::back_inserter(abcd));
|
||||
|
||||
str = test_strings[2];
|
||||
std::copy(str.begin(), str.end(), std::back_inserter(end));
|
||||
}
|
||||
};
|
||||
|
||||
// Test regular output
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(string_ref_output, CharT, char_types)
|
||||
{
|
||||
typedef CharT char_type;
|
||||
typedef std::basic_string< char_type > string_type;
|
||||
typedef std::basic_ostringstream< char_type > ostream_type;
|
||||
typedef boost::basic_string_ref< char_type > string_ref_type;
|
||||
|
||||
context< char_type > ctx;
|
||||
|
||||
ostream_type strm;
|
||||
strm << string_ref_type(ctx.abcd);
|
||||
BOOST_CHECK(strm.str() == ctx.abcd);
|
||||
}
|
||||
|
||||
// Test support for padding
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(padding, CharT, char_types)
|
||||
{
|
||||
typedef CharT char_type;
|
||||
typedef std::basic_string< char_type > string_type;
|
||||
typedef std::basic_ostringstream< char_type > ostream_type;
|
||||
typedef boost::basic_string_ref< char_type > string_ref_type;
|
||||
|
||||
context< char_type > ctx;
|
||||
|
||||
// Test for padding
|
||||
{
|
||||
ostream_type strm_ref;
|
||||
strm_ref << ctx.begin << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
|
||||
|
||||
ostream_type strm_correct;
|
||||
strm_correct << ctx.begin << std::setw(8) << ctx.abcd << ctx.end;
|
||||
|
||||
BOOST_CHECK(strm_ref.str() == strm_correct.str());
|
||||
}
|
||||
|
||||
// Test for long padding
|
||||
{
|
||||
ostream_type strm_ref;
|
||||
strm_ref << ctx.begin << std::setw(100) << string_ref_type(ctx.abcd) << ctx.end;
|
||||
|
||||
ostream_type strm_correct;
|
||||
strm_correct << ctx.begin << std::setw(100) << ctx.abcd << ctx.end;
|
||||
|
||||
BOOST_CHECK(strm_ref.str() == strm_correct.str());
|
||||
}
|
||||
|
||||
// Test that short width does not truncate the string
|
||||
{
|
||||
ostream_type strm_ref;
|
||||
strm_ref << ctx.begin << std::setw(1) << string_ref_type(ctx.abcd) << ctx.end;
|
||||
|
||||
ostream_type strm_correct;
|
||||
strm_correct << ctx.begin << std::setw(1) << ctx.abcd << ctx.end;
|
||||
|
||||
BOOST_CHECK(strm_ref.str() == strm_correct.str());
|
||||
}
|
||||
}
|
||||
|
||||
// Test support for padding fill
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(padding_fill, CharT, char_types)
|
||||
{
|
||||
typedef CharT char_type;
|
||||
typedef std::basic_string< char_type > string_type;
|
||||
typedef std::basic_ostringstream< char_type > ostream_type;
|
||||
typedef boost::basic_string_ref< char_type > string_ref_type;
|
||||
|
||||
context< char_type > ctx;
|
||||
|
||||
ostream_type strm_ref;
|
||||
strm_ref << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
|
||||
|
||||
ostream_type strm_correct;
|
||||
strm_correct << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << ctx.abcd << ctx.end;
|
||||
|
||||
BOOST_CHECK(strm_ref.str() == strm_correct.str());
|
||||
}
|
||||
|
||||
// Test support for alignment
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(alignment, CharT, char_types)
|
||||
{
|
||||
typedef CharT char_type;
|
||||
typedef std::basic_string< char_type > string_type;
|
||||
typedef std::basic_ostringstream< char_type > ostream_type;
|
||||
typedef boost::basic_string_ref< char_type > string_ref_type;
|
||||
|
||||
context< char_type > ctx;
|
||||
|
||||
// Left alignment
|
||||
{
|
||||
ostream_type strm_ref;
|
||||
strm_ref << ctx.begin << std::left << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
|
||||
|
||||
ostream_type strm_correct;
|
||||
strm_correct << ctx.begin << std::left << std::setw(8) << ctx.abcd << ctx.end;
|
||||
|
||||
BOOST_CHECK(strm_ref.str() == strm_correct.str());
|
||||
}
|
||||
|
||||
// Right alignment
|
||||
{
|
||||
ostream_type strm_ref;
|
||||
strm_ref << ctx.begin << std::right << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
|
||||
|
||||
ostream_type strm_correct;
|
||||
strm_correct << ctx.begin << std::right << std::setw(8) << ctx.abcd << ctx.end;
|
||||
|
||||
BOOST_CHECK(strm_ref.str() == strm_correct.str());
|
||||
}
|
||||
}
|
500
utility.htm
500
utility.htm
@ -84,8 +84,10 @@ const std::list<T>::iterator next = boost::next(prev, 2);</pre>
|
||||
will prevent the otherwise implicitly-generated functions (which don't have the
|
||||
proper semantics) from becoming a trap for other programmers.</p>
|
||||
<p>The traditional way to deal with these is to declare a private copy constructor
|
||||
and copy assignment, and then document why this is done. But deriving
|
||||
from <b>noncopyable</b> is simpler and clearer, and doesn't require additional
|
||||
and copy assignment, and then document why this is done. A new alternative
|
||||
was introduced in C++2011, declaring a copy constructor and a copy assignment
|
||||
operator, but marking both as <code>delete</code>d. Deriving
|
||||
from <b>noncopyable</b> is simpler and clearer, and doesn't require additional
|
||||
documentation.</p>
|
||||
<p>The program <a href="noncopyable_test.cpp">noncopyable_test.cpp</a> can be used
|
||||
to verify class <b>noncopyable</b> works as expected. It has have been run
|
||||
@ -106,7 +108,9 @@ class ResourceLadenFileSystem : boost::noncopyable {
|
||||
about the effect on compiler optimization of adding (even trivial inline)
|
||||
destructor declarations. He says "Probably this concern is misplaced,
|
||||
because noncopyable will be used mostly for classes which own resources and
|
||||
thus have non-trivial destruction semantics."</p>
|
||||
thus have non-trivial destruction semantics." With C++2011, using an
|
||||
optimized and trivial constructor and similar destructor can be enforced by
|
||||
declaring both and marking them <code>default</code>.</p>
|
||||
<h2><a name="addressof">Function template addressof()</a></h2>
|
||||
<p>Function <strong>addressof()</strong> returns the address of an object.</p>
|
||||
<blockquote>
|
||||
@ -143,7 +147,7 @@ void f() {
|
||||
<h2><a name="result_of">Class template
|
||||
result_of</a></h2> <p>The class template
|
||||
<code>result_of</code> helps determine the type of a
|
||||
call expression. Given an lvalue <code>f</code> of
|
||||
call expression. For example, given an lvalue <code>f</code> of
|
||||
type <code>F</code> and lvalues <code>t1</code>,
|
||||
<code>t2</code>, ..., <code>t<em>N</em></code> of
|
||||
types <code>T1</code>, <code>T2</code>, ...,
|
||||
@ -151,37 +155,481 @@ void f() {
|
||||
<code>result_of<F(T1, T2, ...,
|
||||
T<em>N</em>)>::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><<a
|
||||
href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>></code>.</p>
|
||||
|
||||
<p>If your compiler's support for <code>decltype</code> is
|
||||
adequate, <code>result_of</code> automatically uses it to
|
||||
deduce the type of the call expression, in which case
|
||||
<code>result_of<F(T1, T2, ...,
|
||||
T<em>N</em>)></code> is
|
||||
<code>F::result_type</code>. When <code>F</code>
|
||||
does not contain <code>result_type</code>,
|
||||
T<em>N</em>)>::type</code> names the type
|
||||
<code>decltype(boost::declval<F>()(boost::declval<T1>(),
|
||||
boost::declval<T2>(), ...,
|
||||
boost::declval<T<em>N</em>>()))</code>, as in the
|
||||
following example.</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
template<class T>
|
||||
T operator()(T x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
typedef boost::result_of<
|
||||
functor(int)
|
||||
>::type type; // type is int</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>You can test whether <code>result_of</code> is using
|
||||
<code>decltype</code> by checking if the macro
|
||||
<code>BOOST_RESULT_OF_USE_DECLTYPE</code> is defined after
|
||||
including <code>result_of.hpp</code>. You can also force
|
||||
<code>result_of</code> to use <code>decltype</code> by
|
||||
defining <code>BOOST_RESULT_OF_USE_DECLTYPE</code> prior
|
||||
to including <code>result_of.hpp</code>.</p>
|
||||
|
||||
<p>If <code>decltype</code> is not used,
|
||||
then automatic result type deduction of function
|
||||
objects is not possible. Instead, <code>result_of</code>
|
||||
uses the following protocol to allow the programmer to
|
||||
specify a type. When <code>F</code> is a class type with a
|
||||
member type <code>result_type</code>,
|
||||
<code>result_of<F(T1, T2, ...,
|
||||
T<em>N</em>)></code> is <code>F::result<F(T1,
|
||||
T<em>N</em>)>::type</code> is
|
||||
<code>F::result_type</code>. When <code>F</code> does
|
||||
not contain <code>result_type</code>,
|
||||
<code>result_of<F(T1, T2, ...,
|
||||
T<em>N</em>)>::type</code> is <code>F::result<F(T1,
|
||||
T2, ..., T<em>N</em>)>::type</code> when
|
||||
<code><em>N</em> > 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><<a
|
||||
href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>></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<class> struct result;
|
||||
|
||||
template<class F, class T>
|
||||
struct result<F(T)> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
T operator()(T x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
typedef boost::result_of<
|
||||
functor(int)
|
||||
>::type type; // type is int</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Since <code>decltype</code> is a new language
|
||||
feature recently standardized in C++11,
|
||||
if you are writing a function object
|
||||
to be used with <code>result_of</code>, for
|
||||
maximum portability, you might consider following
|
||||
the above protocol even if your compiler has
|
||||
proper <code>decltype</code> support. If you wish to continue to
|
||||
use the protocol on compilers that
|
||||
support <code>decltype</code>, there are two options:
|
||||
You can use <code>boost::tr1_result_of</code>, which is also
|
||||
defined in <code><<a href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>></code>.
|
||||
Alternatively, you can define the macro
|
||||
<code>BOOST_RESULT_OF_USE_TR1</code>, which causes
|
||||
<code>result_of</code> to use the protocol described
|
||||
above instead of <code>decltype</code>. If you choose to
|
||||
follow the protocol, take care to ensure that the
|
||||
<code>result_type</code> and
|
||||
<code>result<></code> members accurately
|
||||
represent the return type of
|
||||
<code>operator()</code> given a call expression.</p>
|
||||
|
||||
<p>Additionally, <code>boost::result_of</code>
|
||||
provides a third mode of operation, which some users
|
||||
may find convenient. When
|
||||
<code>BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK</code>
|
||||
is defined, <code>boost::result_of</code> behaves as
|
||||
follows. If the function object has a member
|
||||
type <code>result_type</code> or member
|
||||
template <code>result<></code>, then
|
||||
<code>boost::result_of</code> will use the TR1
|
||||
protocol. Otherwise,
|
||||
<code>boost::result_of</code> will
|
||||
use <code>decltype</code>. Using TR1 with
|
||||
a <code>declytpe</code> fallback may workaround
|
||||
certain problems at the cost of portability. For
|
||||
example:
|
||||
<ul>
|
||||
<li>Deficient compiler: If your code
|
||||
requires <code>boost::result_of</code> to work
|
||||
with incomplete return types but your
|
||||
compiler's <code>decltype</code> implementation
|
||||
does not support incomplete return types, then you
|
||||
can use the TR1 protocol as a workaround. Support
|
||||
for incomplete return types was added late in the
|
||||
C++11 standardization process
|
||||
(see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf">N3276</a>)
|
||||
and is not implemented by some compilers.</li>
|
||||
|
||||
<li>Deficient legacy code: If your existing TR1
|
||||
function object advertises a different type than
|
||||
the actual result type deduced
|
||||
by <code>decltype</code>, then using TR1 with a
|
||||
<code>decltype</code> fallback will allow you to
|
||||
work with both your existing TR1 function objects
|
||||
and new C++11 function object. This situation
|
||||
could occur if your legacy function objects
|
||||
misused the TR1 protocol. See the documentation on
|
||||
known <a href="#result_of_tr1_diff">differences</a>
|
||||
between <code>boost::result_of</code> and TR1.</li>
|
||||
</ul>
|
||||
|
||||
<a name="BOOST_NO_RESULT_OF"></a>
|
||||
<p>This implementation of <code>result_of</code> requires class template partial specialization, the ability to parse function types properly, and support for SFINAE. If <code>result_of</code> is not supported by your compiler, including the header <code>boost/utility/result_of.hpp</code> will define the macro <code>BOOST_NO_RESULT_OF</code>. Contributed by Doug Gregor.</p>
|
||||
<p>This implementation of <code>result_of</code>
|
||||
requires class template partial specialization, the
|
||||
ability to parse function types properly, and support
|
||||
for SFINAE. If <code>result_of</code> is not supported
|
||||
by your compiler, including the header
|
||||
<code>boost/utility/result_of.hpp</code> will
|
||||
define the macro <code>BOOST_NO_RESULT_OF</code>.</p>
|
||||
|
||||
<p>For additional information
|
||||
about <code>result_of</code>, see the C++ Library
|
||||
Technical Report,
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">N1836</a>,
|
||||
or, for motivation and design rationale,
|
||||
the <code>result_of</code> <a href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1454.html">proposal</a>.</p>
|
||||
|
||||
<a name="result_of_guidelines">
|
||||
<h3>Usage guidelines for boost::result_of</h3>
|
||||
</a>
|
||||
|
||||
<p>The following are general suggestions about when
|
||||
and how to use <code>boost::result_of</code>.</p>
|
||||
|
||||
<ol>
|
||||
<li> If you are targeting C++11 and are not concerned
|
||||
about portability to non-compliant compilers or
|
||||
previous versions of the standard, then use
|
||||
<code>std::result_of</code>. If <code>std::result_of</code>
|
||||
meets your needs, then there's no reason to stop using
|
||||
it.</li>
|
||||
|
||||
<li> If you are targeting C++11 but may port your code
|
||||
to legacy compilers at some time in the future, then
|
||||
use <code>boost::result_of</code> with
|
||||
<code>decltype</code>. When <code>decltype</code> is
|
||||
used <code>boost::result_of</code>
|
||||
and <code>std::result_of</code> are usually
|
||||
interchangeable. See the documentation on
|
||||
known <a href="#result_of_cxx11_diff">differences</a>
|
||||
between boost::result_of and C++11 result_of.</li>
|
||||
|
||||
<li> If compiler portability is required,
|
||||
use <code>boost::result_of</code> with the TR1 protocol.</li>
|
||||
</ol>
|
||||
|
||||
<p>Regardless of how you
|
||||
configure <code>boost::result_of</code>, it is
|
||||
important to bear in mind that the return type of a
|
||||
function may change depending on its arguments, and
|
||||
additionally, the return type of a member function may
|
||||
change depending on the cv-qualification of the
|
||||
object. <code>boost::result_of</code> must be passed
|
||||
the appropriately cv-qualified types in order to
|
||||
deduce the corresponding return type. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
int& operator()(int);
|
||||
int const& operator()(int) const;
|
||||
|
||||
float& operator()(float&);
|
||||
float const& operator()(float const&);
|
||||
};
|
||||
|
||||
typedef boost::result_of<
|
||||
functor(int)
|
||||
>::type type1; // type1 is int &
|
||||
|
||||
typedef boost::result_of<
|
||||
const functor(int)
|
||||
>::type type2; // type2 is int const &
|
||||
|
||||
typedef boost::result_of<
|
||||
functor(float&)
|
||||
>::type type3; // type3 is float &
|
||||
|
||||
typedef boost::result_of<
|
||||
functor(float const&)
|
||||
>::type type4; // type4 is float const &</pre>
|
||||
</blockquote>
|
||||
|
||||
<a name="result_of_tr1_protocol_guidelines">
|
||||
<h3>Usage guidelines for the TR1 result_of protocol</h3>
|
||||
</a>
|
||||
|
||||
<p>On compliant C++11
|
||||
compilers, <code>boost::result_of</code> can
|
||||
use <code>decltype</code> to deduce the type of any
|
||||
call expression, including calls to function
|
||||
objects. However, on pre-C++11 compilers or on
|
||||
compilers without adequate decltype support,
|
||||
additional scaffolding is needed from function
|
||||
objects as described above. The following are
|
||||
suggestions about how to use the TR1 protocol.</p>
|
||||
|
||||
<ul>
|
||||
<li>When the return type does not depend on the
|
||||
argument types or the cv-qualification of the
|
||||
function object, simply
|
||||
define <code>result_type</code>. There is no need
|
||||
to use the <code>result</code> template unless the
|
||||
return type varies.</li>
|
||||
|
||||
<li>Use the protocol specified type when defining
|
||||
function prototypes. This can help ensure the
|
||||
actual return type does not get out of sync with
|
||||
the protocol specification. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
typedef int result_type;
|
||||
result_type operator()(int);
|
||||
};</pre>
|
||||
</blockquote> </li>
|
||||
|
||||
<li>Always specify the <code>result</code>
|
||||
specialization near the corresponding
|
||||
<code>operator()</code> overload. This can make it
|
||||
easier to keep the specializations in sync with the
|
||||
overloads. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
template<class> struct result;
|
||||
|
||||
template<class F>
|
||||
struct result<F(int)> {
|
||||
typedef int& type;
|
||||
};
|
||||
result<functor(int)>::type operator()(int);
|
||||
|
||||
template<class F>
|
||||
struct result<const F(int)> {
|
||||
typedef int const& type;
|
||||
};
|
||||
result<const functor(int)>::type operator()(int) const;
|
||||
};</pre>
|
||||
</blockquote> </li>
|
||||
|
||||
<li>Use type transformations to simplify
|
||||
the <code>result</code> template specialization. For
|
||||
example, the following uses
|
||||
<a href="../type_traits/doc/html/index.html">Boost.TypeTraits</a>
|
||||
to specialize the <code>result</code> template for
|
||||
a single <code>operator()</code> that can be called on
|
||||
both a const and non-const function object with
|
||||
either an lvalue or rvalue argument.
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
template<class> struct result;
|
||||
|
||||
template<class F, class T>
|
||||
struct result<F(T)>
|
||||
: boost::remove_cv<
|
||||
typename boost::remove_reference<T>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
T operator()(T const& x) const;
|
||||
};</pre>
|
||||
</blockquote></li>
|
||||
</ul>
|
||||
|
||||
<a name="result_of_tr1_diff">
|
||||
<h3>Known differences between boost::result_of and TR1 result_of</h3>
|
||||
</a>
|
||||
|
||||
When using <code>decltype</code>, <code>boost::result_of</code>
|
||||
ignores the TR1 protocol and instead deduces the
|
||||
return type of function objects directly
|
||||
via <code>decltype</code>. In most situations, users
|
||||
will not notice a difference, so long as they use the
|
||||
protocol correctly. The following are situations in
|
||||
which the type deduced
|
||||
by <code>boost::result_of</code> is known to differ depending on
|
||||
whether <code>decltype</code> or the TR1 protocol is
|
||||
used.
|
||||
|
||||
<ul>
|
||||
<li> TR1 protocol misusage
|
||||
|
||||
<p>When using the TR1
|
||||
protocol, <code>boost::result_of</code> cannot
|
||||
detect whether the actual type of a call to a
|
||||
function object is the same as the type specified
|
||||
by the protocol, which allows for the possibility
|
||||
of inadvertent mismatches between the specified
|
||||
type and the actual type. When
|
||||
using <code>decltype</code>, these subtle bugs
|
||||
may result in compilation errors. For example:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
typedef short result_type;
|
||||
int operator()(short);
|
||||
};
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<boost::result_of<functor(short)>::type, int>::value
|
||||
));
|
||||
|
||||
#else
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<boost::result_of<functor(short)>::type, short>::value
|
||||
));
|
||||
|
||||
#endif</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Note that the user can
|
||||
force <code>boost::result_of</code> to use the TR1
|
||||
protocol even on platforms that
|
||||
support <code>decltype</code> by
|
||||
defining <code>BOOST_RESULT_OF_USE_TR1</code>.</p></li>
|
||||
|
||||
<li> Nullary function objects
|
||||
|
||||
<p>When using the TR1 protocol, <code>boost::result_of</code>
|
||||
cannot always deduce the type of calls to
|
||||
nullary function objects, in which case the
|
||||
type defaults to void. When using <code>decltype</code>,
|
||||
<code>boost::result_of</code> always gives the actual type of the
|
||||
call expression. For example:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
template<class> struct result {
|
||||
typedef int type;
|
||||
};
|
||||
int operator()();
|
||||
};
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<boost::result_of<functor()>::type, int>::value
|
||||
));
|
||||
|
||||
#else
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<boost::result_of<functor()>::type, void>::value
|
||||
));
|
||||
|
||||
#endif</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Note that there are some workarounds for the
|
||||
nullary function problem. So long as the return
|
||||
type does not vary,
|
||||
<code>result_type</code> can always be used to
|
||||
specify the return type regardless of arity. If the
|
||||
return type does vary, then the user can
|
||||
specialize <code>boost::result_of</code> itself for
|
||||
nullary calls.</p></li>
|
||||
|
||||
<li> Non-class prvalues and cv-qualification
|
||||
|
||||
<p>When using the TR1
|
||||
protocol, <code>boost::result_of</code> will
|
||||
report the cv-qualified type specified
|
||||
by <code>result_type</code> or
|
||||
the <code>result</code> template regardless of
|
||||
the actual cv-qualification of the call
|
||||
expression. When using
|
||||
<code>decltype</code>, <code>boost::result_of</code>
|
||||
will report the actual type of the call expression,
|
||||
which is not cv-qualified when the expression is a
|
||||
non-class prvalue. For example:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
template<class> struct result;
|
||||
template<class F, class T> struct result<F(const T)> {
|
||||
typedef const T type;
|
||||
};
|
||||
|
||||
const short operator()(const short);
|
||||
int const & operator()(int const &);
|
||||
};
|
||||
|
||||
// Non-prvalue call expressions work the same with or without decltype.
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
boost::result_of<functor(int const &)>::type,
|
||||
int const &
|
||||
::value
|
||||
));
|
||||
|
||||
// Non-class prvalue call expressions are not actually cv-qualified,
|
||||
// but only the decltype-based result_of reports this accurately.
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
boost::result_of<functor(const short)>::type,
|
||||
short
|
||||
::value
|
||||
));
|
||||
|
||||
#else
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
boost::result_of<functor(const short)>::type,
|
||||
const short
|
||||
::value
|
||||
));
|
||||
|
||||
#endif</pre>
|
||||
</blockquote></li>
|
||||
</ul>
|
||||
|
||||
<a name="result_of_cxx11_diff">
|
||||
<h3>Known differences between boost::result_of and C++11 result_of</h3>
|
||||
</a>
|
||||
|
||||
<p>When using <code>decltype</code>, <code>boost::result_of</code>
|
||||
implements most of the C++11 result_of
|
||||
specification. One known exception is that
|
||||
<code>boost::result_of</code> does not implement the
|
||||
requirements regarding pointers to member data.</p>
|
||||
|
||||
<p>Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others</p>
|
||||
|
||||
<h2>Class templates for the Base-from-Member Idiom</h2>
|
||||
<p>See <a href="base_from_member.html">separate documentation</a>.</p>
|
||||
|
155
value_init.htm
155
value_init.htm
@ -33,6 +33,7 @@
|
||||
|
||||
<ul>
|
||||
<li><a href="#val_init"><code>template class value_initialized<T></code></a></li>
|
||||
<li><a href="#initialized"><code>template class initialized<T></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,37 +223,65 @@ 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>
|
||||
@ -260,7 +295,7 @@ its internal data, prior to constructing the object that it contains.
|
||||
<br> operator T&() { return x ; }
|
||||
<br> T const &data() const { return x ; }
|
||||
<br> T& data() { return x ; }
|
||||
<br> void swap( value_initialized<T>& );
|
||||
<br> void swap( value_initialized& );
|
||||
<br>
|
||||
<br> private :
|
||||
<br> <i>unspecified</i> x ;
|
||||
@ -278,6 +313,12 @@ its internal data, prior to constructing the object that it contains.
|
||||
<br> return x.data() ;
|
||||
<br>}
|
||||
<br>
|
||||
<br>template<class T>
|
||||
<br>void swap ( value_initialized<T>& lhs, value_initialized<T>& rhs )
|
||||
<br>{
|
||||
<br> lhs.swap(rhs) ;
|
||||
<br>}
|
||||
<br>
|
||||
<br>} // namespace boost
|
||||
<br></pre>
|
||||
|
||||
@ -313,7 +354,7 @@ non-member function <code>get()</code>: </p>
|
||||
|
||||
<h3>Warning:</h3>
|
||||
|
||||
<p>The <code>value_initialized</code> implementation of Boost version 1.38.0 and older
|
||||
<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>
|
||||
|
||||
@ -340,6 +381,55 @@ the wrapped object is always performed with the <code>get()</code> idiom:</p>
|
||||
|
||||
<pre>value_initialized<int> x ;<br>get(x) = 1 ; // OK<br><br>value_initialized<int const> cx ;<br>get(x) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized<int> const x_c ;<br>get(x_c) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized<int const> const cx_c ;<br>get(cx_c) = 1 ; // ERROR: Cannot modify a const object<br></pre>
|
||||
|
||||
<h2><a name="initialized"><code>template class initialized<T></code></a></h2>
|
||||
|
||||
<pre>namespace boost {<br><br>template<class T><br>class initialized<br>{
|
||||
<br> public :
|
||||
<br> initialized() : x() {}
|
||||
<br> explicit initialized(T const & arg) : x(arg) {}
|
||||
<br> operator T const &() const;
|
||||
<br> operator T&();
|
||||
<br> T const &data() const;
|
||||
<br> T& data();
|
||||
<br> void swap( initialized& );
|
||||
<br>
|
||||
<br> private :
|
||||
<br> <i>unspecified</i> x ;
|
||||
<br>} ;
|
||||
<br>
|
||||
<br>template<class T>
|
||||
<br>T const& get ( initialized<T> const& x );
|
||||
<br>
|
||||
<br>template<class T>
|
||||
<br>T& get ( initialized<T>& x );
|
||||
<br>
|
||||
<br>template<class T>
|
||||
<br>void swap ( initialized<T>& lhs, initialized<T>& rhs );
|
||||
<br>
|
||||
<br>} // namespace boost
|
||||
<br></pre>
|
||||
|
||||
The template class <code>boost::initialized<T></code> supports both value-initialization
|
||||
and direct-initialization, so its interface is a superset of the interface
|
||||
of <code>value_initialized<T></code>: Its default-constructor
|
||||
value-initializes the wrapped object just like the default-constructor of
|
||||
<code>value_initialized<T></code>, but <code>boost::initialized<T></code>
|
||||
also offers an extra <code>explicit</code>
|
||||
constructor, which direct-initializes the wrapped object by the specified value.
|
||||
<p>
|
||||
|
||||
<code>initialized<T></code> is especially useful when the wrapped
|
||||
object must be either value-initialized or direct-initialized, depending on
|
||||
runtime conditions. For example, <code>initialized<T></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<T></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>
|
||||
@ -399,6 +489,9 @@ Special thanks to Bjö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>,
|
||||
@ -407,9 +500,9 @@ for Boost release version 1.35 (2008), offering a workaround to various compiler
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>Revised 20 February 2009</p>
|
||||
<p>Revised 30 May 2010</p>
|
||||
|
||||
<p>© Copyright Fernando Cacciola, 2002, 2009.</p>
|
||||
<p>© 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>
|
||||
@ -418,4 +511,4 @@ for Boost release version 1.35 (2008), offering a workaround to various compiler
|
||||
<br>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
@ -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) ) ;
|
||||
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;
|
||||
|
||||
|
||||
|
144
value_init_workaround_test.cpp
Normal file
144
value_init_workaround_test.cpp
Normal 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
|
||||
}
|
Reference in New Issue
Block a user