Compare commits

...

70 Commits

Author SHA1 Message Date
bf91c9bb3c Changed implementation to avoid calculating the size of the raw data buffer manually. Trim trailing spaces. 2016-07-16 14:30:45 -06:00
6e98e46e7b Fix gcc 6 warnings about invoking placement new on a buffer of insufficient size. 2016-07-16 14:30:33 -06:00
6a24b1e59c Use Boost.TypeIndex to work with type_info to avoid bunch of workarounds and non-optimal operators. Added RTTI-off tests 2016-07-16 14:29:35 -06:00
42f2a7c714 Merge to master for 1.59.0 release 2015-07-22 10:33:01 -07:00
45ec47542c Merge pull request #8 from eldiener/develop
Use ! operator directly rather than boost::mpl::not with Boost supported...
Please watch the test results, and remind me to merge to master if the tests remain clean
2015-04-27 13:00:41 -07:00
0c467707d9 Remove Borland workaround for obsolete and untested compiler/version. 2015-04-27 14:43:49 -04:00
f0ec326eb0 Use ! operator directly rather than boost::mpl::not with Boost supported compilers. 2015-04-27 04:15:31 -04:00
fde855afb0 Merge pull request #6 from MarcelRaad/patch-1
Qualify enable_if with namespace boost
2015-04-03 06:54:46 -07:00
73e4d02b00 Qualify enable_if with namespace boost
Unfortunately the change from enable_if_c to enable_if in 74c9cc9680 broke a lot of other libraries' regression tests on MSVC, which complains about ambiguous symbols.
2015-04-03 08:55:01 +02:00
001fcff9b8 Merge pull request #5 from eldiener/develop
Remove dependency on deprecated type_traits headers.
@eldiener ; please watch the test bots, and let me know if I can merge to release.
2015-04-02 07:36:10 -07:00
8cc1be159b Removed unnecessary header file include 2015-04-02 07:15:26 -04:00
74c9cc9680 Remove dependency on deprecated type_traits headers. 2015-03-30 01:47:08 -04:00
675d955364 Merge branch 'develop' 2015-01-18 19:32:44 +02:00
854f2e8d5d Fix ambiguous 'detail' errors under msvc-8.0. 2015-01-16 21:54:16 +02:00
157aaeaf23 Merge pull request #4 from apolukhin/rvalue_params
Add support for function signatures with rvalue params

Looks useful.  Tested with gcc-4.9.1, no issues.  Also with 4.9.1 c++0x.  Thanks.
2014-11-02 16:12:33 -07:00
df1db75294 Less includes from Boost.Move and more tests 2014-10-02 15:40:33 +04:00
27e9e1e372 Add support for function signatures with rvalue params 2014-09-29 20:14:06 +04:00
8f8cdae988 Merge pull request #1 from jzmaddock/patch-1
Update Jamfile.v2

I think it's okay, it's already been applied to develop and seems to be working okay.
2014-09-01 20:37:10 -06:00
02abccd686 Merge pull request #3 from danieljames/metadata
Create metadata file.
2014-09-01 20:35:09 -06:00
c4aa569cf4 Merge pull request #2 from jzmaddock/patch-2
Update Jamfile.v2
2014-08-20 15:41:02 -07:00
e38382d33e Add metadata file. 2014-08-18 14:59:11 +01:00
78f1bcc4b4 Update Jamfile.v2
There can be only one project named boost/doc - and we already have that under doc/
This fixes the PDF doc build.
2014-08-13 18:26:43 +01:00
f3d01c47bb Update Jamfile.v2
There can be only one project named boost/doc - and we already have that under doc/
This fixes the PDF doc build.
2014-08-13 18:26:08 +01:00
78eb6b1c8c Fixed two tests to work with C++11/libc++. The tests attempted to compare two ostream&, but didn't really. In c++03, both decayed to void *, which wre then compared. In c++11, the ostreams are comvertible to bool, but only explicitly, and this failed to compile. Use a custom struct with operator== instead of ostream in these tests instead. 2014-02-03 11:46:05 -08:00
a80ac7f5c5 Merge branch 'develop' 2014-02-03 11:29:22 -08:00
e9fe0b6db3 Created first merge point for git 2014-02-03 11:27:41 -08:00
9f06e35e8d Add coverity comments to silence Coverity warnings 2014-01-31 19:50:02 -08:00
250655ad6d Add 'std:' qualification to size_t. Fixes Bug #6184 2014-01-31 19:42:29 -08:00
ea19e9e745 Remove remaining occurances of BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
These evaded scripting.

[SVN r86249]
2013-10-11 23:22:36 +00:00
8d5a27fb85 Function: Remove obsolete GCC version check.
[SVN r86111]
2013-10-01 08:46:26 +00:00
8760088d44 Function: Remove obsolete MSVC version checks.
[SVN r86018]
2013-09-30 00:16:55 +00:00
9245ac2a8f Merge from trunk:
* Update documentation of Boost.Function and add info about rvalues (fixes #8505)

[SVN r84788]
2013-06-15 07:06:26 +00:00
26d278733f Update documentation of Boost.Function and add info about rvalues (refs #8505)
[SVN r84787]
2013-06-15 06:59:30 +00:00
62cce2aaaf Merge fix from trunk; Fixes #7819
[SVN r82280]
2012-12-30 01:07:13 +00:00
95a1956397 Added missing 'std::'; Refs #7819
[SVN r82273]
2012-12-29 16:36:12 +00:00
352cb183fe Merge macro changes for Boost.Function to release branch
[SVN r82054]
2012-12-17 17:50:38 +00:00
74a61f0252 Removed usage of deprecated macros in Boost.Function
[SVN r81570]
2012-11-26 18:47:49 +00:00
9e30736439 Updated to use new macro names
[SVN r81450]
2012-11-21 01:49:52 +00:00
3ac49dc978 Merge from trunk: added move assignment and move constructors to Boost.Function (fixes #7330)
[SVN r80738]
2012-09-28 18:14:00 +00:00
1ebe83a832 Merge doc fixes to release; Fixes #7244
[SVN r80694]
2012-09-24 16:36:41 +00:00
419f424959 Add move assignment and move constructors to Boost.Function (refs #7330)
[SVN r80552]
2012-09-17 04:08:18 +00:00
bfde71273b Fix typo; Refs #7244
[SVN r80077]
2012-08-18 14:26:41 +00:00
0dc186d891 Merge Change 74916 (extra semicolon) to release
[SVN r74939]
2011-10-13 18:34:19 +00:00
b31584cfb5 Merge fixes to release; Fixes #4717
[SVN r72347]
2011-06-02 15:34:54 +00:00
3193df71b9 Function: Merge from trunk.
- Remove extra definition of operator(), since it's inline anyway.  Fixes
  #4765.
- Make sure that the cv flags are copied when we copy a reference to a function
  object.  Fixes #4325
- Fully qualified function calls to avoid ambiguity with new additions to
  standard. Thanks to Conrad Poelman. Fixes #4073
- Remove iterator workaround for newer versions of Visual Age C++. Thanks to
  'ccambly'. Fixes #3912
- Fix unused variable warning for Visual C++. Fixes #3618
- Testing flag for Visual C++.
- Removed all but one old-style cast, prevents GCC warnings, but breaks GCC
  2.95.3. Fixes #3410
- Fixed tab and newline issues from inspection report.



[SVN r70361]
2011-03-21 21:32:38 +00:00
f85a3db133 Spirit: merging from trunk upto rev. 61489
[SVN r63640]
2010-07-04 22:38:38 +00:00
a0286a58c7 Merge documentation fixes.
* Use `doc/src/*.css` instead of `doc/html/*.css`.
* Remove wiki and people directories.
* Some documentation fixes.
* Left out `minimal.css` changes and boostbook changes because of clashes.


[SVN r63347]
2010-06-26 12:30:09 +00:00
1b6a5673cb Merge [58123], [58127], [58128] to release. Fixes #3666.
[SVN r58195]
2009-12-06 17:50:28 +00:00
24a7ce00a8 rm cmake from the release branch before it goes out broken. Policy dictates that you never commit to release, you commit to trunk and merge to release.
[SVN r56941]
2009-10-17 01:10:45 +00:00
c398dfceb3 Add basic copyright/license to keep cmake out of the inspection report
[SVN r55095]
2009-07-22 21:51:01 +00:00
a108a1cf26 Fix a typo.
Merged revisions 54909 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

[SVN r54912]
2009-07-12 16:13:35 +00:00
d68cc8a51c Merge various function changes from trunk.
Merged revisions 49571,50064,51743,51745,53722,54616-54619 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r49571 | noel_belcourt | 2008-11-03 18:37:49 +0000 (Mon, 03 Nov 2008) | 9 lines
  
  Both Sun and Pgi on Linux correctly put typeinfo into the std
  namespace, but function_base keys off the
  BOOST_NO_EXCEPTION_STD_NAMESPACE macro instead of the
  BOOST_NO_STD_TYPEINFO macro.  The attached patch changes
  function_base to use the typeinfo macro.  Because eVC 4.2 doesn't
  put typeinfo into the std namespace, I need to define
  BOOST_NO_STD_TYPEINFO only for this eVC version.
........
  r50064 | johnmaddock | 2008-12-02 10:10:46 +0000 (Tue, 02 Dec 2008) | 1 line
  
  Fix -Wundef warning and suspect usage of BOOST_STRICT_CONFIG.
........
  r51743 | dgregor | 2009-03-13 05:23:53 +0000 (Fri, 13 Mar 2009) | 11 lines
  
  Implement an optimization that David Abrahams and myself came up with,
  where Boost.Function uses a bit in the vtable pointer to indicate when
  the target function object has a trivial copy constructor, trivial
  destructor, and fits within the small object buffer. In this case, we
  just copy the bits of the function object rather than performing an
  indirect call to the manager.
  
  This results in a 60% speedup on a micro-benchmark that copies and
  calls such function objects repeatedly.
........
  r51745 | dgregor | 2009-03-13 05:49:02 +0000 (Fri, 13 Mar 2009) | 7 lines
  
  Make Boost.Function compile under BOOST_NO_EXCEPTIONS.
  
  Fixes #2499
  Fixes #2494
  Fixes #2469
  Fixes #2466
........
  r53722 | vladimir_prus | 2009-06-07 16:44:50 +0100 (Sun, 07 Jun 2009) | 4 lines
  
  Make Boost.Function compile with disabled exceptions.
  
  Closes #2900. Patch from Gabi Davar.
........
  r54616 | danieljames | 2009-07-03 23:20:26 +0100 (Fri, 03 Jul 2009) | 3 lines
  
  When copying boost::ref, copy even when the referenced function is empty. Fixes #2642
  
  Patch by Steven Watanabe
........
  r54617 | danieljames | 2009-07-03 23:20:52 +0100 (Fri, 03 Jul 2009) | 6 lines
  
  Add 'and later versions' to support info for GCC and Visual C++. Fixes #2847.
  
  I didn't explicitly specify the versions since no one's updating this
  list and it's highly unlikely that a future version will break this. The
  same could probably be done for the other compilers but I don't know
  them very well so I'm leaving them alone.
........
  r54618 | danieljames | 2009-07-03 23:21:40 +0100 (Fri, 03 Jul 2009) | 4 lines
  
  Fix Boost.Function unit tests for C++0x. Fixes #3012
  
  Based on a patch from Richard Webb. Changed a bit so that it also
  works for the Visual C++ 10 beta.
........
  r54619 | danieljames | 2009-07-03 23:22:03 +0100 (Fri, 03 Jul 2009) | 3 lines
  
  Work around Visual C++ copy constructor bug. Fixes #2929.
  
  Based on the patch by Steven Watanabe.
........


[SVN r54824]
2009-07-08 23:23:52 +00:00
cca7b35712 Add missing #pragma warning(pop) in Boost.Function.
Merged revisions 53694 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r53694 | danieljames | 2009-06-06 16:31:47 +0100 (Sat, 06 Jun 2009) | 1 line
  
  Add missing #pragma warning(pop). Fixes #2767.
........


[SVN r54410]
2009-06-27 10:46:20 +00:00
9bb12ce87a Fixed almost all tab and min/max issues found by inspect tool
[SVN r53142]
2009-05-20 19:41:20 +00:00
467ae9613f Merge PDF build changes from Trunk.
[SVN r51417]
2009-02-23 18:39:32 +00:00
2fd383cd2e merge of cmake build files from trunk per beman
[SVN r50756]
2009-01-24 18:57:20 +00:00
587658b047 Merge Boost.Function fixes from trunk
[SVN r49361]
2008-10-16 13:21:50 +00:00
83309a36c7 Merge Boost.Function from the trunk
[SVN r47422]
2008-07-14 18:32:29 +00:00
bfdb5b161d Merged fixes for Function, Signals, and MPI from trunk. See #1499, see #1416, see #1486
[SVN r42031]
2007-12-14 14:48:14 +00:00
c4539395fe Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41369]
2007-11-25 18:07:19 +00:00
6147e7ddcc Starting point for releases
[SVN r39706]
2007-10-05 14:25:06 +00:00
1b60e82b2f This commit was manufactured by cvs2svn to create tag
'Version_1_34_1'.

[SVN r38286]
2007-07-24 19:28:14 +00:00
7581949360 Patches from Trac #583.
[SVN r37846]
2007-06-01 16:12:08 +00:00
0b2aeda226 Merged copyright and license addition
[SVN r35907]
2006-11-07 19:27:00 +00:00
2ecd62c612 Remove obsolete Boost.Build v1 files.
[SVN r35880]
2006-11-06 17:10:46 +00:00
47033bd162 Fix inspection problems
[SVN r35827]
2006-11-03 19:41:10 +00:00
c7d5016022 Eliminate MSVC 8.0 warning
[SVN r35588]
2006-10-13 14:29:56 +00:00
d92355cca2 Suppress annoying MSVC warnings
[SVN r35424]
2006-09-29 17:23:28 +00:00
0123f84bff Suppress annoying MSVC warnings
[SVN r35423]
2006-09-29 17:23:17 +00:00
0207da8008 This commit was manufactured by cvs2svn to create branch 'RC_1_34_0'.
[SVN r33417]
2006-03-21 02:26:31 +00:00
12 changed files with 591 additions and 285 deletions

View File

@ -3,7 +3,7 @@
# Distributed under the Boost Software License, Version 1.0. # Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at # (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt) # http://www.boost.org/LICENSE_1_0.txt)
project boost/doc ; project function/doc ;
import boostbook : boostbook ; import boostbook : boostbook ;
boostbook function-doc boostbook function-doc

View File

@ -13,6 +13,15 @@
<itemizedlist spacing="compact"> <itemizedlist spacing="compact">
<listitem><para><bold>Version 1.52.0</bold>: </para>
<itemizedlist spacing="compact">
<listitem><para>Move constructors and move assignment
operators added (only for compilers with C++11 rvalue
references support). Original patch
contributed by Antony Polukhin.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para><bold>Version 1.37.0</bold>: </para> <listitem><para><bold>Version 1.37.0</bold>: </para>
<itemizedlist spacing="compact"> <itemizedlist spacing="compact">
<listitem><para>Improved the performance of Boost.Function's <listitem><para>Improved the performance of Boost.Function's

View File

@ -58,7 +58,7 @@
<para>A function object <code>f</code> of <para>A function object <code>f</code> of
type <code>F</code> is type <code>F</code> is
<emphasis>stateless</emphasis> if it is a function pointer or if <emphasis>stateless</emphasis> if it is a function pointer or if
<code><classname>boost::is_stateless</classname>&lt;T&gt;</code> <code><classname>boost::is_stateless</classname>&lt;F&gt;</code>
is true. The construction of or copy to a Boost.Function object is true. The construction of or copy to a Boost.Function object
from a stateless function object will not cause exceptions to be from a stateless function object will not cause exceptions to be
thrown and will not allocate any storage. thrown and will not allocate any storage.
@ -128,7 +128,7 @@
<method name="target_type" cv="const"> <method name="target_type" cv="const">
<type>const std::type_info&amp;</type> <type>const std::type_info&amp;</type>
<returns><simpara><code>typeid</code> of the target function object, or <code>typeid(void)</code> if <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></returns> <returns><simpara><code>typeid</code> of the target function object, or <code>typeid(void)</code> if <code>this-&gt;<methodname>empty</methodname>()</code>. Works even with RTTI off.</simpara></returns>
<throws><simpara>Will not throw.</simpara></throws> <throws><simpara>Will not throw.</simpara></throws>
</method> </method>
</method-group> </method-group>
@ -203,6 +203,15 @@
<throws><simpara>Will not throw unless copying the target of <code>f</code> throws.</simpara></throws> <throws><simpara>Will not throw unless copying the target of <code>f</code> throws.</simpara></throws>
</constructor> </constructor>
<constructor>
<parameter name="f">
<paramtype><classname>functionN</classname>&amp;&amp;</paramtype>
</parameter>
<requires><simpara>C++11 compatible compiler.</simpara></requires>
<postconditions><simpara>Moves the value from <code>f</code> to <code>*this</code>. If the argument has its function object allocated on the heap, its buffer will be assigned to <code>*this</code> leaving argument empty.</simpara></postconditions>
<throws><simpara>Will not throw unless argument has its function object allocated not on the heap and copying the target of <code>f</code> throws.</simpara></throws>
</constructor>
<constructor> <constructor>
<template> <template>
<template-type-parameter name="F"/> <template-type-parameter name="F"/>
@ -236,6 +245,15 @@
</parameter> </parameter>
<postconditions><simpara>If copy construction does not throw, <code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></postconditions> <postconditions><simpara>If copy construction does not throw, <code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></postconditions>
</copy-assignment> </copy-assignment>
<copy-assignment>
<parameter name="f">
<paramtype><classname>functionN</classname>&amp;&amp;</paramtype>
</parameter>
<requires><simpara>C++11 compatible compiler.</simpara></requires>
<postconditions><simpara>Moves the value from <code>f</code> to <code>*this</code>. If the argument has its function object allocated on the heap, its buffer will be assigned to <code>*this</code> leaving argument empty.</simpara></postconditions>
<throws><simpara>Will not throw unless argument has its function object allocated not on the heap and copying the target of <code>f</code> throws.</simpara></throws>
</copy-assignment>
<method-group name="modifiers"> <method-group name="modifiers">
<method name="swap"> <method name="swap">
@ -607,7 +625,16 @@
<postconditions><simpara>Contains a copy of the <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>.</simpara></postconditions> <postconditions><simpara>Contains a copy of the <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>.</simpara></postconditions>
<throws><simpara>Will not throw unless copying the target of <code>f</code> throws.</simpara></throws> <throws><simpara>Will not throw unless copying the target of <code>f</code> throws.</simpara></throws>
</constructor> </constructor>
<constructor>
<parameter name="f">
<paramtype><classname>functionN</classname>&amp;&amp;</paramtype>
</parameter>
<requires><simpara>C++11 compatible compiler.</simpara></requires>
<postconditions><simpara>Moves the value from <code>f</code> to <code>*this</code>. If the argument has its function object allocated on the heap, its buffer will be assigned to <code>*this</code> leaving argument empty.</simpara></postconditions>
<throws><simpara>Will not throw unless argument has its function object allocated not on the heap and copying the target of <code>f</code> throws.</simpara></throws>
</constructor>
<constructor> <constructor>
<parameter name="f"> <parameter name="f">
<paramtype>const <classname>function</classname>&amp;</paramtype> <paramtype>const <classname>function</classname>&amp;</paramtype>
@ -616,6 +643,15 @@
<throws><simpara>Will not throw unless copying the target of <code>f</code> throws.</simpara></throws> <throws><simpara>Will not throw unless copying the target of <code>f</code> throws.</simpara></throws>
</constructor> </constructor>
<constructor>
<parameter name="f">
<paramtype><classname>function</classname>&amp;&amp;</paramtype>
</parameter>
<requires><simpara>C++11 compatible compiler.</simpara></requires>
<postconditions><simpara>Moves the value from <code>f</code> to <code>*this</code>. If the argument has its function object allocated on the heap, its buffer will be assigned to <code>*this</code> leaving argument empty.</simpara></postconditions>
<throws><simpara>Will not throw unless argument has its function object allocated not on the heap and copying the target of <code>f</code> throws.</simpara></throws>
</constructor>
<constructor> <constructor>
<template> <template>
<template-type-parameter name="F"/> <template-type-parameter name="F"/>
@ -645,10 +681,19 @@
<copy-assignment> <copy-assignment>
<parameter name="f"> <parameter name="f">
<paramtype>const <classname>function</classname>&amp;</paramtype> <paramtype>const <classname>functionN</classname>&amp;</paramtype>
</parameter> </parameter>
<postconditions><simpara>If copy construction does not throw, <code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></postconditions> <postconditions><simpara>If copy construction does not throw, <code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></postconditions>
</copy-assignment> </copy-assignment>
<copy-assignment>
<parameter name="f">
<paramtype><classname>functionN</classname>&amp;&amp;</paramtype>
</parameter>
<requires><simpara>C++11 compatible compiler.</simpara></requires>
<postconditions><simpara>Moves the value from <code>f</code> to <code>*this</code>. If the argument has its function object allocated on the heap, its buffer will be assigned to <code>*this</code> leaving argument empty.</simpara></postconditions>
<throws><simpara>Will not throw unless argument has its function object allocated not on the heap and copying the target of <code>f</code> throws.</simpara></throws>
</copy-assignment>
<copy-assignment> <copy-assignment>
<parameter name="f"> <parameter name="f">
@ -657,6 +702,15 @@
<postconditions><simpara>If copy construction of the target of <code>f</code> does not throw, <code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>. </simpara></postconditions> <postconditions><simpara>If copy construction of the target of <code>f</code> does not throw, <code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>. </simpara></postconditions>
<throws><simpara>Will not throw when the target of <code>f</code> is a stateless function object or a reference to the function object. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></throws> <throws><simpara>Will not throw when the target of <code>f</code> is a stateless function object or a reference to the function object. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></throws>
</copy-assignment> </copy-assignment>
<copy-assignment>
<parameter name="f">
<paramtype><classname>function</classname>&amp;&amp;</paramtype>
</parameter>
<requires><simpara>C++11 compatible compiler.</simpara></requires>
<postconditions><simpara>Moves the value from <code>f</code> to <code>*this</code>. If the argument has its function object allocated on the heap, its buffer will be assigned to <code>*this</code> leaving argument empty.</simpara></postconditions>
<throws><simpara>Will not throw unless argument has its function object allocated not on the heap and copying the target of <code>f</code> throws.</simpara></throws>
</copy-assignment>
<method-group name="modifiers"> <method-group name="modifiers">
<method name="swap"> <method name="swap">

View File

@ -16,16 +16,15 @@
#include <memory> #include <memory>
#include <new> #include <new>
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/integer.hpp> #include <boost/integer.hpp>
#include <boost/type_index.hpp>
#include <boost/type_traits/has_trivial_copy.hpp> #include <boost/type_traits/has_trivial_copy.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp> #include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/type_traits/is_const.hpp> #include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_integral.hpp> #include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_volatile.hpp> #include <boost/type_traits/is_volatile.hpp>
#include <boost/type_traits/composite_traits.hpp> #include <boost/type_traits/composite_traits.hpp>
#include <boost/type_traits/ice.hpp>
#include <boost/ref.hpp> #include <boost/ref.hpp>
#include <boost/mpl/if.hpp> #include <boost/mpl/if.hpp>
#include <boost/detail/workaround.hpp> #include <boost/detail/workaround.hpp>
@ -42,49 +41,18 @@
# pragma warning( push ) # pragma warning( push )
# pragma warning( disable : 4793 ) // complaint about native code generation # pragma warning( disable : 4793 ) // complaint about native code generation
# pragma warning( disable : 4127 ) // "conditional expression is constant" # pragma warning( disable : 4127 ) // "conditional expression is constant"
#endif
// Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info.
#ifdef BOOST_NO_STD_TYPEINFO
// Embedded VC++ does not have type_info in namespace std
# define BOOST_FUNCTION_STD_NS
#else
# define BOOST_FUNCTION_STD_NS std
#endif #endif
// Borrowed from Boost.Python library: determines the cases where we #if defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
// need to use std::type_info::name to compare instead of operator==.
#if defined( BOOST_NO_TYPEID )
# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
#elif (defined(__GNUC__) && __GNUC__ >= 3) \
|| defined(_AIX) \
|| ( defined(__sgi) && defined(__host_mips))
# include <cstring>
# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \
(std::strcmp((X).name(),(Y).name()) == 0)
# else
# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
#endif
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
# define BOOST_FUNCTION_TARGET_FIX(x) x # define BOOST_FUNCTION_TARGET_FIX(x) x
#else #else
# define BOOST_FUNCTION_TARGET_FIX(x) # define BOOST_FUNCTION_TARGET_FIX(x)
#endif // not MSVC #endif // __ICL etc
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x5A0)
# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \ # define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \ typename ::boost::enable_if_c< \
(::boost::is_integral<Functor>::value)>::value), \ !(::boost::is_integral<Functor>::value), \
Type>::type Type>::type
#else
// BCC doesn't recognize this depends on a template argument and complains
// about the use of 'typename'
# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
::boost::enable_if_c<(::boost::type_traits::ice_not< \
(::boost::is_integral<Functor>::value)>::value), \
Type>::type
#endif
namespace boost { namespace boost {
namespace detail { namespace detail {
@ -97,15 +65,16 @@ namespace boost {
* object pointers, and a structure that resembles a bound * object pointers, and a structure that resembles a bound
* member function pointer. * member function pointer.
*/ */
union function_buffer union function_buffer_members
{ {
// For pointers to function objects // For pointers to function objects
mutable void* obj_ptr; typedef void* obj_ptr_t;
mutable obj_ptr_t obj_ptr;
// For pointers to std::type_info objects // For pointers to std::type_info objects
struct type_t { struct type_t {
// (get_functor_type_tag, check_functor_type_tag). // (get_functor_type_tag, check_functor_type_tag).
const detail::sp_typeinfo* type; const boost::typeindex::type_info* type;
// Whether the type is const-qualified. // Whether the type is const-qualified.
bool const_qualified; bool const_qualified;
@ -114,7 +83,8 @@ namespace boost {
} type; } type;
// For function pointers of all kinds // For function pointers of all kinds
mutable void (*func_ptr)(); typedef void (*func_ptr_t)();
mutable func_ptr_t func_ptr;
// For bound member pointers // For bound member pointers
struct bound_memfunc_ptr_t { struct bound_memfunc_ptr_t {
@ -129,9 +99,15 @@ namespace boost {
bool is_const_qualified; bool is_const_qualified;
bool is_volatile_qualified; bool is_volatile_qualified;
} obj_ref; } obj_ref;
};
union function_buffer
{
// Type-specific union members
mutable function_buffer_members members;
// To relax aliasing constraints // To relax aliasing constraints
mutable char data; mutable char data[sizeof(function_buffer_members)];
}; };
/** /**
@ -198,45 +174,42 @@ namespace boost {
struct reference_manager struct reference_manager
{ {
static inline void static inline void
manage(const function_buffer& in_buffer, function_buffer& out_buffer, manage(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
switch (op) { switch (op) {
case clone_functor_tag: case clone_functor_tag:
out_buffer.obj_ref = in_buffer.obj_ref; out_buffer.members.obj_ref = in_buffer.members.obj_ref;
return; return;
case move_functor_tag: case move_functor_tag:
out_buffer.obj_ref = in_buffer.obj_ref; out_buffer.members.obj_ref = in_buffer.members.obj_ref;
in_buffer.obj_ref.obj_ptr = 0; in_buffer.members.obj_ref.obj_ptr = 0;
return; return;
case destroy_functor_tag: case destroy_functor_tag:
out_buffer.obj_ref.obj_ptr = 0; out_buffer.members.obj_ref.obj_ptr = 0;
return; return;
case check_functor_type_tag: case check_functor_type_tag:
{ {
const detail::sp_typeinfo& check_type
= *out_buffer.type.type;
// Check whether we have the same type. We can add // Check whether we have the same type. We can add
// cv-qualifiers, but we can't take them away. // cv-qualifiers, but we can't take them away.
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(F)) if (*out_buffer.members.type.type == boost::typeindex::type_id<F>()
&& (!in_buffer.obj_ref.is_const_qualified && (!in_buffer.members.obj_ref.is_const_qualified
|| out_buffer.type.const_qualified) || out_buffer.members.type.const_qualified)
&& (!in_buffer.obj_ref.is_volatile_qualified && (!in_buffer.members.obj_ref.is_volatile_qualified
|| out_buffer.type.volatile_qualified)) || out_buffer.members.type.volatile_qualified))
out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr; out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} }
return; return;
case get_functor_type_tag: case get_functor_type_tag:
out_buffer.type.type = &BOOST_SP_TYPEID(F); out_buffer.members.type.type = &boost::typeindex::type_id<F>().type_info();
out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified; out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified;
out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified; out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified;
return; return;
} }
} }
@ -250,9 +223,9 @@ namespace boost {
struct function_allows_small_object_optimization struct function_allows_small_object_optimization
{ {
BOOST_STATIC_CONSTANT BOOST_STATIC_CONSTANT
(bool, (bool,
value = ((sizeof(F) <= sizeof(function_buffer) && value = ((sizeof(F) <= sizeof(function_buffer) &&
(alignment_of<function_buffer>::value (alignment_of<function_buffer>::value
% alignment_of<F>::value == 0)))); % alignment_of<F>::value == 0))));
}; };
@ -264,7 +237,7 @@ namespace boost {
A(a) A(a)
{ {
} }
functor_wrapper(const functor_wrapper& f) : functor_wrapper(const functor_wrapper& f) :
F(static_cast<const F&>(f)), F(static_cast<const F&>(f)),
A(static_cast<const A&>(f)) A(static_cast<const A&>(f))
@ -283,61 +256,57 @@ namespace boost {
// Function pointers // Function pointers
static inline void static inline void
manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer, manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
if (op == clone_functor_tag) if (op == clone_functor_tag)
out_buffer.func_ptr = in_buffer.func_ptr; out_buffer.members.func_ptr = in_buffer.members.func_ptr;
else if (op == move_functor_tag) { else if (op == move_functor_tag) {
out_buffer.func_ptr = in_buffer.func_ptr; out_buffer.members.func_ptr = in_buffer.members.func_ptr;
in_buffer.func_ptr = 0; in_buffer.members.func_ptr = 0;
} else if (op == destroy_functor_tag) } else if (op == destroy_functor_tag)
out_buffer.func_ptr = 0; out_buffer.members.func_ptr = 0;
else if (op == check_functor_type_tag) { else if (op == check_functor_type_tag) {
const detail::sp_typeinfo& check_type if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
= *out_buffer.type.type; out_buffer.members.obj_ptr = &in_buffer.members.func_ptr;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
out_buffer.obj_ptr = &in_buffer.func_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.type.type = &BOOST_SP_TYPEID(Functor); out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
} }
} }
// Function objects that fit in the small-object buffer. // Function objects that fit in the small-object buffer.
static inline void static inline void
manage_small(const function_buffer& in_buffer, function_buffer& out_buffer, manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
if (op == clone_functor_tag || op == move_functor_tag) { if (op == clone_functor_tag || op == move_functor_tag) {
const functor_type* in_functor = const functor_type* in_functor =
reinterpret_cast<const functor_type*>(&in_buffer.data); reinterpret_cast<const functor_type*>(in_buffer.data);
new (reinterpret_cast<void*>(&out_buffer.data)) functor_type(*in_functor); new (reinterpret_cast<void*>(out_buffer.data)) functor_type(*in_functor);
if (op == move_functor_tag) { if (op == move_functor_tag) {
functor_type* f = reinterpret_cast<functor_type*>(&in_buffer.data); functor_type* f = reinterpret_cast<functor_type*>(in_buffer.data);
(void)f; // suppress warning about the value of f not being used (MSVC) (void)f; // suppress warning about the value of f not being used (MSVC)
f->~Functor(); f->~Functor();
} }
} else if (op == destroy_functor_tag) { } else if (op == destroy_functor_tag) {
// Some compilers (Borland, vc6, ...) are unhappy with ~functor_type. // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
functor_type* f = reinterpret_cast<functor_type*>(&out_buffer.data); functor_type* f = reinterpret_cast<functor_type*>(out_buffer.data);
(void)f; // suppress warning about the value of f not being used (MSVC) (void)f; // suppress warning about the value of f not being used (MSVC)
f->~Functor(); f->~Functor();
} else if (op == check_functor_type_tag) { } else if (op == check_functor_type_tag) {
const detail::sp_typeinfo& check_type if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
= *out_buffer.type.type; out_buffer.members.obj_ptr = in_buffer.data;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
out_buffer.obj_ptr = &in_buffer.data;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.type.type = &BOOST_SP_TYPEID(Functor); out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
} }
} }
}; };
@ -350,7 +319,7 @@ namespace boost {
// Function pointers // Function pointers
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_ptr_tag) functor_manager_operation_type op, function_ptr_tag)
{ {
functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op); functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
@ -358,15 +327,15 @@ namespace boost {
// Function objects that fit in the small-object buffer. // Function objects that fit in the small-object buffer.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::true_) functor_manager_operation_type op, mpl::true_)
{ {
functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op); functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
} }
// Function objects that require heap allocation // Function objects that require heap allocation
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::false_) functor_manager_operation_type op, mpl::false_)
{ {
if (op == clone_functor_tag) { if (op == clone_functor_tag) {
@ -376,29 +345,27 @@ namespace boost {
// jewillco: Changing this to static_cast because GCC 2.95.3 is // jewillco: Changing this to static_cast because GCC 2.95.3 is
// obsolete. // obsolete.
const functor_type* f = const functor_type* f =
static_cast<const functor_type*>(in_buffer.obj_ptr); static_cast<const functor_type*>(in_buffer.members.obj_ptr);
functor_type* new_f = new functor_type(*f); functor_type* new_f = new functor_type(*f);
out_buffer.obj_ptr = new_f; out_buffer.members.obj_ptr = new_f;
} else if (op == move_functor_tag) { } else if (op == move_functor_tag) {
out_buffer.obj_ptr = in_buffer.obj_ptr; out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
in_buffer.obj_ptr = 0; in_buffer.members.obj_ptr = 0;
} else if (op == destroy_functor_tag) { } else if (op == destroy_functor_tag) {
/* Cast from the void pointer to the functor pointer type */ /* Cast from the void pointer to the functor pointer type */
functor_type* f = functor_type* f =
static_cast<functor_type*>(out_buffer.obj_ptr); static_cast<functor_type*>(out_buffer.members.obj_ptr);
delete f; delete f;
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else if (op == check_functor_type_tag) { } else if (op == check_functor_type_tag) {
const detail::sp_typeinfo& check_type if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
= *out_buffer.type.type; out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
out_buffer.obj_ptr = in_buffer.obj_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.type.type = &BOOST_SP_TYPEID(Functor); out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
} }
} }
@ -406,7 +373,7 @@ namespace boost {
// object can use the small-object optimization buffer or // object can use the small-object optimization buffer or
// whether we need to allocate it on the heap. // whether we need to allocate it on the heap.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_obj_tag) functor_manager_operation_type op, function_obj_tag)
{ {
manager(in_buffer, out_buffer, op, manager(in_buffer, out_buffer, op,
@ -415,7 +382,7 @@ namespace boost {
// For member pointers, we use the small-object optimization buffer. // For member pointers, we use the small-object optimization buffer.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, member_ptr_tag) functor_manager_operation_type op, member_ptr_tag)
{ {
manager(in_buffer, out_buffer, op, mpl::true_()); manager(in_buffer, out_buffer, op, mpl::true_());
@ -425,15 +392,15 @@ namespace boost {
/* Dispatch to an appropriate manager based on whether we have a /* Dispatch to an appropriate manager based on whether we have a
function pointer or a function object pointer. */ function pointer or a function object pointer. */
static inline void static inline void
manage(const function_buffer& in_buffer, function_buffer& out_buffer, manage(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
typedef typename get_function_tag<functor_type>::type tag_type; typedef typename get_function_tag<functor_type>::type tag_type;
switch (op) { switch (op) {
case get_functor_type_tag: case get_functor_type_tag:
out_buffer.type.type = &BOOST_SP_TYPEID(functor_type); out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
return; return;
default: default:
@ -451,7 +418,7 @@ namespace boost {
// Function pointers // Function pointers
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_ptr_tag) functor_manager_operation_type op, function_ptr_tag)
{ {
functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op); functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
@ -459,15 +426,15 @@ namespace boost {
// Function objects that fit in the small-object buffer. // Function objects that fit in the small-object buffer.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::true_) functor_manager_operation_type op, mpl::true_)
{ {
functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op); functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
} }
// Function objects that require heap allocation // Function objects that require heap allocation
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::false_) functor_manager_operation_type op, mpl::false_)
{ {
typedef functor_wrapper<Functor,Allocator> functor_wrapper_type; typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
@ -480,36 +447,34 @@ namespace boost {
// GCC 2.95.3 gets the CV qualifiers wrong here, so we // GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do. // can't do the static_cast that we should do.
const functor_wrapper_type* f = const functor_wrapper_type* f =
static_cast<const functor_wrapper_type*>(in_buffer.obj_ptr); static_cast<const functor_wrapper_type*>(in_buffer.members.obj_ptr);
wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f)); wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
wrapper_allocator.construct(copy, *f); wrapper_allocator.construct(copy, *f);
// Get back to the original pointer type // Get back to the original pointer type
functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy); functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
out_buffer.obj_ptr = new_f; out_buffer.members.obj_ptr = new_f;
} else if (op == move_functor_tag) { } else if (op == move_functor_tag) {
out_buffer.obj_ptr = in_buffer.obj_ptr; out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
in_buffer.obj_ptr = 0; in_buffer.members.obj_ptr = 0;
} else if (op == destroy_functor_tag) { } else if (op == destroy_functor_tag) {
/* Cast from the void pointer to the functor_wrapper_type */ /* Cast from the void pointer to the functor_wrapper_type */
functor_wrapper_type* victim = functor_wrapper_type* victim =
static_cast<functor_wrapper_type*>(in_buffer.obj_ptr); static_cast<functor_wrapper_type*>(in_buffer.members.obj_ptr);
wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim)); wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
wrapper_allocator.destroy(victim); wrapper_allocator.destroy(victim);
wrapper_allocator.deallocate(victim,1); wrapper_allocator.deallocate(victim,1);
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else if (op == check_functor_type_tag) { } else if (op == check_functor_type_tag) {
const detail::sp_typeinfo& check_type if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
= *out_buffer.type.type; out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
out_buffer.obj_ptr = in_buffer.obj_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.type.type = &BOOST_SP_TYPEID(Functor); out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
} }
} }
@ -517,7 +482,7 @@ namespace boost {
// object can use the small-object optimization buffer or // object can use the small-object optimization buffer or
// whether we need to allocate it on the heap. // whether we need to allocate it on the heap.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_obj_tag) functor_manager_operation_type op, function_obj_tag)
{ {
manager(in_buffer, out_buffer, op, manager(in_buffer, out_buffer, op,
@ -528,15 +493,15 @@ namespace boost {
/* Dispatch to an appropriate manager based on whether we have a /* Dispatch to an appropriate manager based on whether we have a
function pointer or a function object pointer. */ function pointer or a function object pointer. */
static inline void static inline void
manage(const function_buffer& in_buffer, function_buffer& out_buffer, manage(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
typedef typename get_function_tag<functor_type>::type tag_type; typedef typename get_function_tag<functor_type>::type tag_type;
switch (op) { switch (op) {
case get_functor_type_tag: case get_functor_type_tag:
out_buffer.type.type = &BOOST_SP_TYPEID(functor_type); out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
return; return;
default: default:
@ -614,8 +579,8 @@ namespace boost {
*/ */
struct vtable_base struct vtable_base
{ {
void (*manager)(const function_buffer& in_buffer, void (*manager)(const function_buffer& in_buffer,
function_buffer& out_buffer, function_buffer& out_buffer,
functor_manager_operation_type op); functor_manager_operation_type op);
}; };
} // end namespace function } // end namespace function
@ -635,15 +600,15 @@ public:
/** Determine if the function is empty (i.e., has no target). */ /** Determine if the function is empty (i.e., has no target). */
bool empty() const { return !vtable; } bool empty() const { return !vtable; }
/** Retrieve the type of the stored function object, or BOOST_SP_TYPEID(void) /** Retrieve the type of the stored function object, or type_id<void>()
if this is empty. */ if this is empty. */
const detail::sp_typeinfo& target_type() const const boost::typeindex::type_info& target_type() const
{ {
if (!vtable) return BOOST_SP_TYPEID(void); if (!vtable) return boost::typeindex::type_id<void>().type_info();
detail::function::function_buffer type; detail::function::function_buffer type;
get_vtable()->manager(functor, type, detail::function::get_functor_type_tag); get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
return *type.type.type; return *type.members.type.type;
} }
template<typename Functor> template<typename Functor>
@ -652,42 +617,34 @@ public:
if (!vtable) return 0; if (!vtable) return 0;
detail::function::function_buffer type_result; detail::function::function_buffer type_result;
type_result.type.type = &BOOST_SP_TYPEID(Functor); type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
type_result.type.const_qualified = is_const<Functor>::value; type_result.members.type.const_qualified = is_const<Functor>::value;
type_result.type.volatile_qualified = is_volatile<Functor>::value; type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
get_vtable()->manager(functor, type_result, get_vtable()->manager(functor, type_result,
detail::function::check_functor_type_tag); detail::function::check_functor_type_tag);
return static_cast<Functor*>(type_result.obj_ptr); return static_cast<Functor*>(type_result.members.obj_ptr);
} }
template<typename Functor> template<typename Functor>
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
const Functor* target( Functor * = 0 ) const
#else
const Functor* target() const const Functor* target() const
#endif
{ {
if (!vtable) return 0; if (!vtable) return 0;
detail::function::function_buffer type_result; detail::function::function_buffer type_result;
type_result.type.type = &BOOST_SP_TYPEID(Functor); type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
type_result.type.const_qualified = true; type_result.members.type.const_qualified = true;
type_result.type.volatile_qualified = is_volatile<Functor>::value; type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
get_vtable()->manager(functor, type_result, get_vtable()->manager(functor, type_result,
detail::function::check_functor_type_tag); detail::function::check_functor_type_tag);
// GCC 2.95.3 gets the CV qualifiers wrong here, so we // GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do. // can't do the static_cast that we should do.
return static_cast<const Functor*>(type_result.obj_ptr); return static_cast<const Functor*>(type_result.members.obj_ptr);
} }
template<typename F> template<typename F>
bool contains(const F& f) const bool contains(const F& f) const
{ {
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
if (const F* fp = this->target( (F*)0 ))
#else
if (const F* fp = this->template target<F>()) if (const F* fp = this->template target<F>())
#endif
{ {
return function_equal(*fp, f); return function_equal(*fp, f);
} else { } else {
@ -901,10 +858,9 @@ namespace detail {
} // end namespace boost } // end namespace boost
#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
#undef BOOST_FUNCTION_COMPARE_TYPE_ID
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
# pragma warning( pop ) # pragma warning( pop )
#endif #endif
#endif // BOOST_FUNCTION_BASE_HEADER #endif // BOOST_FUNCTION_BASE_HEADER

View File

@ -19,8 +19,7 @@ namespace boost { namespace python { namespace objects {
}}} }}}
#endif #endif
#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ #if defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
|| defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
|| !(defined(BOOST_STRICT_CONFIG) || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540) || !(defined(BOOST_STRICT_CONFIG) || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
# define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX # define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
#endif #endif

View File

@ -16,7 +16,7 @@
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
# pragma warning( push ) # pragma warning( push )
# pragma warning( disable : 4127 ) // "conditional expression is constant" # pragma warning( disable : 4127 ) // "conditional expression is constant"
#endif #endif
#define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T) #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
@ -26,7 +26,13 @@
#define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY) #define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY)
#define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a) #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
# define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
#else
# include <boost/move/utility_core.hpp>
# define BOOST_FUNCTION_ARG(J,I,D) ::boost::forward< BOOST_PP_CAT(T,I) >(BOOST_PP_CAT(a,I))
# define BOOST_FUNCTION_ARGS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG,BOOST_PP_EMPTY)
#endif
#define BOOST_FUNCTION_ARG_TYPE(J,I,D) \ #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type); typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type);
@ -91,7 +97,7 @@ namespace boost {
static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr); FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr);
return f(BOOST_FUNCTION_ARGS); return f(BOOST_FUNCTION_ARGS);
} }
}; };
@ -108,7 +114,7 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr); FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr);
BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
} }
}; };
@ -126,9 +132,9 @@ namespace boost {
{ {
FunctionObj* f; FunctionObj* f;
if (function_allows_small_object_optimization<FunctionObj>::value) if (function_allows_small_object_optimization<FunctionObj>::value)
f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data); f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
else else
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
return (*f)(BOOST_FUNCTION_ARGS); return (*f)(BOOST_FUNCTION_ARGS);
} }
}; };
@ -147,9 +153,9 @@ namespace boost {
{ {
FunctionObj* f; FunctionObj* f;
if (function_allows_small_object_optimization<FunctionObj>::value) if (function_allows_small_object_optimization<FunctionObj>::value)
f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data); f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
else else
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
} }
}; };
@ -165,8 +171,8 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionObj* f = FunctionObj* f =
reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
return (*f)(BOOST_FUNCTION_ARGS); return (*f)(BOOST_FUNCTION_ARGS);
} }
}; };
@ -183,8 +189,8 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionObj* f = FunctionObj* f =
reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
} }
}; };
@ -202,8 +208,8 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
MemberPtr* f = MemberPtr* f =
reinterpret_cast<MemberPtr*>(&function_obj_ptr.data); reinterpret_cast<MemberPtr*>(function_obj_ptr.data);
return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS); return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
} }
}; };
@ -220,8 +226,8 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
MemberPtr* f = MemberPtr* f =
reinterpret_cast<MemberPtr*>(&function_obj_ptr.data); reinterpret_cast<MemberPtr*>(function_obj_ptr.data);
BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
} }
}; };
@ -316,7 +322,7 @@ namespace boost {
/* Given the tag returned by get_function_tag, retrieve the /* Given the tag returned by get_function_tag, retrieve the
actual invoker that will be used for the given function actual invoker that will be used for the given function
object. object.
Each specialization contains an "apply" nested class template Each specialization contains an "apply" nested class template
that accepts the function object, return type, function that accepts the function object, return type, function
@ -507,21 +513,21 @@ namespace boost {
private: private:
// Function pointers // Function pointers
template<typename FunctionPtr> template<typename FunctionPtr>
bool bool
assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
{ {
this->clear(functor); this->clear(functor);
if (f) { if (f) {
// should be a reinterpret cast, but some compilers insist // should be a reinterpret cast, but some compilers insist
// on giving cv-qualifiers to free functions // on giving cv-qualifiers to free functions
functor.func_ptr = reinterpret_cast<void (*)()>(f); functor.members.func_ptr = reinterpret_cast<void (*)()>(f);
return true; return true;
} else { } else {
return false; return false;
} }
} }
template<typename FunctionPtr,typename Allocator> template<typename FunctionPtr,typename Allocator>
bool bool
assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const
{ {
return assign_to(f,functor,function_ptr_tag()); return assign_to(f,functor,function_ptr_tag());
@ -560,13 +566,13 @@ namespace boost {
// Function objects // Function objects
// Assign to a function object using the small object optimization // Assign to a function object using the small object optimization
template<typename FunctionObj> template<typename FunctionObj>
void void
assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const
{ {
new (reinterpret_cast<void*>(&functor.data)) FunctionObj(f); new (reinterpret_cast<void*>(functor.data)) FunctionObj(f);
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
void void
assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const
{ {
assign_functor(f,functor,mpl::true_()); assign_functor(f,functor,mpl::true_());
@ -574,13 +580,13 @@ namespace boost {
// Assign to a function object allocated on the heap. // Assign to a function object allocated on the heap.
template<typename FunctionObj> template<typename FunctionObj>
void void
assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const
{ {
functor.obj_ptr = new FunctionObj(f); functor.members.obj_ptr = new FunctionObj(f);
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
void void
assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const
{ {
typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type; typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
@ -591,15 +597,15 @@ namespace boost {
wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
wrapper_allocator.construct(copy, functor_wrapper_type(f,a)); wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy); functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
functor.obj_ptr = new_f; functor.members.obj_ptr = new_f;
} }
template<typename FunctionObj> template<typename FunctionObj>
bool bool
assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
{ {
if (!boost::detail::function::has_empty_target(boost::addressof(f))) { if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
assign_functor(f, functor, assign_functor(f, functor,
mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>()); mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
return true; return true;
} else { } else {
@ -607,7 +613,7 @@ namespace boost {
} }
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
bool bool
assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const
{ {
if (!boost::detail::function::has_empty_target(boost::addressof(f))) { if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
@ -621,18 +627,18 @@ namespace boost {
// Reference to a function object // Reference to a function object
template<typename FunctionObj> template<typename FunctionObj>
bool bool
assign_to(const reference_wrapper<FunctionObj>& f, assign_to(const reference_wrapper<FunctionObj>& f,
function_buffer& functor, function_obj_ref_tag) const function_buffer& functor, function_obj_ref_tag) const
{ {
functor.obj_ref.obj_ptr = (void *)(f.get_pointer()); functor.members.obj_ref.obj_ptr = (void *)(f.get_pointer());
functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value; functor.members.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value; functor.members.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
return true; return true;
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
bool bool
assign_to_a(const reference_wrapper<FunctionObj>& f, assign_to_a(const reference_wrapper<FunctionObj>& f,
function_buffer& functor, Allocator, function_obj_ref_tag) const function_buffer& functor, Allocator, function_obj_ref_tag) const
{ {
return assign_to(f,functor,function_obj_ref_tag()); return assign_to(f,functor,function_obj_ref_tag());
@ -677,7 +683,7 @@ namespace boost {
vtable_type* get_vtable() const { vtable_type* get_vtable() const {
return reinterpret_cast<vtable_type*>( return reinterpret_cast<vtable_type*>(
reinterpret_cast<std::size_t>(vtable) & ~static_cast<size_t>(0x01)); reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
} }
struct clear_type {}; struct clear_type {};
@ -711,9 +717,8 @@ namespace boost {
template<typename Functor> template<typename Functor>
BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
,typename enable_if_c< ,typename boost::enable_if_c<
(boost::type_traits::ice_not< !(is_integral<Functor>::value),
(is_integral<Functor>::value)>::value),
int>::type = 0 int>::type = 0
#endif // BOOST_NO_SFINAE #endif // BOOST_NO_SFINAE
) : ) :
@ -724,9 +729,8 @@ namespace boost {
template<typename Functor,typename Allocator> template<typename Functor,typename Allocator>
BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
,typename enable_if_c< ,typename boost::enable_if_c<
(boost::type_traits::ice_not< !(is_integral<Functor>::value),
(is_integral<Functor>::value)>::value),
int>::type = 0 int>::type = 0
#endif // BOOST_NO_SFINAE #endif // BOOST_NO_SFINAE
) : ) :
@ -749,6 +753,13 @@ namespace boost {
this->assign_to_own(f); this->assign_to_own(f);
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base()
{
this->move_assign(f);
}
#endif
~BOOST_FUNCTION_FUNCTION() { clear(); } ~BOOST_FUNCTION_FUNCTION() { clear(); }
result_type operator()(BOOST_FUNCTION_PARMS) const result_type operator()(BOOST_FUNCTION_PARMS) const
@ -767,9 +778,8 @@ namespace boost {
// construct. // construct.
template<typename Functor> template<typename Functor>
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
typename enable_if_c< typename boost::enable_if_c<
(boost::type_traits::ice_not< !(is_integral<Functor>::value),
(is_integral<Functor>::value)>::value),
BOOST_FUNCTION_FUNCTION&>::type BOOST_FUNCTION_FUNCTION&>::type
#else #else
BOOST_FUNCTION_FUNCTION& BOOST_FUNCTION_FUNCTION&
@ -831,6 +841,25 @@ namespace boost {
return *this; return *this;
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Move assignment from another BOOST_FUNCTION_FUNCTION
BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f)
{
if (&f == this)
return *this;
this->clear();
BOOST_TRY {
this->move_assign(f);
} BOOST_CATCH (...) {
vtable = 0;
BOOST_RETHROW;
}
BOOST_CATCH_END
return *this;
}
#endif
void swap(BOOST_FUNCTION_FUNCTION& other) void swap(BOOST_FUNCTION_FUNCTION& other)
{ {
if (&other == this) if (&other == this)
@ -887,49 +916,15 @@ namespace boost {
template<typename Functor> template<typename Functor>
void assign_to(Functor f) void assign_to(Functor f)
{ {
using detail::function::vtable_base; using boost::detail::function::vtable_base;
typedef typename detail::function::get_function_tag<Functor>::type tag; typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker; typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
typedef typename get_invoker:: typedef typename get_invoker::
template apply<Functor, R BOOST_FUNCTION_COMMA template apply<Functor, R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS> BOOST_FUNCTION_TEMPLATE_ARGS>
handler_type; handler_type;
typedef typename handler_type::invoker_type invoker_type;
typedef typename handler_type::manager_type manager_type;
// Note: it is extremely important that this initialization use
// static initialization. Otherwise, we will have a race
// condition here in multi-threaded code. See
// http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
static const vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to(f, functor)) {
std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
if (boost::has_trivial_copy_constructor<Functor>::value &&
boost::has_trivial_destructor<Functor>::value &&
detail::function::function_allows_small_object_optimization<Functor>::value)
value |= static_cast<size_t>(0x01);
vtable = reinterpret_cast<detail::function::vtable_base *>(value);
} else
vtable = 0;
}
template<typename Functor,typename Allocator>
void assign_to_a(Functor f,Allocator a)
{
using detail::function::vtable_base;
typedef typename detail::function::get_function_tag<Functor>::type tag;
typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
typedef typename get_invoker::
template apply_a<Functor, R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS,
Allocator>
handler_type;
typedef typename handler_type::invoker_type invoker_type; typedef typename handler_type::invoker_type invoker_type;
typedef typename handler_type::manager_type manager_type; typedef typename handler_type::manager_type manager_type;
@ -940,22 +935,58 @@ namespace boost {
static const vtable_type stored_vtable = static const vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke }; { { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to_a(f, functor, a)) { if (stored_vtable.assign_to(f, functor)) {
std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base); std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
// coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
if (boost::has_trivial_copy_constructor<Functor>::value && if (boost::has_trivial_copy_constructor<Functor>::value &&
boost::has_trivial_destructor<Functor>::value && boost::has_trivial_destructor<Functor>::value &&
detail::function::function_allows_small_object_optimization<Functor>::value) boost::detail::function::function_allows_small_object_optimization<Functor>::value)
value |= static_cast<std::size_t>(0x01); value |= static_cast<std::size_t>(0x01);
vtable = reinterpret_cast<detail::function::vtable_base *>(value); vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
} else } else
vtable = 0; vtable = 0;
} }
// Moves the value from the specified argument to *this. If the argument template<typename Functor,typename Allocator>
// has its function object allocated on the heap, move_assign will pass void assign_to_a(Functor f,Allocator a)
// its buffer to *this, and set the argument's buffer pointer to NULL. {
void move_assign(BOOST_FUNCTION_FUNCTION& f) using boost::detail::function::vtable_base;
{
typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
typedef typename get_invoker::
template apply_a<Functor, R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS,
Allocator>
handler_type;
typedef typename handler_type::invoker_type invoker_type;
typedef typename handler_type::manager_type manager_type;
// Note: it is extremely important that this initialization use
// static initialization. Otherwise, we will have a race
// condition here in multi-threaded code. See
// http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
static const vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to_a(f, functor, a)) {
std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
// coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
if (boost::has_trivial_copy_constructor<Functor>::value &&
boost::has_trivial_destructor<Functor>::value &&
boost::detail::function::function_allows_small_object_optimization<Functor>::value)
value |= static_cast<std::size_t>(0x01);
vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
} else
vtable = 0;
}
// Moves the value from the specified argument to *this. If the argument
// has its function object allocated on the heap, move_assign will pass
// its buffer to *this, and set the argument's buffer pointer to NULL.
void move_assign(BOOST_FUNCTION_FUNCTION& f)
{
if (&f == this) if (&f == this)
return; return;
@ -1033,9 +1064,8 @@ public:
template<typename Functor> template<typename Functor>
function(Functor f function(Functor f
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
,typename enable_if_c< ,typename boost::enable_if_c<
(boost::type_traits::ice_not< !(is_integral<Functor>::value),
(is_integral<Functor>::value)>::value),
int>::type = 0 int>::type = 0
#endif #endif
) : ) :
@ -1045,9 +1075,8 @@ public:
template<typename Functor,typename Allocator> template<typename Functor,typename Allocator>
function(Functor f, Allocator a function(Functor f, Allocator a
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
,typename enable_if_c< ,typename boost::enable_if_c<
(boost::type_traits::ice_not< !(is_integral<Functor>::value),
(is_integral<Functor>::value)>::value),
int>::type = 0 int>::type = 0
#endif #endif
) : ) :
@ -1063,17 +1092,30 @@ public:
function(const base_type& f) : base_type(static_cast<const base_type&>(f)){} function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Move constructors
function(self_type&& f): base_type(static_cast<base_type&&>(f)){}
function(base_type&& f): base_type(static_cast<base_type&&>(f)){}
#endif
self_type& operator=(const self_type& f) self_type& operator=(const self_type& f)
{ {
self_type(f).swap(*this); self_type(f).swap(*this);
return *this; return *this;
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
self_type& operator=(self_type&& f)
{
self_type(static_cast<self_type&&>(f)).swap(*this);
return *this;
}
#endif
template<typename Functor> template<typename Functor>
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
typename enable_if_c< typename boost::enable_if_c<
(boost::type_traits::ice_not< !(is_integral<Functor>::value),
(is_integral<Functor>::value)>::value),
self_type&>::type self_type&>::type
#else #else
self_type& self_type&
@ -1097,6 +1139,14 @@ public:
self_type(f).swap(*this); self_type(f).swap(*this);
return *this; return *this;
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
self_type& operator=(base_type&& f)
{
self_type(static_cast<base_type&&>(f)).swap(*this);
return *this;
}
#endif
}; };
#undef BOOST_FUNCTION_PARTIAL_SPEC #undef BOOST_FUNCTION_PARTIAL_SPEC
@ -1125,6 +1175,9 @@ public:
#undef BOOST_FUNCTION_TEMPLATE_ARGS #undef BOOST_FUNCTION_TEMPLATE_ARGS
#undef BOOST_FUNCTION_PARMS #undef BOOST_FUNCTION_PARMS
#undef BOOST_FUNCTION_PARM #undef BOOST_FUNCTION_PARM
#ifdef BOOST_FUNCTION_ARG
# undef BOOST_FUNCTION_ARG
#endif
#undef BOOST_FUNCTION_ARGS #undef BOOST_FUNCTION_ARGS
#undef BOOST_FUNCTION_ARG_TYPE #undef BOOST_FUNCTION_ARG_TYPE
#undef BOOST_FUNCTION_ARG_TYPES #undef BOOST_FUNCTION_ARG_TYPES
@ -1133,4 +1186,4 @@ public:
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
# pragma warning( pop ) # pragma warning( pop )
#endif #endif

18
meta/libraries.json Normal file
View File

@ -0,0 +1,18 @@
{
"key": "function",
"name": "Function",
"authors": [
"Doug Gregor"
],
"description": "Function object wrappers for deferred calls or callbacks.",
"std": [
"tr1"
],
"category": [
"Function-objects",
"Programming"
],
"maintainers": [
"Douglas Gregor <dgregor -at- cs.indiana.edu>"
]
}

View File

@ -21,6 +21,8 @@ import testing ;
: :
[ run libs/function/test/function_test.cpp : : : : lib_function_test ] [ run libs/function/test/function_test.cpp : : : : lib_function_test ]
[ run libs/function/test/function_test.cpp : : : <rtti>off : lib_function_test_no_rtti ]
[ run libs/function/test/function_n_test.cpp : : : : ] [ run libs/function/test/function_n_test.cpp : : : : ]
[ run libs/function/test/allocator_test.cpp ../../../libs/test/build//boost_test_exec_monitor : : : : ] [ run libs/function/test/allocator_test.cpp ../../../libs/test/build//boost_test_exec_monitor : : : : ]
@ -61,6 +63,8 @@ import testing ;
[ run libs/function/test/nothrow_swap.cpp : : : : ] [ run libs/function/test/nothrow_swap.cpp : : : : ]
[ run libs/function/test/rvalues_test.cpp : : : : ]
[ compile libs/function/test/function_typeof_test.cpp ] [ compile libs/function/test/function_typeof_test.cpp ]
; ;
} }

View File

@ -690,6 +690,95 @@ static void test_call()
test_call_cref(std::plus<int>()); test_call_cref(std::plus<int>());
} }
struct big_aggregating_structure {
int disable_small_objects_optimizations[32];
big_aggregating_structure()
{
++ global_int;
}
big_aggregating_structure(const big_aggregating_structure&)
{
++ global_int;
}
~big_aggregating_structure()
{
-- global_int;
}
void operator()()
{
++ global_int;
}
void operator()(int)
{
++ global_int;
}
};
template <class FunctionT>
static void test_move_semantics()
{
typedef FunctionT f1_type;
big_aggregating_structure obj;
f1_type f1 = obj;
global_int = 0;
f1();
BOOST_CHECK(!f1.empty());
BOOST_CHECK(global_int == 1);
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Testing rvalue constructors
f1_type f2(static_cast<f1_type&&>(f1));
BOOST_CHECK(f1.empty());
BOOST_CHECK(!f2.empty());
BOOST_CHECK(global_int == 1);
f2();
BOOST_CHECK(global_int == 2);
f1_type f3(static_cast<f1_type&&>(f2));
BOOST_CHECK(f1.empty());
BOOST_CHECK(f2.empty());
BOOST_CHECK(!f3.empty());
BOOST_CHECK(global_int == 2);
f3();
BOOST_CHECK(global_int == 3);
// Testing move assignment
f1_type f4;
BOOST_CHECK(f4.empty());
f4 = static_cast<f1_type&&>(f3);
BOOST_CHECK(f1.empty());
BOOST_CHECK(f2.empty());
BOOST_CHECK(f3.empty());
BOOST_CHECK(!f4.empty());
BOOST_CHECK(global_int == 3);
f4();
BOOST_CHECK(global_int == 4);
// Testing self move assignment
f4 = static_cast<f1_type&&>(f4);
BOOST_CHECK(!f4.empty());
BOOST_CHECK(global_int == 4);
// Testing, that no memory leaked when assigning to nonempty function
f4 = obj;
BOOST_CHECK(!f4.empty());
BOOST_CHECK(global_int == 4);
f1_type f5 = obj;
BOOST_CHECK(global_int == 5);
f4 = static_cast<f1_type&&>(f5);
BOOST_CHECK(global_int == 4);
#endif
}
int test_main(int, char* []) int test_main(int, char* [])
{ {
test_zero_args(); test_zero_args();
@ -702,6 +791,8 @@ int test_main(int, char* [])
test_exception(); test_exception();
test_implicit(); test_implicit();
test_call(); test_call();
test_move_semantics<function<void()> >();
test_move_semantics<boost::function0<void> >();
return 0; return 0;
} }

View File

@ -14,24 +14,32 @@
#include <iostream> #include <iostream>
#include <functional> #include <functional>
struct Y {
Y(int y = 0) : y_(y) {}
bool operator==(const Y& rhs) { return y_ == rhs.y_; }
private:
int y_;
};
struct X { struct X {
int foo(int); int foo(int);
std::ostream& foo2(std::ostream&) const; Y& foo2(Y&) const;
}; };
int X::foo(int x) { return -x; } int X::foo(int x) { return -x; }
std::ostream& X::foo2(std::ostream& x) const { return x; } Y& X::foo2(Y& x) const { return x; }
int main() int main()
{ {
boost::function<int (X*, int)> f; boost::function<int (X*, int)> f;
boost::function<std::ostream& (X*, std::ostream&)> f2; boost::function<Y& (X*, Y&)> f2;
Y y1;
f = &X::foo; f = &X::foo;
f2 = &X::foo2; f2 = &X::foo2;
X x; X x;
BOOST_TEST(f(&x, 5) == -5); BOOST_TEST(f(&x, 5) == -5);
BOOST_TEST(f2(&x, boost::ref(std::cout)) == std::cout); BOOST_TEST(f2(&x, boost::ref(y1)) == y1);
return ::boost::report_errors(); return ::boost::report_errors();
} }

View File

@ -14,24 +14,32 @@
#include <iostream> #include <iostream>
#include <functional> #include <functional>
struct Y {
Y(int y = 0) : y_(y) {}
bool operator==(const Y& rhs) { return y_ == rhs.y_; }
private:
int y_;
};
struct X { struct X {
int foo(int); int foo(int);
std::ostream& foo2(std::ostream&) const; Y& foo2(Y&) const;
}; };
int X::foo(int x) { return -x; } int X::foo(int x) { return -x; }
std::ostream& X::foo2(std::ostream& x) const { return x; } Y& X::foo2(Y& x) const { return x; }
int main() int main()
{ {
boost::function2<int, X*, int> f; boost::function2<int, X*, int> f;
boost::function2<std::ostream&, X*, std::ostream&> f2; boost::function2<Y&, X*, Y&> f2;
Y y1;
f = &X::foo; f = &X::foo;
f2 = &X::foo2; f2 = &X::foo2;
X x; X x;
BOOST_TEST(f(&x, 5) == -5); BOOST_TEST(f(&x, 5) == -5);
BOOST_TEST(f2(&x, boost::ref(std::cout)) == std::cout); BOOST_TEST(f2(&x, boost::ref(y1)) == y1);
return ::boost::report_errors(); return ::boost::report_errors();
} }

106
test/rvalues_test.cpp Normal file
View File

@ -0,0 +1,106 @@
// Copyright 2014 Antony Polukhin.
//
// 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 <cstdlib>
#include <boost/test/minimal.hpp>
#include <boost/function.hpp>
#include <boost/move/move.hpp>
class only_movable {
private:
BOOST_MOVABLE_BUT_NOT_COPYABLE(only_movable)
int value_;
bool moved_;
public:
only_movable(BOOST_RV_REF(only_movable) x)
: value_(x.value_)
, moved_(false)
{
x.moved_ = true;
}
only_movable& operator=(BOOST_RV_REF(only_movable) x) {
value_ = x.value_;
x.moved_ = true;
moved_ = false;
return *this;
}
explicit only_movable(int value = 0) : value_(value), moved_(false) {}
int get_value() const { return value_; }
bool is_moved() const { return moved_; }
};
int one(BOOST_RV_REF(only_movable) v) { return v.get_value(); }
only_movable two(BOOST_RV_REF(only_movable) t) {
only_movable t1 = boost::move(t);
return BOOST_MOVE_RET(only_movable, t1);
}
only_movable two_sum(BOOST_RV_REF(only_movable) t1, BOOST_RV_REF(only_movable) t2) {
only_movable ret(t1.get_value() + t2.get_value());
return BOOST_MOVE_RET(only_movable, ret);
}
struct sum_struct {
only_movable operator()(BOOST_RV_REF(only_movable) t1, BOOST_RV_REF(only_movable) t2) const {
only_movable ret(t1.get_value() + t2.get_value());
return BOOST_MOVE_RET(only_movable, ret);
}
};
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
int three(std::string&&) { return 1; }
std::string&& four(std::string&& s) { return boost::move(s); }
#endif
int test_main(int, char*[])
{
using boost::function;
function <int(BOOST_RV_REF(only_movable))> f1 = one;
only_movable om1(1);
BOOST_CHECK(f1(boost::move(om1)) == 1);
function <only_movable(BOOST_RV_REF(only_movable))> f2 = two;
only_movable om2(2);
only_movable om2_2 = f2(boost::move(om2));
BOOST_CHECK(om2_2.get_value() == 2);
BOOST_CHECK(om2.is_moved());
{
function <only_movable(BOOST_RV_REF(only_movable), BOOST_RV_REF(only_movable))> f2_sum = two_sum;
only_movable om1_sum(1), om2_sum(2);
only_movable om2_sum_2 = f2_sum(boost::move(om1_sum), boost::move(om2_sum));
BOOST_CHECK(om2_sum_2.get_value() == 3);
}
{
sum_struct s;
function <only_movable(BOOST_RV_REF(only_movable), BOOST_RV_REF(only_movable))> f2_sum = s;
only_movable om1_sum(1), om2_sum(2);
only_movable om2_sum_2 = f2_sum(boost::move(om1_sum), boost::move(om2_sum));
BOOST_CHECK(om2_sum_2.get_value() == 3);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
function <int(std::string&&)> f3 = three;
function <std::string&& (std::string&& s)> f4 = four;
f3(std::string("Hello"));
BOOST_CHECK(f4(std::string("world")) == "world");
#endif
return 0;
}