Compare commits

..

1 Commits

Author SHA1 Message Date
c551fa0f68 Branch for development of boost.system related changes
[SVN r40931]
2007-11-08 14:20:16 +00:00
7 changed files with 430 additions and 550 deletions

View File

@ -13,22 +13,6 @@
<itemizedlist spacing="compact"> <itemizedlist spacing="compact">
<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> <listitem><para><bold>Version 1.34.0</bold>: </para>
<itemizedlist spacing="compact"> <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> <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

@ -24,7 +24,7 @@
<para> And, of course, function pointers have several advantages over Boost.Function: <para> And, of course, function pointers have several advantages over Boost.Function:
<itemizedlist spacing="compact"> <itemizedlist spacing="compact">
<listitem><para> Function pointers are smaller (the size of one pointer instead of four or more) </para></listitem> <listitem><para> Function pointers are smaller (the size of one pointer instead of three) </para></listitem>
<listitem><para> Function pointers are faster (Boost.Function may require two calls through function pointers) </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> Function pointers are backward-compatible with C libraries.</para></listitem>
<listitem><para> More readable error messages. </para></listitem> <listitem><para> More readable error messages. </para></listitem>
@ -37,12 +37,12 @@
<section> <section>
<title>Function object wrapper size</title> <title>Function object wrapper size</title>
<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> <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>
</section> </section>
<section> <section>
<title>Copying efficiency</title> <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. Small function objects can be stored within the <code>boost::function</code> object itself, improving copying efficiency.</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.</para>
</section> </section>
<section> <section>

View File

@ -141,6 +141,9 @@
<template-type-parameter name="T2"/> <template-type-parameter name="T2"/>
<template-varargs/> <template-varargs/>
<template-type-parameter name="TN"/> <template-type-parameter name="TN"/>
<template-type-parameter name="Allocator">
<default><classname>std::allocator</classname>&lt;void&gt;</default>
</template-type-parameter>
</template> </template>
<inherit access="public"><classname>function_base</classname></inherit> <inherit access="public"><classname>function_base</classname></inherit>
@ -157,6 +160,7 @@
</description> </description>
<typedef name="result_type"><type>R</type></typedef> <typedef name="result_type"><type>R</type></typedef>
<typedef name="allocator_type"><type>Allocator</type></typedef>
<typedef name="argument_type"> <typedef name="argument_type">
<type>T1</type><purpose>If N == 1</purpose> <type>T1</type><purpose>If N == 1</purpose>
</typedef> </typedef>
@ -212,19 +216,6 @@
<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> <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>
<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> <destructor>
<effects><simpara>If <code>!this-&gt;<methodname>empty</methodname>()</code>, destroys the target of this.</simpara></effects> <effects><simpara>If <code>!this-&gt;<methodname>empty</methodname>()</code>, destroys the target of this.</simpara></effects>
@ -333,10 +324,11 @@
<template-type-parameter name="T2"/> <template-type-parameter name="T2"/>
<template-varargs/> <template-varargs/>
<template-type-parameter name="TN"/> <template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
</template> </template>
<type>void</type> <type>void</type>
<parameter name="f1"><paramtype><classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter> <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&gt;&amp;</paramtype></parameter> <parameter name="f2"><paramtype><classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<effects><simpara><code>f1.<methodname>swap</methodname>(f2)</code></simpara></effects> <effects><simpara><code>f1.<methodname>swap</methodname>(f2)</code></simpara></effects>
</function> </function>
</free-function-group> </free-function-group>
@ -349,10 +341,11 @@
<template-type-parameter name="T2"/> <template-type-parameter name="T2"/>
<template-varargs/> <template-varargs/>
<template-type-parameter name="TN"/> <template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype>Functor</paramtype></parameter> <parameter name="g"><paramtype>Functor</paramtype></parameter>
</signature> </signature>
<signature> <signature>
@ -361,11 +354,12 @@
<template-type-parameter name="T2"/> <template-type-parameter name="T2"/>
<template-varargs/> <template-varargs/>
<template-type-parameter name="TN"/> <template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="g"><paramtype>Functor</paramtype></parameter> <parameter name="g"><paramtype>Functor</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
</signature> </signature>
<signature> <signature>
<template> <template>
@ -373,10 +367,11 @@
<template-type-parameter name="T2"/> <template-type-parameter name="T2"/>
<template-varargs/> <template-varargs/>
<template-type-parameter name="TN"/> <template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter> <parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
</signature> </signature>
<signature> <signature>
@ -385,11 +380,12 @@
<template-type-parameter name="T2"/> <template-type-parameter name="T2"/>
<template-varargs/> <template-varargs/>
<template-type-parameter name="TN"/> <template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter> <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&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
</signature> </signature>
<signature> <signature>
<template> <template>
@ -397,14 +393,16 @@
<template-type-parameter name="T2"/> <template-type-parameter name="T2"/>
<template-varargs/> <template-varargs/>
<template-type-parameter name="TN"/> <template-type-parameter name="TN"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="U1"/> <template-type-parameter name="U1"/>
<template-type-parameter name="U2"/> <template-type-parameter name="U2"/>
<template-varargs/> <template-varargs/>
<template-type-parameter name="UN"/> <template-type-parameter name="UN"/>
<template-type-parameter name="Allocator2"/>
</template> </template>
<type>void</type> <type>void</type>
<parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter> <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&gt;&amp;</paramtype></parameter> <parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN, Allocator2&gt;&amp;</paramtype></parameter>
</signature> </signature>
<returns><simpara>True when <code>f</code> stores an object of <returns><simpara>True when <code>f</code> stores an object of
@ -444,10 +442,11 @@
<template-type-parameter name="T2"/> <template-type-parameter name="T2"/>
<template-varargs/> <template-varargs/>
<template-type-parameter name="TN"/> <template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype>Functor</paramtype></parameter> <parameter name="g"><paramtype>Functor</paramtype></parameter>
</signature> </signature>
<signature> <signature>
@ -456,11 +455,12 @@
<template-type-parameter name="T2"/> <template-type-parameter name="T2"/>
<template-varargs/> <template-varargs/>
<template-type-parameter name="TN"/> <template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="g"><paramtype>Functor</paramtype></parameter> <parameter name="g"><paramtype>Functor</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
</signature> </signature>
<signature> <signature>
<template> <template>
@ -468,10 +468,11 @@
<template-type-parameter name="T2"/> <template-type-parameter name="T2"/>
<template-varargs/> <template-varargs/>
<template-type-parameter name="TN"/> <template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter> <parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
</signature> </signature>
<signature> <signature>
@ -480,11 +481,12 @@
<template-type-parameter name="T2"/> <template-type-parameter name="T2"/>
<template-varargs/> <template-varargs/>
<template-type-parameter name="TN"/> <template-type-parameter name="TN"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter> <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&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
</signature> </signature>
<signature> <signature>
<template> <template>
@ -492,14 +494,16 @@
<template-type-parameter name="T2"/> <template-type-parameter name="T2"/>
<template-varargs/> <template-varargs/>
<template-type-parameter name="TN"/> <template-type-parameter name="TN"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="U1"/> <template-type-parameter name="U1"/>
<template-type-parameter name="U2"/> <template-type-parameter name="U2"/>
<template-varargs/> <template-varargs/>
<template-type-parameter name="UN"/> <template-type-parameter name="UN"/>
<template-type-parameter name="Allocator2"/>
</template> </template>
<type>void</type> <type>void</type>
<parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter> <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&gt;&amp;</paramtype></parameter> <parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN, Allocator2&gt;&amp;</paramtype></parameter>
</signature> </signature>
<returns><simpara>True when <code>f</code> does not store an <returns><simpara>True when <code>f</code> does not store an
@ -539,8 +543,11 @@
<template-type-parameter name="Signature"> <template-type-parameter name="Signature">
<purpose>Function type R (T1, T2, ..., TN)</purpose> <purpose>Function type R (T1, T2, ..., TN)</purpose>
</template-type-parameter> </template-type-parameter>
<template-type-parameter name="Allocator">
<default><classname>std::allocator</classname>&lt;void&gt;</default>
</template-type-parameter>
</template> </template>
<inherit access="public"><classname>functionN</classname>&lt;R, T1, T2, ..., TN&gt;</inherit> <inherit access="public"><classname>functionN</classname>&lt;R, T1, T2, ..., TN, Allocator&gt;</inherit>
<purpose>A generalized function pointer that can be used for <purpose>A generalized function pointer that can be used for
callbacks or wrapping function objects.</purpose> callbacks or wrapping function objects.</purpose>
@ -562,6 +569,7 @@
</description> </description>
<typedef name="result_type"><type>R</type></typedef> <typedef name="result_type"><type>R</type></typedef>
<typedef name="allocator_type"><type>Allocator</type></typedef>
<typedef name="argument_type"> <typedef name="argument_type">
<type>T1</type><purpose>If N == 1</purpose> <type>T1</type><purpose>If N == 1</purpose>
</typedef> </typedef>
@ -625,19 +633,6 @@
<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> <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>
<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> <destructor>
<effects><simpara>If <code>!this-&gt;<methodname>empty</methodname>()</code>, destroys the target of <code>this</code>.</simpara></effects> <effects><simpara>If <code>!this-&gt;<methodname>empty</methodname>()</code>, destroys the target of <code>this</code>.</simpara></effects>
@ -750,10 +745,11 @@
<function name="swap"> <function name="swap">
<template> <template>
<template-type-parameter name="Signature"/> <template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
</template> </template>
<type>void</type> <type>void</type>
<parameter name="f1"><paramtype><classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter> <parameter name="f1"><paramtype><classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype><classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter> <parameter name="f2"><paramtype><classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<effects><simpara><code>f1.<methodname>swap</methodname>(f2)</code></simpara></effects> <effects><simpara><code>f1.<methodname>swap</methodname>(f2)</code></simpara></effects>
</function> </function>
</free-function-group> </free-function-group>
@ -763,47 +759,53 @@
<signature> <signature>
<template> <template>
<template-type-parameter name="Signature"/> <template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype>Functor</paramtype></parameter> <parameter name="g"><paramtype>Functor</paramtype></parameter>
</signature> </signature>
<signature> <signature>
<template> <template>
<template-type-parameter name="Signature"/> <template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="g"><paramtype>Functor</paramtype></parameter> <parameter name="g"><paramtype>Functor</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
</signature> </signature>
<signature> <signature>
<template> <template>
<template-type-parameter name="Signature"/> <template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter> <parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
</signature> </signature>
<signature> <signature>
<template> <template>
<template-type-parameter name="Signature"/> <template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter> <parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
</signature> </signature>
<signature> <signature>
<template> <template>
<template-type-parameter name="Signature1"/> <template-type-parameter name="Signature1"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="Signature2"/> <template-type-parameter name="Signature2"/>
<template-type-parameter name="Allocator2"/>
</template> </template>
<type>void</type> <type>void</type>
<parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1&gt;&amp;</paramtype></parameter> <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&gt;&amp;</paramtype></parameter> <parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2, Allocator2&gt;&amp;</paramtype></parameter>
</signature> </signature>
<returns><simpara>True when <code>f</code> stores an object of <returns><simpara>True when <code>f</code> stores an object of
@ -838,47 +840,53 @@
<signature> <signature>
<template> <template>
<template-type-parameter name="Signature"/> <template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype>Functor</paramtype></parameter> <parameter name="g"><paramtype>Functor</paramtype></parameter>
</signature> </signature>
<signature> <signature>
<template> <template>
<template-type-parameter name="Signature"/> <template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="g"><paramtype>Functor</paramtype></parameter> <parameter name="g"><paramtype>Functor</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
</signature> </signature>
<signature> <signature>
<template> <template>
<template-type-parameter name="Signature"/> <template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter> <parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
</signature> </signature>
<signature> <signature>
<template> <template>
<template-type-parameter name="Signature"/> <template-type-parameter name="Signature"/>
<template-type-parameter name="Allocator"/>
<template-type-parameter name="Functor"/> <template-type-parameter name="Functor"/>
</template> </template>
<type>bool</type> <type>bool</type>
<parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter> <parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
<parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter> <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
</signature> </signature>
<signature> <signature>
<template> <template>
<template-type-parameter name="Signature1"/> <template-type-parameter name="Signature1"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="Signature2"/> <template-type-parameter name="Signature2"/>
<template-type-parameter name="Allocator2"/>
</template> </template>
<type>void</type> <type>void</type>
<parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1&gt;&amp;</paramtype></parameter> <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&gt;&amp;</paramtype></parameter> <parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2, Allocator2&gt;&amp;</paramtype></parameter>
</signature> </signature>
<returns><simpara>True when <code>f</code> does not store an <returns><simpara>True when <code>f</code> does not store an

View File

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

View File

@ -1,9 +1,8 @@
// Boost.Function library // Boost.Function library
// Copyright Douglas Gregor 2001-2006 // Copyright Douglas Gregor 2001-2006. Use, modification and
// Copyright Emil Dotchevski 2007 // distribution is subject to the Boost Software License, Version
// Use, modification and distribution is subject to the Boost Software License, Version 1.0. // 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)
// For more information, see http://www.boost.org // For more information, see http://www.boost.org
@ -34,7 +33,6 @@
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
# 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"
#endif #endif
// Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info. // Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info.
@ -74,7 +72,7 @@ namespace boost { namespace python { namespace objects {
#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ #if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|| defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \ || defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
|| !(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
@ -95,12 +93,21 @@ namespace boost { namespace python { namespace objects {
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
namespace boost { namespace boost {
template<typename Signature> #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
class function; // The library shipping with MIPSpro 7.3.1.3m has a broken allocator<void>
class function_base;
template<typename Signature> template<typename Signature,
inline void swap(function<Signature>& f1, typename Allocator = std::allocator<function_base> >
function<Signature>& f2) 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); f1.swap(f2);
} }
@ -204,8 +211,8 @@ namespace boost {
struct reference_manager struct reference_manager
{ {
static inline void static inline void
get(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:
@ -251,29 +258,20 @@ namespace boost {
% alignment_of<F>::value == 0)))); % 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 * The functor_manager class contains a static function "manage" which
* can clone or destroy the given function/function object pointer. * can clone or destroy the given function/function object pointer.
*/ */
template<typename Functor> template<typename Functor, typename Allocator>
struct functor_manager_common struct functor_manager
{ {
private:
typedef Functor functor_type; typedef Functor functor_type;
// Function pointers // For function pointers, the manager is trivial
static inline void static inline void
manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op, function_ptr_tag)
{ {
if (op == clone_functor_tag) if (op == clone_functor_tag)
out_buffer.func_ptr = in_buffer.func_ptr; out_buffer.func_ptr = in_buffer.func_ptr;
@ -291,8 +289,8 @@ 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
manage_small(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op, mpl::true_)
{ {
if (op == clone_functor_tag) { if (op == clone_functor_tag) {
const functor_type* in_functor = const functor_type* in_functor =
@ -310,48 +308,57 @@ namespace boost {
out_buffer.obj_ptr = 0; out_buffer.obj_ptr = 0;
} }
} }
};
template<typename Functor>
struct functor_manager
{
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, function_ptr_tag)
{
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 // 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_)
{ {
#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) { if (op == clone_functor_tag) {
// Clone the functor
// 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_type* f = const functor_type* f =
(const functor_type*)(in_buffer.obj_ptr); (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); functor_type* new_f = new functor_type(*f);
# endif // BOOST_NO_STD_ALLOCATOR
out_buffer.obj_ptr = new_f; out_buffer.obj_ptr = new_f;
} 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.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; delete f;
# endif // BOOST_NO_STD_ALLOCATOR
out_buffer.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else /* op == check_functor_type_tag */ { } else /* op == check_functor_type_tag */ {
const BOOST_FUNCTION_STD_NS::type_info& check_type = const BOOST_FUNCTION_STD_NS::type_info& check_type =
@ -374,98 +381,13 @@ namespace boost {
mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>()); mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
} }
public: // For member pointers, we treat them as function objects with
/* Dispatch to an appropriate manager based on whether we have a // the small-object optimization always enabled.
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.const_obj_ptr = &typeid(functor_type);
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 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, member_ptr_tag)
{ {
functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op); manager(in_buffer, out_buffer, op, mpl::true_());
}
// 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 == 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 /* 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.obj_ptr;
else
out_buffer.obj_ptr = 0;
}
}
// 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: public:
@ -556,7 +478,6 @@ namespace boost {
*/ */
struct vtable_base struct vtable_base
{ {
vtable_base() : manager(0) { }
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);
@ -658,7 +579,7 @@ public:
#endif #endif
public: // should be protected, but GCC 2.95.3 will fail to allow access public: // should be protected, but GCC 2.95.3 will fail to allow access
detail::function::vtable_base* vtable; const detail::function::vtable_base* vtable;
mutable detail::function::function_buffer functor; mutable detail::function::function_buffer functor;
}; };
@ -833,4 +754,8 @@ namespace detail {
#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
#undef BOOST_FUNCTION_COMPARE_TYPE_ID #undef BOOST_FUNCTION_COMPARE_TYPE_ID
#if defined(BOOST_MSVC)
# pragma warning( pop )
#endif
#endif // BOOST_FUNCTION_BASE_HEADER #endif // BOOST_FUNCTION_BASE_HEADER

View File

@ -1,9 +1,8 @@
// Boost.Function library // Boost.Function library
// Copyright Douglas Gregor 2001-2006 // Copyright Douglas Gregor 2001-2006. Use, modification and
// Copyright Emil Dotchevski 2007 // distribution is subject to the Boost Software License, Version
// Use, modification and distribution is subject to the Boost Software License, Version 1.0. // 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)
// For more information, see http://www.boost.org // For more information, see http://www.boost.org
@ -12,11 +11,6 @@
// protection. // protection.
#include <boost/function/detail/prologue.hpp> #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_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) #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
@ -32,6 +26,13 @@
#define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY) #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 // Comma if nonzero number of arguments
#if BOOST_FUNCTION_NUM_ARGS == 0 #if BOOST_FUNCTION_NUM_ARGS == 0
# define BOOST_FUNCTION_COMMA # define BOOST_FUNCTION_COMMA
@ -53,12 +54,20 @@
BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \ #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) 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 \ #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \ #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \ #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) 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) #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
#ifndef BOOST_NO_VOID_RETURNS #ifndef BOOST_NO_VOID_RETURNS
@ -180,6 +189,44 @@ 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< template<
typename FunctionPtr, typename FunctionPtr,
typename R BOOST_FUNCTION_COMMA typename R BOOST_FUNCTION_COMMA
@ -243,11 +290,130 @@ namespace boost {
>::type type; >::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. * vtable for a specific boost::function instance.
*/ */
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
struct BOOST_FUNCTION_VTABLE : vtable_base typename Allocator>
struct BOOST_FUNCTION_VTABLE
{ {
#ifndef BOOST_NO_VOID_RETURNS #ifndef BOOST_NO_VOID_RETURNS
typedef R result_type; typedef R result_type;
@ -260,80 +426,25 @@ namespace boost {
BOOST_FUNCTION_TEMPLATE_ARGS); BOOST_FUNCTION_TEMPLATE_ARGS);
template<typename F> template<typename F>
BOOST_FUNCTION_VTABLE(F f) : vtable_base(), invoker(0) bool assign_to(const F& f, function_buffer& functor) const
{
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; typedef typename get_function_tag<F>::type tag;
return assign_to(f, functor, tag()); return assign_to(f, functor, tag());
} }
template<typename F,typename Allocator>
bool assign_to_a(F f, function_buffer& functor, Allocator a)
{
typedef typename get_function_tag<F>::type tag;
return assign_to_a(f, functor, a, tag());
}
void clear(function_buffer& functor) void clear(function_buffer& functor) const
{ {
if (manager) if (base.manager)
manager(functor, functor, destroy_functor_tag); base.manager(functor, functor, destroy_functor_tag);
} }
#ifndef BOOST_NO_PRIVATE_IN_AGGREGATE
private: private:
template<typename F> #endif
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 // 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> template<typename FunctionPtr>
bool bool
assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) assign_to(FunctionPtr f, function_buffer& functor,
function_ptr_tag) const
{ {
this->clear(functor); this->clear(functor);
if (f) { if (f) {
@ -345,53 +456,17 @@ namespace boost {
return false; 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 // Member pointers
#if BOOST_FUNCTION_NUM_ARGS > 0 #if BOOST_FUNCTION_NUM_ARGS > 0
template<typename MemberPtr> template<typename MemberPtr>
void init(MemberPtr f, member_ptr_tag) bool
assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
{ {
// 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) { if (f) {
this->assign_to(mem_fn(f), functor); // Always use the small-object optimization for member
return true; // pointers.
} else { assign_functor(f, functor, mpl::true_());
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; return true;
} else { } else {
return false; return false;
@ -400,72 +475,41 @@ namespace boost {
#endif // BOOST_FUNCTION_NUM_ARGS > 0 #endif // BOOST_FUNCTION_NUM_ARGS > 0
// Function objects // 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 // 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_) assign_functor(const FunctionObj& f, function_buffer& functor,
mpl::true_) const
{ {
new ((void*)&functor.data) FunctionObj(f); 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. // 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_) assign_functor(const FunctionObj& f, function_buffer& functor,
mpl::false_) const
{ {
#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); 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> template<typename FunctionObj>
bool bool
assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) assign_to(const 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,
@ -475,45 +519,12 @@ namespace boost {
return false; return false;
} }
} }
template<typename FunctionObj,typename Allocator>
bool
assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag)
{
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 // 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> 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) function_buffer& functor, function_obj_ref_tag) const
{ {
if (!boost::detail::function::has_empty_target(f.get_pointer())) { if (!boost::detail::function::has_empty_target(f.get_pointer())) {
// DPG TBD: We might need to detect constness of // DPG TBD: We might need to detect constness of
@ -526,15 +537,9 @@ namespace boost {
return false; 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: public:
vtable_base base;
invoker_type invoker; invoker_type invoker;
}; };
} // end namespace function } // end namespace function
@ -542,7 +547,8 @@ namespace boost {
template< template<
typename R BOOST_FUNCTION_COMMA typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR
> >
class BOOST_FUNCTION_FUNCTION : public function_base class BOOST_FUNCTION_FUNCTION : public function_base
@ -567,7 +573,7 @@ namespace boost {
private: private:
typedef boost::detail::function::BOOST_FUNCTION_VTABLE< typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, Allocator>
vtable_type; vtable_type;
struct clear_type {}; struct clear_type {};
@ -592,6 +598,7 @@ namespace boost {
BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS); BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
BOOST_FUNCTION_ARG_TYPES BOOST_FUNCTION_ARG_TYPES
typedef Allocator allocator_type;
typedef BOOST_FUNCTION_FUNCTION self_type; typedef BOOST_FUNCTION_FUNCTION self_type;
BOOST_FUNCTION_FUNCTION() : function_base() { } BOOST_FUNCTION_FUNCTION() : function_base() { }
@ -611,19 +618,6 @@ namespace boost {
{ {
this->assign_to(f); 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 #ifndef BOOST_NO_SFINAE
BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { } BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
@ -649,7 +643,7 @@ namespace boost {
if (this->empty()) if (this->empty())
boost::throw_exception(bad_function_call()); boost::throw_exception(bad_function_call());
return static_cast<vtable_type*>(vtable)->invoker return reinterpret_cast<const vtable_type*>(vtable)->invoker
(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
} }
#else #else
@ -673,25 +667,18 @@ namespace boost {
operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{ {
this->clear(); this->clear();
#ifndef BOOST_NO_EXCEPTIONS
try { try {
this->assign_to(f); this->assign_to(f);
} catch (...) { } catch (...) {
vtable = 0; vtable = 0;
throw; throw;
} }
#else
this->assign_to(f);
#endif
return *this; 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 #ifndef BOOST_NO_SFINAE
BOOST_FUNCTION_FUNCTION& operator=(clear_type*) BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
@ -715,12 +702,16 @@ namespace boost {
return *this; return *this;
this->clear(); this->clear();
#ifndef BOOST_NO_EXCEPTIONS
try { try {
this->assign_to_own(f); this->assign_to_own(f);
} catch (...) { } catch (...) {
vtable = 0; vtable = 0;
throw; throw;
} }
#else
this->assign_to_own(f);
#endif
return *this; return *this;
} }
@ -738,7 +729,7 @@ namespace boost {
void clear() void clear()
{ {
if (vtable) { if (vtable) {
static_cast<vtable_type*>(vtable)->clear(this->functor); reinterpret_cast<const vtable_type*>(vtable)->clear(this->functor);
vtable = 0; vtable = 0;
} }
} }
@ -773,64 +764,84 @@ namespace boost {
} }
template<typename Functor> template<typename Functor>
void assign_to(Functor f) void assign_to(const Functor& f)
{ {
static vtable_type stored_vtable(f); using detail::function::vtable_base;
if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable;
else vtable = 0; typedef typename detail::function::get_function_tag<Functor>::type tag;
} typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
template<typename Functor,typename Allocator> typedef typename get_invoker::
void assign_to_a(Functor f,Allocator a) template apply<Functor, R BOOST_FUNCTION_COMMA
{ BOOST_FUNCTION_TEMPLATE_ARGS, Allocator>
static vtable_type stored_vtable(f,a); handler_type;
if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable;
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;
else vtable = 0; else vtable = 0;
} }
}; };
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
typename Allocator>
inline void swap(BOOST_FUNCTION_FUNCTION< inline void swap(BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS BOOST_FUNCTION_TEMPLATE_ARGS ,
Allocator
>& f1, >& f1,
BOOST_FUNCTION_FUNCTION< BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS BOOST_FUNCTION_TEMPLATE_ARGS,
Allocator
>& f2) >& f2)
{ {
f1.swap(f2); f1.swap(f2);
} }
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
typename BOOST_FUNCTION_FUNCTION< typename BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
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>
::operator()(BOOST_FUNCTION_PARMS) const ::operator()(BOOST_FUNCTION_PARMS) const
{ {
if (this->empty()) if (this->empty())
boost::throw_exception(bad_function_call()); boost::throw_exception(bad_function_call());
return static_cast<vtable_type*>(vtable)->invoker return reinterpret_cast<const vtable_type*>(vtable)->invoker
(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
} }
#endif #endif
// Poison comparisons between boost::function objects of the same type. // Poison comparisons between boost::function objects of the same type.
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
typename Allocator>
void operator==(const BOOST_FUNCTION_FUNCTION< void operator==(const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS>&, BOOST_FUNCTION_TEMPLATE_ARGS ,
Allocator>&,
const BOOST_FUNCTION_FUNCTION< const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS>&); BOOST_FUNCTION_TEMPLATE_ARGS ,
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> Allocator>&);
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
typename Allocator>
void operator!=(const BOOST_FUNCTION_FUNCTION< void operator!=(const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS>&, BOOST_FUNCTION_TEMPLATE_ARGS ,
Allocator>&,
const BOOST_FUNCTION_FUNCTION< const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS>& ); BOOST_FUNCTION_TEMPLATE_ARGS ,
Allocator>&);
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
@ -841,16 +852,20 @@ template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
#endif #endif
template<typename R BOOST_FUNCTION_COMMA template<typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS> BOOST_FUNCTION_TEMPLATE_PARMS,
class function<BOOST_FUNCTION_PARTIAL_SPEC> typename Allocator>
: public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>
: public BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
BOOST_FUNCTION_COMMA Allocator>
{ {
typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type; typedef BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
BOOST_FUNCTION_COMMA Allocator> base_type;
typedef function self_type; typedef function self_type;
struct clear_type {}; struct clear_type {};
public: public:
typedef typename base_type::allocator_type allocator_type;
function() : base_type() {} function() : base_type() {}
@ -866,18 +881,6 @@ public:
base_type(f) 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 #ifndef BOOST_NO_SFINAE
function(clear_type*) : base_type() {} function(clear_type*) : base_type() {}
@ -930,6 +933,8 @@ public:
// Cleanup after ourselves... // Cleanup after ourselves...
#undef BOOST_FUNCTION_VTABLE #undef BOOST_FUNCTION_VTABLE
#undef BOOST_FUNCTION_GET_INVOKER
#undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
#undef BOOST_FUNCTION_COMMA #undef BOOST_FUNCTION_COMMA
#undef BOOST_FUNCTION_FUNCTION #undef BOOST_FUNCTION_FUNCTION
#undef BOOST_FUNCTION_FUNCTION_INVOKER #undef BOOST_FUNCTION_FUNCTION_INVOKER
@ -938,10 +943,12 @@ public:
#undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_FUNCTION_REF_INVOKER #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_VOID_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_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER #undef BOOST_FUNCTION_GET_MEMBER_INVOKER
#undef BOOST_FUNCTION_TEMPLATE_PARMS #undef BOOST_FUNCTION_TEMPLATE_PARMS
#undef BOOST_FUNCTION_TEMPLATE_ARGS #undef BOOST_FUNCTION_TEMPLATE_ARGS
#undef BOOST_FUNCTION_PARMS #undef BOOST_FUNCTION_PARMS
@ -951,7 +958,3 @@ public:
#undef BOOST_FUNCTION_ARG_TYPES #undef BOOST_FUNCTION_ARG_TYPES
#undef BOOST_FUNCTION_VOID_RETURN_TYPE #undef BOOST_FUNCTION_VOID_RETURN_TYPE
#undef BOOST_FUNCTION_RETURN #undef BOOST_FUNCTION_RETURN
#if defined(BOOST_MSVC)
# pragma warning( pop )
#endif

View File

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