Compare commits

..

21 Commits

Author SHA1 Message Date
98a207958d Branch for adding initializer list support (only in the unreleased gcc 4.4 at the moment).
[SVN r48931]
2008-09-23 19:45:43 +00:00
75890fea53 CodeGear C++ fix, from Nicola Musatti. Fixes #2325
[SVN r48922]
2008-09-23 00:26:21 +00:00
da259e8dce Make MyLargeFunctor large.
[SVN r48633]
2008-09-06 16:30:58 +00:00
2fe4cc253f Fix double-destruction problem with small function objects and swap(), and try to work around a GCC 4.2 issue. See #1910 for comments about the former problem from Niels Dekker.
[SVN r48627]
2008-09-06 03:16:25 +00:00
f379ef8532 Make Boost.Function's target() operation respect the cv-qualifiers of referenced function objects. Fixes #736
[SVN r48618]
2008-09-05 17:52:12 +00:00
ea18f5777b Add Boost.Typeof support to Boost.Function. Fixes #1621
[SVN r48616]
2008-09-05 16:13:49 +00:00
d5a86a2d52 Improve the performance of Boost.Function's swap. Thanks to Niels Dekker for the original patch. Fixes #1910
[SVN r48615]
2008-09-05 15:43:22 +00:00
e3dfa7268a Add forward-declaration header for Boost.Function. Fixes #1668
[SVN r48613]
2008-09-05 14:55:34 +00:00
bacb5d6752 Attempt to work around problem with allocator casts in Boost.Function
[SVN r46446]
2008-06-17 13:59:04 +00:00
04040ae566 Improve documentation on the size/efficiency of boost::function objects
[SVN r44852]
2008-04-28 14:11:46 +00:00
fe2d04e954 Change <functional> include so that it still works when Boost.TR1 is in the include path.
[SVN r44506]
2008-04-17 15:49:39 +00:00
0936dbdd03 Add missing include for is_void
[SVN r44030]
2008-04-04 12:26:53 +00:00
adb7b0a214 Change Boost.Function allocator behavior, from Emil Dotchevski
[SVN r43884]
2008-03-27 19:44:37 +00:00
cead36cd5b Disable more Visual C++ warnings in Function headers. Fixes #1416
[SVN r41798]
2007-12-06 18:39:06 +00:00
81e558491b Merge lots of copyrights
[SVN r40811]
2007-11-05 21:22:29 +00:00
2378ba59e7 Fix for Borland compilers.
[SVN r39657]
2007-10-02 17:41:35 +00:00
53b95c386d Finalizes the fix to Bug #1260, making vtable_base an actual POD type (oops)
and playing more nicely with reinterpret_cast (thanks to Brad King for the
fixes).



[SVN r39285]
2007-09-14 21:05:46 +00:00
3312c7ffcd function_template.hpp:
- Pass-by-reference internally, when we can. Fixes #1067



[SVN r39244]
2007-09-13 19:06:53 +00:00
de27ae9697 function/function_base.hpp, function/function_template.hpp:
- Switch from dynamic initialization of the vtable pointer to static
    initialization (Fixes #1260)
  - Handle member pointers properly, only using mem_fn within the invoker
    to deal with all of the messy bits of calling member pointers



[SVN r39240]
2007-09-13 17:38:58 +00:00
a7b9940f15 Handle GCC's -fno-exceptions properly. Fixes #1198
[SVN r39061]
2007-08-29 19:06:11 +00:00
e4f165a4e8 Disable MSVC warning about native code generation. Fixes #1163
[SVN r39060]
2007-08-29 18:59:16 +00:00
19 changed files with 1024 additions and 513 deletions

View File

@ -1,3 +1,8 @@
# Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
# 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)
project boost/doc ;
import boostbook : boostbook ;

View File

@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
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)
-->
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<section id="function.faq" last-revision="$Date$">

View File

@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
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)
-->
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<section id="function.history" last-revision="$Date$">
@ -6,6 +13,42 @@
<itemizedlist spacing="compact">
<listitem><para><bold>Version 1.37.0</bold>: </para>
<itemizedlist spacing="compact">
<listitem><para>Improved the performance of Boost.Function's
swap() operation for large function objects. Original patch
contributed by Niels Dekker.</para></listitem>
<listitem><para>Added a new header &lt;boost/function/function_typeof.hpp&gt; that provides support for using the Boost.Typeof library on Boost.Function objects.</para></listitem>
<listitem><para>Added a new header &lt;boost/function/function_fwd.hpp&gt; that provides support for using the Boost.Typeof library on Boost.Function objects.</para></listitem>
<listitem><para>The <methodname alt="boost::function::target">target</methodname>()
function now respects the cv-qualifiers of function objects
stored by reference
(using <classname>boost::reference_wrapper</classname>), such
that a reference to a <code>const</code> function object cannot
be accessed as a reference to a non-<code>const</code> function
object.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para><bold>Version 1.36.0</bold>: </para>
<itemizedlist spacing="compact">
<listitem><para>Boost.Function now implements allocator support
in the same way that is is provided in C++0x, based on C++
committee
proposal <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2308.html">N2308</ulink>. This
change removes the <computeroutput>Allocator</computeroutput>
template parameter of <classname>boost::function</classname> in
favor of a constructor that takes an argument. While this is a
backward-incompatible change, it is likely to affect only a few
users. This change to Function was contributed by Emil
Dotchevski, which also authored the corresponding C++ committee
proposal.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para><bold>Version 1.34.0</bold>: </para>
<itemizedlist spacing="compact">
<listitem><para>Boost.Function now implements a small buffer optimization, which can drastically improve the performance when copying or construction Boost.Function objects storing small function objects. For instance, <code>bind(&amp;X:foo, &amp;x, _1, _2)</code> requires no heap allocation when placed into a Boost.Function object. Note that some exception-safety guarantees have changed: assignment provides the basic exception guarantee and <code>swap()</code> may throw.</para></listitem>

View File

@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
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)
-->
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<section id="function.misc" last-revision="$Date$">
@ -17,7 +24,7 @@
<para> And, of course, function pointers have several advantages over Boost.Function:
<itemizedlist spacing="compact">
<listitem><para> Function pointers are smaller (the size of one pointer instead of three) </para></listitem>
<listitem><para> Function pointers are smaller (the size of one pointer instead of four or more) </para></listitem>
<listitem><para> Function pointers are faster (Boost.Function may require two calls through function pointers) </para></listitem>
<listitem><para> Function pointers are backward-compatible with C libraries.</para></listitem>
<listitem><para> More readable error messages. </para></listitem>
@ -30,12 +37,12 @@
<section>
<title>Function object wrapper size</title>
<para> Function object wrappers will be the size of two function pointers plus one function pointer or data pointer (whichever is larger). On common 32-bit platforms, this amounts to 12 bytes per wrapper. Additionally, the function object target will be allocated on the heap.</para>
<para> Function object wrappers will be the size of a struct containing a member function pointer and two data pointers. The actual size can vary significantly depending on the underlying platform; on 32-bit Mac OS X with GCC, this amounts to 16 bytes, while it is 32 bytes Windows with Visual C++. Additionally, the function object target may be allocated on the heap, if it cannot be placed into the small-object buffer in the <code>boost::function</code> object.</para>
</section>
<section>
<title>Copying efficiency</title>
<para> Copying function object wrappers may require allocating memory for a copy of the function object target. The default allocator may be replaced with a faster custom allocator or one may choose to allow the function object wrappers to only store function object targets by reference (using <computeroutput>ref</computeroutput>) if the cost of this cloning becomes prohibitive.</para>
<para> Copying function object wrappers may require allocating memory for a copy of the function object target. The default allocator may be replaced with a faster custom allocator or one may choose to allow the function object wrappers to only store function object targets by reference (using <computeroutput>ref</computeroutput>) if the cost of this cloning becomes prohibitive. Small function objects can be stored within the <code>boost::function</code> object itself, improving copying efficiency.</para>
</section>
<section>

View File

@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
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)
-->
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
@ -134,9 +141,6 @@
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator">
<default><classname>std::allocator</classname>&lt;void&gt;</default>
</template-type-parameter>
</template>
<inherit access="public"><classname>function_base</classname></inherit>
@ -153,7 +157,6 @@
</description>
<typedef name="result_type"><type>R</type></typedef>
<typedef name="allocator_type"><type>Allocator</type></typedef>
<typedef name="argument_type">
<type>T1</type><purpose>If N == 1</purpose>
</typedef>
@ -209,6 +212,19 @@
<postconditions><simpara><code>*this</code> targets a copy of <code>f</code> if <code>f</code> is nonempty, or <code>this-&gt;<methodname>empty</methodname>()</code> if <code>f</code> is empty.</simpara></postconditions>
</constructor>
<constructor>
<template>
<template-type-parameter name="F"/>
<template-type-parameter name="Allocator"/>
</template>
<parameter name="f"><paramtype>F</paramtype></parameter>
<parameter name="alloc"><paramtype>Allocator</paramtype></parameter>
<requires><simpara>F is a function object Callable from <code>this</code>, Allocator is an allocator. The copy constructor and destructor of Allocator shall not throw.</simpara></requires>
<postconditions><simpara><code>*this</code> targets a copy of <code>f</code> if <code>f</code> is nonempty, or <code>this-&gt;<methodname>empty</methodname>()</code> if <code>f</code> is empty.</simpara></postconditions>
<effects><simpara>If memory allocation is required, the given allocator (or a copy of it) will be used to allocate that memory.</simpara></effects>
</constructor>
<destructor>
<effects><simpara>If <code>!this-&gt;<methodname>empty</methodname>()</code>, destroys the target of this.</simpara></effects>
@ -317,11 +333,10 @@
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
</template>
<type>void</type>
<parameter name="f1"><paramtype><classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype><classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f1"><paramtype><classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype><classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
<effects><simpara><code>f1.<methodname>swap</methodname>(f2)</code></simpara></effects>
</function>
</free-function-group>
@ -334,11 +349,10 @@
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype>Functor</paramtype></parameter>
</signature>
<signature>
@ -347,12 +361,11 @@
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="g"><paramtype>Functor</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
</signature>
<signature>
<template>
@ -360,11 +373,10 @@
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
</signature>
<signature>
@ -373,12 +385,11 @@
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
</signature>
<signature>
<template>
@ -386,16 +397,14 @@
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="U1"/>
<template-type-parameter name="U2"/>
<template-varargs/>
<template-type-parameter name="UN"/>
<template-type-parameter name="Allocator2"/>
</template>
<type>void</type>
<parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN, Allocator2&gt;&amp;</paramtype></parameter>
<parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN&gt;&amp;</paramtype></parameter>
</signature>
<returns><simpara>True when <code>f</code> stores an object of
@ -435,11 +444,10 @@
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype>Functor</paramtype></parameter>
</signature>
<signature>
@ -448,12 +456,11 @@
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="g"><paramtype>Functor</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
</signature>
<signature>
<template>
@ -461,11 +468,10 @@
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
</signature>
<signature>
@ -474,12 +480,11 @@
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
</signature>
<signature>
<template>
@ -487,16 +492,14 @@
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="U1"/>
<template-type-parameter name="U2"/>
<template-varargs/>
<template-type-parameter name="UN"/>
<template-type-parameter name="Allocator2"/>
</template>
<type>void</type>
<parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN, Allocator2&gt;&amp;</paramtype></parameter>
<parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN&gt;&amp;</paramtype></parameter>
</signature>
<returns><simpara>True when <code>f</code> does not store an
@ -536,11 +539,8 @@
<template-type-parameter name="Signature">
<purpose>Function type R (T1, T2, ..., TN)</purpose>
</template-type-parameter>
<template-type-parameter name="Allocator">
<default><classname>std::allocator</classname>&lt;void&gt;</default>
</template-type-parameter>
</template>
<inherit access="public"><classname>functionN</classname>&lt;R, T1, T2, ..., TN, Allocator&gt;</inherit>
<inherit access="public"><classname>functionN</classname>&lt;R, T1, T2, ..., TN&gt;</inherit>
<purpose>A generalized function pointer that can be used for
callbacks or wrapping function objects.</purpose>
@ -562,7 +562,6 @@
</description>
<typedef name="result_type"><type>R</type></typedef>
<typedef name="allocator_type"><type>Allocator</type></typedef>
<typedef name="argument_type">
<type>T1</type><purpose>If N == 1</purpose>
</typedef>
@ -626,6 +625,19 @@
<postconditions><simpara><code>*this</code> targets a copy of <code>f</code> if <code>f</code> is nonempty, or <code>this-&gt;<methodname>empty</methodname>()</code> if <code>f</code> is empty.</simpara></postconditions>
</constructor>
<constructor>
<template>
<template-type-parameter name="F"/>
<template-type-parameter name="Allocator"/>
</template>
<parameter name="f"><paramtype>F</paramtype></parameter>
<parameter name="alloc"><paramtype>Allocator</paramtype></parameter>
<requires><simpara>F is a function object Callable from <code>this</code>, Allocator is an allocator. The copy constructor and destructor of Allocator shall not throw.</simpara></requires>
<postconditions><simpara><code>*this</code> targets a copy of <code>f</code> if <code>f</code> is nonempty, or <code>this-&gt;<methodname>empty</methodname>()</code> if <code>f</code> is empty.</simpara></postconditions>
<effects><simpara>If memory allocation is required, the given allocator (or a copy of it) will be used to allocate that memory.</simpara></effects>
</constructor>
<destructor>
<effects><simpara>If <code>!this-&gt;<methodname>empty</methodname>()</code>, destroys the target of <code>this</code>.</simpara></effects>
@ -738,11 +750,10 @@
<function name="swap">
<template>
<template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
</template>
<type>void</type>
<parameter name="f1"><paramtype><classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype><classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f1"><paramtype><classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype><classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
<effects><simpara><code>f1.<methodname>swap</methodname>(f2)</code></simpara></effects>
</function>
</free-function-group>
@ -752,53 +763,47 @@
<signature>
<template>
<template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype>Functor</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="g"><paramtype>Functor</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Signature1"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="Signature2"/>
<template-type-parameter name="Allocator2"/>
</template>
<type>void</type>
<parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2, Allocator2&gt;&amp;</paramtype></parameter>
<parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2&gt;&amp;</paramtype></parameter>
</signature>
<returns><simpara>True when <code>f</code> stores an object of
@ -833,53 +838,47 @@
<signature>
<template>
<template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype>Functor</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="g"><paramtype>Functor</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Signature1"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="Signature2"/>
<template-type-parameter name="Allocator2"/>
</template>
<type>void</type>
<parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2, Allocator2&gt;&amp;</paramtype></parameter>
<parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2&gt;&amp;</paramtype></parameter>
</signature>
<returns><simpara>True when <code>f</code> does not store an

View File

@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
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)
-->
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<testsuite id="function.testsuite" last-revision="$Date$">

View File

@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
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)
-->
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<section xmlns:xi="http://www.w3.org/2001/XInclude" id="function.tutorial"

View File

@ -11,7 +11,7 @@
#define BOOST_FUNCTION_PROLOGUE_HPP
# include <cassert>
# include <algorithm>
# include <functional> // unary_function, binary_function
# include <boost/config/no_tr1/functional.hpp> // unary_function, binary_function
# include <boost/throw_exception.hpp>
# include <boost/config.hpp>
# include <boost/function/function_base.hpp>
@ -22,4 +22,5 @@
# include <boost/preprocessor/cat.hpp>
# include <boost/preprocessor/repeat.hpp>
# include <boost/preprocessor/inc.hpp>
# include <boost/type_traits/is_void.hpp>
#endif // BOOST_FUNCTION_PROLOGUE_HPP

View File

@ -1,8 +1,9 @@
// Boost.Function library
// Copyright Douglas Gregor 2001-2006. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// Copyright Douglas Gregor 2001-2006
// Copyright Emil Dotchevski 2007
// 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
@ -17,8 +18,11 @@
#include <typeinfo>
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_volatile.hpp>
#include <boost/type_traits/composite_traits.hpp>
#include <boost/type_traits/ice.hpp>
#include <boost/ref.hpp>
#include <boost/mpl/if.hpp>
#include <boost/detail/workaround.hpp>
@ -29,10 +33,12 @@
# include "boost/mpl/bool.hpp"
#endif
#include <boost/function_equal.hpp>
#include <boost/function/function_fwd.hpp>
#if defined(BOOST_MSVC)
# pragma warning( push )
# pragma warning( disable : 4793 ) // complaint about native code generation
# pragma warning( disable : 4127 ) // "conditional expression is constant"
#endif
// Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info.
@ -61,22 +67,7 @@
# define BOOST_FUNCTION_TARGET_FIX(x)
#endif // not MSVC
#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
// Work around a compiler bug.
// boost::python::objects::function has to be seen by the compiler before the
// boost::function class template.
namespace boost { namespace python { namespace objects {
class function;
}}}
#endif
#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|| defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
|| !(defined(BOOST_STRICT_CONFIG) || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
# define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
#endif
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x600)
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x5A0)
# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \
(::boost::is_integral<Functor>::value)>::value), \
@ -90,31 +81,6 @@ namespace boost { namespace python { namespace objects {
Type>::type
#endif
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
namespace boost {
#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
// The library shipping with MIPSpro 7.3.1.3m has a broken allocator<void>
class function_base;
template<typename Signature,
typename Allocator = std::allocator<function_base> >
class function;
#else
template<typename Signature, typename Allocator = std::allocator<void> >
class function;
#endif
template<typename Signature, typename Allocator>
inline void swap(function<Signature, Allocator>& f1,
function<Signature, Allocator>& f2)
{
f1.swap(f2);
}
} // end namespace boost
#endif // have partial specialization
namespace boost {
namespace detail {
namespace function {
@ -129,11 +95,18 @@ namespace boost {
union function_buffer
{
// For pointers to function objects
void* obj_ptr;
mutable void* obj_ptr;
// For pointers to std::type_info objects
// (get_functor_type_tag, check_functor_type_tag).
const void* const_obj_ptr;
struct type_t {
// (get_functor_type_tag, check_functor_type_tag).
const BOOST_FUNCTION_STD_NS::type_info* type;
// Whether the type is const-qualified.
bool const_qualified;
// Whether the type is volatile-qualified.
bool volatile_qualified;
} type;
// For function pointers of all kinds
mutable void (*func_ptr)();
@ -144,6 +117,14 @@ namespace boost {
void* obj_ptr;
} bound_memfunc_ptr;
// For references to function objects. We explicitly keep
// track of the cv-qualifiers on the object referenced.
struct obj_ref_t {
mutable void* obj_ptr;
bool is_const_qualified;
bool is_volatile_qualified;
} obj_ref;
// To relax aliasing constraints
mutable char data;
};
@ -175,6 +156,7 @@ namespace boost {
// The operation type to perform on the given functor/function pointer
enum functor_manager_operation_type {
clone_functor_tag,
move_functor_tag,
destroy_functor_tag,
check_functor_type_tag,
get_functor_type_tag
@ -211,34 +193,45 @@ namespace boost {
struct reference_manager
{
static inline void
manage(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op)
get(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op)
{
switch (op) {
case clone_functor_tag:
out_buffer.obj_ptr = in_buffer.obj_ptr;
out_buffer.obj_ref.obj_ptr = in_buffer.obj_ref.obj_ptr;
return;
case move_functor_tag:
out_buffer.obj_ref.obj_ptr = in_buffer.obj_ref.obj_ptr;
in_buffer.obj_ref.obj_ptr = 0;
return;
case destroy_functor_tag:
out_buffer.obj_ptr = 0;
out_buffer.obj_ref.obj_ptr = 0;
return;
case check_functor_type_tag:
{
// DPG TBD: Since we're only storing a pointer, it's
// possible that the user could ask for a base class or
// derived class. Is that okay?
const BOOST_FUNCTION_STD_NS::type_info& check_type =
*static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F)))
out_buffer.obj_ptr = in_buffer.obj_ptr;
const BOOST_FUNCTION_STD_NS::type_info& check_type
= *out_buffer.type.type;
// Check whether we have the same type. We can add
// cv-qualifiers, but we can't take them away.
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F))
&& (!in_buffer.obj_ref.is_const_qualified
|| out_buffer.type.const_qualified)
&& (!in_buffer.obj_ref.is_volatile_qualified
|| out_buffer.type.volatile_qualified))
out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr;
else
out_buffer.obj_ptr = 0;
}
return;
case get_functor_type_tag:
out_buffer.const_obj_ptr = &typeid(F);
out_buffer.type.type = &typeid(F);
out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified;
out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified;
return;
}
}
@ -258,33 +251,94 @@ namespace boost {
% alignment_of<F>::value == 0))));
};
template <typename F,typename A>
struct functor_wrapper: public F, public A
{
functor_wrapper( F f, A a ):
F(f),
A(a)
{
}
};
/**
* The functor_manager class contains a static function "manage" which
* can clone or destroy the given function/function object pointer.
*/
template<typename Functor, typename Allocator>
template<typename Functor>
struct functor_manager_common
{
typedef Functor functor_type;
// Function pointers
static inline void
manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op)
{
if (op == clone_functor_tag)
out_buffer.func_ptr = in_buffer.func_ptr;
else if (op == move_functor_tag) {
out_buffer.func_ptr = in_buffer.func_ptr;
in_buffer.func_ptr = 0;
} else if (op == destroy_functor_tag)
out_buffer.func_ptr = 0;
else if (op == check_functor_type_tag) {
const BOOST_FUNCTION_STD_NS::type_info& check_type
= *out_buffer.type.type;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = &in_buffer.func_ptr;
else
out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &typeid(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
}
// Function objects that fit in the small-object buffer.
static inline void
manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op)
{
if (op == clone_functor_tag || op == move_functor_tag) {
const functor_type* in_functor =
reinterpret_cast<const functor_type*>(&in_buffer.data);
new ((void*)&out_buffer.data) functor_type(*in_functor);
if (op == move_functor_tag) {
reinterpret_cast<functor_type*>(&in_buffer.data)->~Functor();
}
} else if (op == destroy_functor_tag) {
// Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();
} else if (op == check_functor_type_tag) {
const BOOST_FUNCTION_STD_NS::type_info& check_type
= *out_buffer.type.type;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = &in_buffer.data;
else
out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &typeid(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
}
};
template<typename Functor>
struct functor_manager
{
private:
typedef Functor functor_type;
// For function pointers, the manager is trivial
// Function pointers
static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_ptr_tag)
{
if (op == clone_functor_tag)
out_buffer.func_ptr = in_buffer.func_ptr;
else if (op == destroy_functor_tag)
out_buffer.func_ptr = 0;
else /* op == check_functor_type_tag */ {
const BOOST_FUNCTION_STD_NS::type_info& check_type =
*static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = &in_buffer.func_ptr;
else
out_buffer.obj_ptr = 0;
}
functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
}
// Function objects that fit in the small-object buffer.
@ -292,21 +346,7 @@ namespace boost {
manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::true_)
{
if (op == clone_functor_tag) {
const functor_type* in_functor =
reinterpret_cast<const functor_type*>(&in_buffer.data);
new ((void*)&out_buffer.data) functor_type(*in_functor);
} else if (op == destroy_functor_tag) {
// Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();
} else /* op == check_functor_type_tag */ {
const BOOST_FUNCTION_STD_NS::type_info& check_type =
*static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = &in_buffer.data;
else
out_buffer.obj_ptr = 0;
}
functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
}
// Function objects that require heap allocation
@ -314,59 +354,34 @@ namespace boost {
manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::false_)
{
#ifndef BOOST_NO_STD_ALLOCATOR
typedef typename Allocator::template rebind<functor_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
#else
typedef functor_type* pointer_type;
#endif // BOOST_NO_STD_ALLOCATOR
# ifndef BOOST_NO_STD_ALLOCATOR
allocator_type allocator;
# endif // BOOST_NO_STD_ALLOCATOR
if (op == clone_functor_tag) {
// Clone the functor
// GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do.
const functor_type* f =
(const functor_type*)(in_buffer.obj_ptr);
// Clone the functor
# ifndef BOOST_NO_STD_ALLOCATOR
pointer_type copy = allocator.allocate(1);
allocator.construct(copy, *f);
// Get back to the original pointer type
functor_type* new_f = static_cast<functor_type*>(copy);
# else
functor_type* new_f = new functor_type(*f);
# endif // BOOST_NO_STD_ALLOCATOR
out_buffer.obj_ptr = new_f;
} else if (op == move_functor_tag) {
out_buffer.obj_ptr = in_buffer.obj_ptr;
in_buffer.obj_ptr = 0;
} else if (op == destroy_functor_tag) {
/* Cast from the void pointer to the functor pointer type */
functor_type* f =
static_cast<functor_type*>(out_buffer.obj_ptr);
# ifndef BOOST_NO_STD_ALLOCATOR
/* Cast from the functor pointer type to the allocator's pointer
type */
pointer_type victim = static_cast<pointer_type>(f);
// Destroy and deallocate the functor
allocator.destroy(victim);
allocator.deallocate(victim, 1);
# else
delete f;
# endif // BOOST_NO_STD_ALLOCATOR
out_buffer.obj_ptr = 0;
} else /* op == check_functor_type_tag */ {
const BOOST_FUNCTION_STD_NS::type_info& check_type =
*static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
} else if (op == check_functor_type_tag) {
const BOOST_FUNCTION_STD_NS::type_info& check_type
= *out_buffer.type.type;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = in_buffer.obj_ptr;
else
out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &typeid(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
}
@ -381,13 +396,107 @@ namespace boost {
mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
}
// For member pointers, we treat them as function objects with
// the small-object optimization always enabled.
public:
/* Dispatch to an appropriate manager based on whether we have a
function pointer or a function object pointer. */
static inline void
manage(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op)
{
typedef typename get_function_tag<functor_type>::type tag_type;
switch (op) {
case get_functor_type_tag:
out_buffer.type.type = &typeid(functor_type);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
return;
default:
manager(in_buffer, out_buffer, op, tag_type());
return;
}
}
};
template<typename Functor, typename Allocator>
struct functor_manager_a
{
private:
typedef Functor functor_type;
// Function pointers
static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, member_ptr_tag)
functor_manager_operation_type op, function_ptr_tag)
{
manager(in_buffer, out_buffer, op, mpl::true_());
functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
}
// Function objects that fit in the small-object buffer.
static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::true_)
{
functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
}
// Function objects that require heap allocation
static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::false_)
{
typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
typedef typename Allocator::template rebind<functor_wrapper_type>::other
wrapper_allocator_type;
typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
if (op == clone_functor_tag) {
// Clone the functor
// GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do.
const functor_wrapper_type* f =
(const functor_wrapper_type*)(in_buffer.obj_ptr);
wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
wrapper_allocator.construct(copy, *f);
// Get back to the original pointer type
functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
out_buffer.obj_ptr = new_f;
} else if (op == move_functor_tag) {
out_buffer.obj_ptr = in_buffer.obj_ptr;
in_buffer.obj_ptr = 0;
} else if (op == destroy_functor_tag) {
/* Cast from the void pointer to the functor_wrapper_type */
functor_wrapper_type* victim =
static_cast<functor_wrapper_type*>(in_buffer.obj_ptr);
wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
wrapper_allocator.destroy(victim);
wrapper_allocator.deallocate(victim,1);
out_buffer.obj_ptr = 0;
} else if (op == check_functor_type_tag) {
const BOOST_FUNCTION_STD_NS::type_info& check_type
= *out_buffer.type.type;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = in_buffer.obj_ptr;
else
out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &typeid(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
}
// For function objects, we determine whether the function
// object can use the small-object optimization buffer or
// whether we need to allocate it on the heap.
static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_obj_tag)
{
manager(in_buffer, out_buffer, op,
mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
}
public:
@ -400,7 +509,9 @@ namespace boost {
typedef typename get_function_tag<functor_type>::type tag_type;
switch (op) {
case get_functor_type_tag:
out_buffer.const_obj_ptr = &typeid(functor_type);
out_buffer.type.type = &typeid(functor_type);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
return;
default:
@ -478,6 +589,7 @@ namespace boost {
*/
struct vtable_base
{
vtable_base() : manager(0) { }
void (*manager)(const function_buffer& in_buffer,
function_buffer& out_buffer,
functor_manager_operation_type op);
@ -507,7 +619,7 @@ public:
detail::function::function_buffer type;
vtable->manager(functor, type, detail::function::get_functor_type_tag);
return *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(type.const_obj_ptr);
return *type.type.type;
}
template<typename Functor>
@ -516,7 +628,9 @@ public:
if (!vtable) return 0;
detail::function::function_buffer type_result;
type_result.const_obj_ptr = &typeid(Functor);
type_result.type.type = &typeid(Functor);
type_result.type.const_qualified = is_const<Functor>::value;
type_result.type.volatile_qualified = is_volatile<Functor>::value;
vtable->manager(functor, type_result,
detail::function::check_functor_type_tag);
return static_cast<Functor*>(type_result.obj_ptr);
@ -532,7 +646,9 @@ public:
if (!vtable) return 0;
detail::function::function_buffer type_result;
type_result.const_obj_ptr = &typeid(Functor);
type_result.type.type = &typeid(Functor);
type_result.type.const_qualified = true;
type_result.type.volatile_qualified = is_volatile<Functor>::value;
vtable->manager(functor, type_result,
detail::function::check_functor_type_tag);
// GCC 2.95.3 gets the CV qualifiers wrong here, so we
@ -579,7 +695,7 @@ public:
#endif
public: // should be protected, but GCC 2.95.3 will fail to allow access
const detail::function::vtable_base* vtable;
detail::function::vtable_base* vtable;
mutable detail::function::function_buffer functor;
};
@ -754,8 +870,4 @@ namespace detail {
#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
#undef BOOST_FUNCTION_COMPARE_TYPE_ID
#if defined(BOOST_MSVC)
# pragma warning( pop )
#endif
#endif // BOOST_FUNCTION_BASE_HEADER

View File

@ -0,0 +1,70 @@
// Boost.Function library
// Copyright (C) Douglas Gregor 2008
//
// 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
#ifndef BOOST_FUNCTION_FWD_HPP
#define BOOST_FUNCTION_FWD_HPP
#include <boost/config.hpp>
#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
// Work around a compiler bug.
// boost::python::objects::function has to be seen by the compiler before the
// boost::function class template.
namespace boost { namespace python { namespace objects {
class function;
}}}
#endif
#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|| defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
|| !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
# define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
#endif
namespace boost {
class bad_function_call;
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
// Preferred syntax
template<typename Signature> class function;
template<typename Signature>
inline void swap(function<Signature>& f1, function<Signature>& f2)
{
f1.swap(f2);
}
#endif // have partial specialization
// Portable syntax
template<typename R> class function0;
template<typename R, typename T1> class function1;
template<typename R, typename T1, typename T2> class function2;
template<typename R, typename T1, typename T2, typename T3> class function3;
template<typename R, typename T1, typename T2, typename T3, typename T4>
class function4;
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5>
class function5;
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6>
class function6;
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7>
class function7;
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8>
class function8;
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8, typename T9>
class function9;
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8, typename T9,
typename T10>
class function10;
}
#endif

View File

@ -1,8 +1,9 @@
// Boost.Function library
// Copyright Douglas Gregor 2001-2006. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// Copyright Douglas Gregor 2001-2006
// Copyright Emil Dotchevski 2007
// 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
@ -11,6 +12,11 @@
// protection.
#include <boost/function/detail/prologue.hpp>
#if defined(BOOST_MSVC)
# pragma warning( push )
# pragma warning( disable : 4127 ) // "conditional expression is constant"
#endif
#define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
#define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
@ -26,13 +32,6 @@
#define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
// Type of the default allocator
#ifndef BOOST_NO_STD_ALLOCATOR
# define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator<function_base>
#else
# define BOOST_FUNCTION_DEFAULT_ALLOCATOR int
#endif // BOOST_NO_STD_ALLOCATOR
// Comma if nonzero number of arguments
#if BOOST_FUNCTION_NUM_ARGS == 0
# define BOOST_FUNCTION_COMMA
@ -54,20 +53,12 @@
BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_MEMBER_INVOKER \
BOOST_JOIN(member_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VOID_MEMBER_INVOKER \
BOOST_JOIN(void_member_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_MEMBER_INVOKER \
BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_INVOKER \
BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
#ifndef BOOST_NO_VOID_RETURNS
@ -189,44 +180,6 @@ namespace boost {
}
};
#if BOOST_FUNCTION_NUM_ARGS > 0
/* Handle invocation of member pointers. */
template<
typename MemberPtr,
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_MEMBER_INVOKER
{
static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
MemberPtr* f =
reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
}
};
template<
typename MemberPtr,
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_VOID_MEMBER_INVOKER
{
static BOOST_FUNCTION_VOID_RETURN_TYPE
invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
MemberPtr* f =
reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
}
};
#endif
template<
typename FunctionPtr,
typename R BOOST_FUNCTION_COMMA
@ -290,130 +243,11 @@ namespace boost {
>::type type;
};
#if BOOST_FUNCTION_NUM_ARGS > 0
/* Retrieve the appropriate invoker for a member pointer. */
template<
typename MemberPtr,
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_GET_MEMBER_INVOKER
{
typedef typename mpl::if_c<(is_void<R>::value),
BOOST_FUNCTION_VOID_MEMBER_INVOKER<
MemberPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>,
BOOST_FUNCTION_MEMBER_INVOKER<
MemberPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
>::type type;
};
#endif
/* Given the tag returned by get_function_tag, retrieve the
actual invoker that will be used for the given function
object.
Each specialization contains an "apply" nested class template
that accepts the function object, return type, function
argument types, and allocator. The resulting "apply" class
contains two typedefs, "invoker_type" and "manager_type",
which correspond to the invoker and manager types. */
template<typename Tag>
struct BOOST_FUNCTION_GET_INVOKER { };
/* Retrieve the invoker for a function pointer. */
template<>
struct BOOST_FUNCTION_GET_INVOKER<function_ptr_tag>
{
template<typename FunctionPtr,
typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
struct apply
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
typedef functor_manager<FunctionPtr, Allocator> manager_type;
};
};
#if BOOST_FUNCTION_NUM_ARGS > 0
/* Retrieve the invoker for a member pointer. */
template<>
struct BOOST_FUNCTION_GET_INVOKER<member_ptr_tag>
{
template<typename MemberPtr,
typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
struct apply
{
typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
MemberPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
typedef functor_manager<MemberPtr, Allocator> manager_type;
};
};
#endif
/* Retrieve the invoker for a function object. */
template<>
struct BOOST_FUNCTION_GET_INVOKER<function_obj_tag>
{
template<typename FunctionObj,
typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
struct apply
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
typedef functor_manager<FunctionObj, Allocator> manager_type;
};
};
/* Retrieve the invoker for a reference to a function object. */
template<>
struct BOOST_FUNCTION_GET_INVOKER<function_obj_ref_tag>
{
template<typename RefWrapper,
typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
struct apply
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
typename RefWrapper::type,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
typedef reference_manager<typename RefWrapper::type> manager_type;
};
};
/**
* vtable for a specific boost::function instance.
*/
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
struct BOOST_FUNCTION_VTABLE
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
struct BOOST_FUNCTION_VTABLE : vtable_base
{
#ifndef BOOST_NO_VOID_RETURNS
typedef R result_type;
@ -426,25 +260,80 @@ namespace boost {
BOOST_FUNCTION_TEMPLATE_ARGS);
template<typename F>
bool assign_to(const F& f, function_buffer& functor) const
BOOST_FUNCTION_VTABLE(F f) : vtable_base(), invoker(0)
{
init(f);
}
template<typename F,typename Allocator>
BOOST_FUNCTION_VTABLE(F f, Allocator) : vtable_base(), invoker(0)
{
init_a<Allocator>(f);
}
template<typename F>
bool assign_to(F f, function_buffer& functor)
{
typedef typename get_function_tag<F>::type tag;
return assign_to(f, functor, tag());
}
void clear(function_buffer& functor) const
template<typename F,typename Allocator>
bool assign_to_a(F f, function_buffer& functor, Allocator a)
{
if (base.manager)
base.manager(functor, functor, destroy_functor_tag);
typedef typename get_function_tag<F>::type tag;
return assign_to_a(f, functor, a, tag());
}
#ifndef BOOST_NO_PRIVATE_IN_AGGREGATE
void clear(function_buffer& functor)
{
if (manager)
manager(functor, functor, destroy_functor_tag);
}
private:
#endif
template<typename F>
void init(F f)
{
typedef typename get_function_tag<F>::type tag;
init(f, tag());
}
template<typename Allocator,typename F>
void init_a(F f)
{
typedef typename get_function_tag<F>::type tag;
init_a<Allocator>(f, tag());
}
// Function pointers
template<typename FunctionPtr>
void init(FunctionPtr /*f*/, function_ptr_tag)
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
manager = &functor_manager<FunctionPtr>::manage;
}
template<typename Allocator,typename FunctionPtr>
void init_a(FunctionPtr f, function_ptr_tag)
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
manager = &functor_manager_a<FunctionPtr, Allocator>::manage;
}
template<typename FunctionPtr>
bool
assign_to(FunctionPtr f, function_buffer& functor,
function_ptr_tag) const
assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag)
{
this->clear(functor);
if (f) {
@ -456,17 +345,53 @@ namespace boost {
return false;
}
}
template<typename FunctionPtr,typename Allocator>
bool
assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag)
{
return assign_to(f,functor,function_ptr_tag());
}
// Member pointers
#if BOOST_FUNCTION_NUM_ARGS > 0
template<typename MemberPtr>
bool
assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
void init(MemberPtr f, member_ptr_tag)
{
// DPG TBD: Add explicit support for member function
// objects, so we invoke through mem_fn() but we retain the
// right target_type() values.
this->init(mem_fn(f));
}
template<typename Allocator,typename MemberPtr>
void init_a(MemberPtr f, member_ptr_tag)
{
// DPG TBD: Add explicit support for member function
// objects, so we invoke through mem_fn() but we retain the
// right target_type() values.
this->init_a<Allocator>(mem_fn(f));
}
template<typename MemberPtr>
bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag)
{
// DPG TBD: Add explicit support for member function
// objects, so we invoke through mem_fn() but we retain the
// right target_type() values.
if (f) {
// Always use the small-object optimization for member
// pointers.
assign_functor(f, functor, mpl::true_());
this->assign_to(mem_fn(f), functor);
return true;
} else {
return false;
}
}
template<typename MemberPtr,typename Allocator>
bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag)
{
// DPG TBD: Add explicit support for member function
// objects, so we invoke through mem_fn() but we retain the
// right target_type() values.
if (f) {
this->assign_to_a(mem_fn(f), functor, a);
return true;
} else {
return false;
@ -475,41 +400,72 @@ namespace boost {
#endif // BOOST_FUNCTION_NUM_ARGS > 0
// Function objects
template<typename FunctionObj>
void init(FunctionObj /*f*/, function_obj_tag)
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
manager = &functor_manager<FunctionObj>::manage;
}
template<typename Allocator,typename FunctionObj>
void init_a(FunctionObj /*f*/, function_obj_tag)
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
manager = &functor_manager_a<FunctionObj, Allocator>::manage;
}
// Assign to a function object using the small object optimization
template<typename FunctionObj>
void
assign_functor(const FunctionObj& f, function_buffer& functor,
mpl::true_) const
assign_functor(FunctionObj f, function_buffer& functor, mpl::true_)
{
new ((void*)&functor.data) FunctionObj(f);
}
template<typename FunctionObj,typename Allocator>
void
assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_)
{
assign_functor(f,functor,mpl::true_());
}
// Assign to a function object allocated on the heap.
template<typename FunctionObj>
void
assign_functor(const FunctionObj& f, function_buffer& functor,
mpl::false_) const
assign_functor(FunctionObj f, function_buffer& functor, mpl::false_)
{
#ifndef BOOST_NO_STD_ALLOCATOR
typedef typename Allocator::template rebind<FunctionObj>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
allocator.construct(copy, f);
// Get back to the original pointer type
functor.obj_ptr = static_cast<FunctionObj*>(copy);
# else
functor.obj_ptr = new FunctionObj(f);
# endif // BOOST_NO_STD_ALLOCATOR
}
template<typename FunctionObj,typename Allocator>
void
assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_)
{
typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
typedef typename Allocator::template rebind<functor_wrapper_type>::other
wrapper_allocator_type;
typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
wrapper_allocator_type wrapper_allocator(a);
wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
functor.obj_ptr = new_f;
}
template<typename FunctionObj>
bool
assign_to(const FunctionObj& f, function_buffer& functor,
function_obj_tag) const
assign_to(FunctionObj f, function_buffer& functor, function_obj_tag)
{
if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
assign_functor(f, functor,
@ -519,27 +475,64 @@ namespace boost {
return false;
}
}
// Reference to a function object
template<typename FunctionObj>
template<typename FunctionObj,typename Allocator>
bool
assign_to(const reference_wrapper<FunctionObj>& f,
function_buffer& functor, function_obj_ref_tag) const
assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag)
{
if (!boost::detail::function::has_empty_target(f.get_pointer())) {
// DPG TBD: We might need to detect constness of
// FunctionObj to assign into obj_ptr or const_obj_ptr to
// be truly legit, but no platform in existence makes
// const void* different from void*.
functor.const_obj_ptr = f.get_pointer();
if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
assign_functor_a(f, functor, a,
mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
return true;
} else {
return false;
}
}
// Reference to a function object
template<typename FunctionObj>
void
init(const reference_wrapper<FunctionObj>& /*f*/, function_obj_ref_tag)
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
manager = &reference_manager<FunctionObj>::get;
}
template<typename Allocator,typename FunctionObj>
void
init_a(const reference_wrapper<FunctionObj>& f, function_obj_ref_tag)
{
init(f,function_obj_ref_tag());
}
template<typename FunctionObj>
bool
assign_to(const reference_wrapper<FunctionObj>& f,
function_buffer& functor, function_obj_ref_tag)
{
if (!boost::detail::function::has_empty_target(f.get_pointer())) {
functor.obj_ref.obj_ptr = (void *)f.get_pointer();
functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
return true;
} else {
return false;
}
}
template<typename FunctionObj,typename Allocator>
bool
assign_to_a(const reference_wrapper<FunctionObj>& f,
function_buffer& functor, Allocator, function_obj_ref_tag)
{
return assign_to(f,functor,function_obj_ref_tag());
}
public:
vtable_base base;
invoker_type invoker;
};
} // end namespace function
@ -547,8 +540,7 @@ namespace boost {
template<
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR
BOOST_FUNCTION_TEMPLATE_PARMS
>
class BOOST_FUNCTION_FUNCTION : public function_base
@ -573,7 +565,7 @@ namespace boost {
private:
typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, Allocator>
R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
vtable_type;
struct clear_type {};
@ -598,7 +590,6 @@ namespace boost {
BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
BOOST_FUNCTION_ARG_TYPES
typedef Allocator allocator_type;
typedef BOOST_FUNCTION_FUNCTION self_type;
BOOST_FUNCTION_FUNCTION() : function_base() { }
@ -618,6 +609,19 @@ namespace boost {
{
this->assign_to(f);
}
template<typename Functor,typename Allocator>
BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
#ifndef BOOST_NO_SFINAE
,typename enable_if_c<
(boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value),
int>::type = 0
#endif // BOOST_NO_SFINAE
) :
function_base()
{
this->assign_to_a(f,a);
}
#ifndef BOOST_NO_SFINAE
BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
@ -643,7 +647,7 @@ namespace boost {
if (this->empty())
boost::throw_exception(bad_function_call());
return reinterpret_cast<const vtable_type*>(vtable)->invoker
return static_cast<vtable_type*>(vtable)->invoker
(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
}
#else
@ -667,18 +671,25 @@ namespace boost {
operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{
this->clear();
#ifndef BOOST_NO_EXCEPTIONS
try {
this->assign_to(f);
} catch (...) {
vtable = 0;
throw;
}
#else
this->assign_to(f);
#endif
return *this;
}
template<typename Functor,typename Allocator>
void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
{
this->clear();
try {
this->assign_to_a(f,a);
} catch (...) {
vtable = 0;
throw;
}
}
#ifndef BOOST_NO_SFINAE
BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
@ -702,16 +713,12 @@ namespace boost {
return *this;
this->clear();
#ifndef BOOST_NO_EXCEPTIONS
try {
this->assign_to_own(f);
} catch (...) {
vtable = 0;
throw;
}
#else
this->assign_to_own(f);
#endif
return *this;
}
@ -720,16 +727,17 @@ namespace boost {
if (&other == this)
return;
BOOST_FUNCTION_FUNCTION tmp = *this;
*this = other;
other = tmp;
BOOST_FUNCTION_FUNCTION tmp;
tmp.move_assign(*this);
this->move_assign(other);
other.move_assign(tmp);
}
// Clear out a target, if there is one
void clear()
{
if (vtable) {
reinterpret_cast<const vtable_type*>(vtable)->clear(this->functor);
static_cast<vtable_type*>(vtable)->clear(this->functor);
vtable = 0;
}
}
@ -764,84 +772,91 @@ namespace boost {
}
template<typename Functor>
void assign_to(const Functor& f)
void assign_to(Functor f)
{
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<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;
static const vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable.base;
static vtable_type stored_vtable(f);
if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable;
else vtable = 0;
}
template<typename Functor,typename Allocator>
void assign_to_a(Functor f,Allocator a)
{
static vtable_type stored_vtable(f,a);
if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable;
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)
return;
#if !defined(BOOST_NO_EXCEPTIONS)
try {
#endif
if (!f.empty()) {
this->vtable = f.vtable;
f.vtable->manager(f.functor, this->functor,
boost::detail::function::move_functor_tag);
f.vtable = 0;
#if !defined(BOOST_NO_EXCEPTIONS)
} else {
clear();
}
} catch (...) {
vtable = 0;
throw;
}
#endif
}
};
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
typename Allocator>
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
inline void swap(BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS ,
Allocator
BOOST_FUNCTION_TEMPLATE_ARGS
>& f1,
BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS,
Allocator
BOOST_FUNCTION_TEMPLATE_ARGS
>& f2)
{
f1.swap(f2);
}
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
typename BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
Allocator>::result_type
BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
Allocator>
R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type
BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
::operator()(BOOST_FUNCTION_PARMS) const
{
if (this->empty())
boost::throw_exception(bad_function_call());
return reinterpret_cast<const vtable_type*>(vtable)->invoker
return static_cast<vtable_type*>(vtable)->invoker
(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
}
#endif
// Poison comparisons between boost::function objects of the same type.
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
typename Allocator>
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
void operator==(const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS ,
Allocator>&,
BOOST_FUNCTION_TEMPLATE_ARGS>&,
const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS ,
Allocator>&);
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
typename Allocator>
BOOST_FUNCTION_TEMPLATE_ARGS>&);
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
void operator!=(const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS ,
Allocator>&,
BOOST_FUNCTION_TEMPLATE_ARGS>&,
const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS ,
Allocator>&);
BOOST_FUNCTION_TEMPLATE_ARGS>& );
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
@ -852,20 +867,16 @@ template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
#endif
template<typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>
: public BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
BOOST_FUNCTION_COMMA Allocator>
BOOST_FUNCTION_TEMPLATE_PARMS>
class function<BOOST_FUNCTION_PARTIAL_SPEC>
: public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
{
typedef BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
BOOST_FUNCTION_COMMA Allocator> base_type;
typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
typedef function self_type;
struct clear_type {};
public:
typedef typename base_type::allocator_type allocator_type;
function() : base_type() {}
@ -881,6 +892,18 @@ public:
base_type(f)
{
}
template<typename Functor,typename Allocator>
function(Functor f, Allocator a
#ifndef BOOST_NO_SFINAE
,typename enable_if_c<
(boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value),
int>::type = 0
#endif
) :
base_type(f,a)
{
}
#ifndef BOOST_NO_SFINAE
function(clear_type*) : base_type() {}
@ -933,8 +956,6 @@ public:
// Cleanup after ourselves...
#undef BOOST_FUNCTION_VTABLE
#undef BOOST_FUNCTION_GET_INVOKER
#undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
#undef BOOST_FUNCTION_COMMA
#undef BOOST_FUNCTION_FUNCTION
#undef BOOST_FUNCTION_FUNCTION_INVOKER
@ -943,12 +964,10 @@ public:
#undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_MEMBER_INVOKER
#undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_GET_MEMBER_INVOKER
#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
#undef BOOST_FUNCTION_TEMPLATE_PARMS
#undef BOOST_FUNCTION_TEMPLATE_ARGS
#undef BOOST_FUNCTION_PARMS
@ -958,3 +977,7 @@ public:
#undef BOOST_FUNCTION_ARG_TYPES
#undef BOOST_FUNCTION_VOID_RETURN_TYPE
#undef BOOST_FUNCTION_RETURN
#if defined(BOOST_MSVC)
# pragma warning( pop )
#endif

View File

@ -0,0 +1,45 @@
// Boost.Function library - Typeof support
// Copyright (C) Douglas Gregor 2008
//
// 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
#ifndef BOOST_FUNCTION_TYPEOF_HPP
#define BOOST_FUNCTION_TYPEOF_HPP
#include <boost/function/function_fwd.hpp>
#include <boost/typeof/typeof.hpp>
#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
BOOST_TYPEOF_REGISTER_TYPE(boost::bad_function_call)
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function, (typename))
#endif
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function0, (typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function1, (typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function2, (typename)(typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function3,
(typename)(typename)(typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function4,
(typename)(typename)(typename)(typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function5,
(typename)(typename)(typename)(typename)(typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function6,
(typename)(typename)(typename)(typename)(typename)(typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function7,
(typename)(typename)(typename)(typename)(typename)(typename)(typename)
(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function8,
(typename)(typename)(typename)(typename)(typename)(typename)(typename)
(typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function9,
(typename)(typename)(typename)(typename)(typename)(typename)(typename)
(typename)(typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function10,
(typename)(typename)(typename)(typename)(typename)(typename)(typename)
(typename)(typename)(typename)(typename))
#endif

View File

@ -1,4 +1,11 @@
<html>
<!--
Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
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)
-->
<head>
<meta http-equiv="refresh" content="0; URL=../../doc/html/function.html">
</head>

View File

@ -58,6 +58,9 @@ import testing ;
[ run libs/function/test/contains2_test.cpp : : : : ]
[ run libs/function/test/nothrow_swap.cpp : : : : ]
[ compile libs/function/test/function_typeof_test.cpp ]
;
}

View File

@ -27,6 +27,14 @@ struct counting_allocator : public std::allocator<T>
typedef counting_allocator<U> other;
};
counting_allocator()
{
}
template<typename U>
counting_allocator( counting_allocator<U> )
{
}
T* allocate(std::size_t n)
{
@ -41,20 +49,27 @@ struct counting_allocator : public std::allocator<T>
}
};
struct plus_int
struct enable_small_object_optimization
{
};
struct disable_small_object_optimization
{
int unused_state_data[32];
};
template <typename base>
struct plus_int: base
{
int operator()(int x, int y) const { return x + y; }
int unused_state_data[32];
};
static int do_minus(int x, int y) { return x-y; }
struct DoNothing
template <typename base>
struct DoNothing: base
{
void operator()() const {}
int unused_state_data[32];
};
static void do_nothing() {}
@ -62,33 +77,57 @@ static void do_nothing() {}
int
test_main(int, char*[])
{
function2<int, int, int, counting_allocator<int> > f;
f = plus_int();
function2<int, int, int> f;
f.assign( plus_int<disable_small_object_optimization>(), counting_allocator<int>() );
f.clear();
BOOST_CHECK(alloc_count == 1);
BOOST_CHECK(dealloc_count == 1);
alloc_count = 0;
dealloc_count = 0;
f = &do_minus;
f.assign( plus_int<enable_small_object_optimization>(), counting_allocator<int>() );
f.clear();
BOOST_CHECK(alloc_count == 0);
BOOST_CHECK(dealloc_count == 0);
f.assign( plus_int<disable_small_object_optimization>(), std::allocator<int>() );
f.clear();
f.assign( plus_int<enable_small_object_optimization>(), std::allocator<int>() );
f.clear();
function0<void, counting_allocator<int> > fv;
alloc_count = 0;
dealloc_count = 0;
fv = DoNothing();
f.assign( &do_minus, counting_allocator<int>() );
f.clear();
BOOST_CHECK(alloc_count == 0);
BOOST_CHECK(dealloc_count == 0);
f.assign( &do_minus, std::allocator<int>() );
f.clear();
function0<void> fv;
alloc_count = 0;
dealloc_count = 0;
fv.assign( DoNothing<disable_small_object_optimization>(), counting_allocator<int>() );
fv.clear();
BOOST_CHECK(alloc_count == 1);
BOOST_CHECK(dealloc_count == 1);
alloc_count = 0;
dealloc_count = 0;
fv = &do_nothing;
fv.assign( DoNothing<enable_small_object_optimization>(), counting_allocator<int>() );
fv.clear();
BOOST_CHECK(alloc_count == 0);
BOOST_CHECK(dealloc_count == 0);
fv.assign( DoNothing<disable_small_object_optimization>(), std::allocator<int>() );
fv.clear();
fv.assign( DoNothing<enable_small_object_optimization>(), std::allocator<int>() );
fv.clear();
alloc_count = 0;
dealloc_count = 0;
fv.assign( &do_nothing, counting_allocator<int>() );
fv.clear();
BOOST_CHECK(alloc_count == 0);
BOOST_CHECK(dealloc_count == 0);
fv.assign( &do_nothing, std::allocator<int>() );
fv.clear();
return 0;
}

View File

@ -88,6 +88,15 @@ static void target_test()
BOOST_CHECK(!f.target<int (*)()>());
BOOST_CHECK(f.target<Seventeen>());
BOOST_CHECK(f.target<Seventeen>() == &this_seventeen);
const Seventeen const_seventeen = this_seventeen;
f = boost::ref(const_seventeen);
BOOST_CHECK(!f.target<int (*)()>());
BOOST_CHECK(f.target<const Seventeen>());
BOOST_CHECK(f.target<const Seventeen>() == &const_seventeen);
BOOST_CHECK(f.target<const volatile Seventeen>());
BOOST_CHECK(!f.target<Seventeen>());
BOOST_CHECK(!f.target<volatile Seventeen>());
}
static void equal_test()

View File

@ -636,6 +636,54 @@ test_ref()
}
}
static unsigned construction_count = 0;
static unsigned destruction_count = 0;
struct MySmallFunctor {
MySmallFunctor() { ++construction_count; }
MySmallFunctor(const MySmallFunctor &) { ++construction_count; }
~MySmallFunctor() { ++destruction_count; }
int operator()() { return 0; }
};
struct MyLargeFunctor {
MyLargeFunctor() { ++construction_count; }
MyLargeFunctor(const MyLargeFunctor &) { ++construction_count; }
~MyLargeFunctor() { ++destruction_count; }
int operator()() { return 0; }
float data[128];
};
void test_construct_destroy_count()
{
{
boost::function0<int> f;
boost::function0<int> g;
f = MySmallFunctor();
g = MySmallFunctor();
f.swap(g);
}
// MySmallFunctor objects should be constructed as many times as
// they are destroyed.
BOOST_CHECK(construction_count == destruction_count);
construction_count = 0;
destruction_count = 0;
{
boost::function0<int> f;
boost::function0<int> g;
f = MyLargeFunctor();
g = MyLargeFunctor();
f.swap(g);
}
// MyLargeFunctor objects should be constructed as many times as
// they are destroyed.
BOOST_CHECK(construction_count == destruction_count);
}
int test_main(int, char* [])
{
test_zero_args();
@ -644,5 +692,6 @@ int test_main(int, char* [])
test_emptiness();
test_member_functions();
test_ref();
test_construct_destroy_count();
return 0;
}

View File

@ -0,0 +1,18 @@
// Boost.Function library
// Copyright Douglas Gregor 2008. 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
#include <boost/function/function_typeof.hpp>
#include <boost/function.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
void f(boost::function0<void> f, boost::function0<void> g)
{
BOOST_STATIC_ASSERT((boost::is_same<boost::function0<void>, BOOST_TYPEOF(f = g)>::value));
}

60
test/nothrow_swap.cpp Normal file
View File

@ -0,0 +1,60 @@
// Boost.Function library
// Copyright Douglas Gregor 2008. 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
#include <boost/test/minimal.hpp>
#include <boost/function.hpp>
struct tried_to_copy { };
struct MaybeThrowOnCopy {
MaybeThrowOnCopy(int value = 0) : value(value) { }
MaybeThrowOnCopy(const MaybeThrowOnCopy& other) : value(other.value) {
if (throwOnCopy)
throw tried_to_copy();
}
MaybeThrowOnCopy& operator=(const MaybeThrowOnCopy& other) {
if (throwOnCopy)
throw tried_to_copy();
value = other.value;
return *this;
}
int operator()() { return value; }
int value;
// Make sure that this function object doesn't trigger the
// small-object optimization in Function.
float padding[100];
static bool throwOnCopy;
};
bool MaybeThrowOnCopy::throwOnCopy = false;
int test_main(int, char* [])
{
boost::function0<int> f;
boost::function0<int> g;
MaybeThrowOnCopy::throwOnCopy = false;
f = MaybeThrowOnCopy(1);
g = MaybeThrowOnCopy(2);
BOOST_CHECK(f() == 1);
BOOST_CHECK(g() == 2);
MaybeThrowOnCopy::throwOnCopy = true;
f.swap(g);
BOOST_CHECK(f() == 2);
BOOST_CHECK(g() == 1);
return 0;
}