Compare commits

...

39 Commits

Author SHA1 Message Date
922ce7b8ae Branch at revision 46530
[SVN r46531]
2008-06-19 18:57:10 +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
80a3f47099 Committed patch to eliminate warnings with GCC's -Wundef. Fixes #1197
[SVN r38827]
2007-08-21 15:35:19 +00:00
2a85edbd31 Remove V1 Jamfiles
[SVN r38516]
2007-08-08 19:02:26 +00:00
5c514ebe35 Try to work around EC++4 bug
[SVN r37471]
2007-04-18 12:13:53 +00:00
6a3f0df553 Add copyright, license
[SVN r35905]
2006-11-07 19:11:57 +00:00
64c8d10fa8 Eliminate MSVC 8.0 warning
[SVN r35588]
2006-10-13 14:29:56 +00:00
a2a810d2c1 Put back #include <functional> in case functionN.hpp is used directly
[SVN r34519]
2006-07-12 22:12:01 +00:00
d84481361f TR1 cyclic dependency fixes.
[SVN r34499]
2006-07-10 13:17:41 +00:00
872f12efee TR1 conformance: derive from unary_function/binary_function
[SVN r34481]
2006-07-08 18:07:33 +00:00
69ee6e2375 Fixed an 'unused parameter' warning.
[SVN r33204]
2006-03-02 21:24:57 +00:00
fdd91dbf91 Stop using assert() in tests
[SVN r33181]
2006-02-28 22:56:33 +00:00
87ad11583c Use ~Functor instead of ~function_type always, since it makes Borland
and vc6 and who knows what else happy.


[SVN r32832]
2006-02-11 19:08:25 +00:00
9fe1351ab7 Workaround for Borland compilers, from Alistair
[SVN r32394]
2006-01-24 13:57:25 +00:00
58b61efb5f trivial adjustments to enable warning-free compilation with gcc -Wall -W -Werror
[SVN r32364]
2006-01-20 16:53:30 +00:00
f195b6c10a Fixes for GCC 2.95.3
[SVN r32319]
2006-01-13 19:32:58 +00:00
2b4f81ca67 Workaround for GCC 2.95.3
[SVN r32302]
2006-01-13 02:45:33 +00:00
1f51812589 EDG 238 compatibility (and potentially other compilers)
[SVN r32294]
2006-01-12 15:31:46 +00:00
78f6b385d5 Small buffer optimization for Boost.Function
[SVN r32282]
2006-01-10 23:52:35 +00:00
93c691fbdf function_base.hpp, function_template.hpp:
- Use a vtable instead of separate manager/invoker pointers, to shrink the
    size of a boost::function object to 8 bytes
  - Fix a problem with NULL member pointers


[SVN r32186]
2005-12-30 02:31:51 +00:00
c5e64fab99 BOOST_CRITICAL_ERROR is no longer usable
[SVN r32185]
2005-12-30 02:27:13 +00:00
6023ff5608 Workaround for a problem in Wave.
[SVN r32094]
2005-12-18 21:06:32 +00:00
944c2ea72a Merged from Version_1_33_1
[SVN r31949]
2005-12-08 03:23:02 +00:00
35e2ff56a0 Large patch from Ulrich Eckhardt to fix support for EVC++ 4.
[SVN r30670]
2005-08-25 16:27:28 +00:00
b5b12295c2 Try to work around Borland parsing bug
[SVN r30645]
2005-08-24 14:12:03 +00:00
eea010ef80 Fully-qualify detail namespace accesses to work around compiler bugs
[SVN r30627]
2005-08-22 12:55:34 +00:00
b8ef34c043 Merged from 1.33.0 release
[SVN r30540]
2005-08-12 13:02:37 +00:00
18 changed files with 1060 additions and 622 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,10 +1,40 @@
<?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$">
<title>History &amp; Compatibility Notes</title>
<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>
<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>
</itemizedlist>
</listitem>
<listitem><para><bold>Version 1.30.0</bold>: </para>
<itemizedlist spacing="compact">
<listitem><para>All features deprecated in version 1.29.0 have

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">
@ -118,6 +125,12 @@
<returns><simpara><code>true</code> if <code>this-&gt;<methodname>target</methodname>&lt;Functor&gt;()</code> is non-NULL and <code><functionname>function_equal</functionname>(*(this-&gt;target&lt;Functor&gt;()), f)</code></simpara></returns>
</method>
<method name="target_type" cv="const">
<type>const std::type_info&amp;</type>
<returns><simpara><code>typeid</code> of the target function object, or <code>typeid(void)</code> if <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></returns>
<throws><simpara>Will not throw.</simpara></throws>
</method>
</method-group>
</class>
@ -128,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>
@ -147,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>
@ -182,7 +191,7 @@
</struct>
<constructor>
<postconditions><simpara><code>this-><methodname>empty</methodname>()</code></simpara></postconditions>
<postconditions><simpara><code>this-&gt;<methodname>empty</methodname>()</code></simpara></postconditions>
<throws><simpara>Will not throw.</simpara></throws>
</constructor>
@ -201,11 +210,23 @@
<parameter name="f"><paramtype>F</paramtype></parameter>
<requires><simpara>F is a function object Callable from <code>this</code>.</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>
<throws><simpara>Will not throw when <code>f</code> is a stateless function object.</simpara></throws>
</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-><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>
</destructor>
@ -213,8 +234,7 @@
<parameter name="f">
<paramtype>const <classname>functionN</classname>&amp;</paramtype>
</parameter>
<postconditions><simpara><code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>.</simpara></postconditions>
<throws><simpara>Will not throw when the target of <code>f</code> is a stateless function object or a reference to the function object.</simpara></throws>
<postconditions><simpara>If copy construction does not throw, <code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></postconditions>
</copy-assignment>
<method-group name="modifiers">
@ -222,13 +242,11 @@
<type>void</type>
<parameter name="f"><paramtype>const <classname>functionN</classname>&amp;</paramtype></parameter>
<effects><simpara>Interchanges the targets of <code>*this</code> and <code>f</code>.</simpara></effects>
<throws><simpara>Will not throw.</simpara></throws>
</method>
<method name="clear">
<type>void</type>
<postconditions><simpara>this-&gt;<methodname>empty</methodname>()</simpara></postconditions>
<throws><simpara>Will not throw.</simpara></throws>
</method>
</method-group>
@ -286,6 +304,13 @@
<returns><simpara><code>true</code> if <code>this-&gt;<methodname>target</methodname>&lt;Functor&gt;()</code> is non-NULL and <code><functionname>function_equal</functionname>(*(this-&gt;target&lt;Functor&gt;()), f)</code></simpara></returns>
</method>
<method name="target_type" cv="const">
<type>const std::type_info&amp;</type>
<returns><simpara><code>typeid</code> of the target function object, or <code>typeid(void)</code> if <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></returns>
<throws><simpara>Will not throw.</simpara></throws>
</method>
</method-group>
<method-group name="invocation">
@ -297,7 +322,7 @@
<parameter name="aN"><paramtype>argN_type</paramtype></parameter>
<effects><simpara><code>f(a1, a2, ..., aN)</code>, where <code>f</code> is the target of <code>*this</code>.</simpara></effects>
<returns><simpara>if <code>R</code> is <code>void</code>, nothing is returned; otherwise, the return value of the call to <code>f</code> is returned.</simpara></returns>
<throws><simpara><code><classname>bad_function_call</classname></code> if <code>!this-&gt;<methodname>empty</methodname>()</code>. Otherwise, may through any exception thrown by the target function <code>f</code>.</simpara></throws>
<throws><simpara><code><classname>bad_function_call</classname></code> if <code>this-&gt;<methodname>empty</methodname>()</code>. Otherwise, may through any exception thrown by the target function <code>f</code>.</simpara></throws>
</method>
</method-group>
@ -308,13 +333,11 @@
<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>
<throws><simpara>Will not throw.</simpara></throws>
</function>
</free-function-group>
@ -326,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>
@ -339,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>
@ -352,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>
@ -365,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>
@ -378,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
@ -427,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>
@ -440,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>
@ -453,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>
@ -466,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>
@ -479,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
@ -528,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>
@ -554,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>
@ -589,7 +596,7 @@
</struct>
<constructor>
<postconditions><simpara><code>this-><methodname>empty</methodname>()</code></simpara></postconditions>
<postconditions><simpara><code>this-&gt;<methodname>empty</methodname>()</code></simpara></postconditions>
<throws><simpara>Will not throw.</simpara></throws>
</constructor>
@ -616,28 +623,39 @@
<parameter name="f"><paramtype>F</paramtype></parameter>
<requires><simpara>F is a function object Callable from <code>this</code>.</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>
<throws><simpara>Will not throw when <code>f</code> is a stateless function object.</simpara></throws>
</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-><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>
</destructor>
<copy-assignment>
<parameter name="f">
<paramtype>const <classname>functionN</classname>&amp;</paramtype>
<paramtype>const <classname>function</classname>&amp;</paramtype>
</parameter>
<postconditions><simpara><code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code></simpara></postconditions>
<throws><simpara>Will not throw when the target of <code>f</code> is a stateless function object or a reference to the function object.</simpara></throws>
<postconditions><simpara>If copy construction does not throw, <code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></postconditions>
</copy-assignment>
<copy-assignment>
<parameter name="f">
<paramtype>const <classname>function</classname>&amp;</paramtype>
</parameter>
<postconditions><simpara><code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code></simpara></postconditions>
<throws><simpara>Will not throw when the target of <code>f</code> is a stateless function object or a reference to the function object.</simpara></throws>
<postconditions><simpara>If copy construction of the target of <code>f</code> does not throw, <code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>. </simpara></postconditions>
<throws><simpara>Will not throw when the target of <code>f</code> is a stateless function object or a reference to the function object. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></throws>
</copy-assignment>
<method-group name="modifiers">
@ -645,7 +663,6 @@
<type>void</type>
<parameter name="f"><paramtype>const <classname>function</classname>&amp;</paramtype></parameter>
<effects><simpara>Interchanges the targets of <code>*this</code> and <code>f</code>.</simpara></effects>
<throws><simpara>Will not throw.</simpara></throws>
</method>
<method name="clear">
@ -708,6 +725,12 @@
<returns><simpara><code>true</code> if <code>this-&gt;<methodname>target</methodname>&lt;Functor&gt;()</code> is non-NULL and <code><functionname>function_equal</functionname>(*(this-&gt;target&lt;Functor&gt;()), f)</code></simpara></returns>
</method>
<method name="target_type" cv="const">
<type>const std::type_info&amp;</type>
<returns><simpara><code>typeid</code> of the target function object, or <code>typeid(void)</code> if <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></returns>
<throws><simpara>Will not throw.</simpara></throws>
</method>
</method-group>
<method-group name="invocation">
@ -719,7 +742,7 @@
<parameter name="aN"><paramtype>argN_type</paramtype></parameter>
<effects><simpara><code>f(a1, a2, ..., aN)</code>, where <code>f</code> is the target of <code>*this</code>.</simpara></effects>
<returns><simpara>if <code>R</code> is <code>void</code>, nothing is returned; otherwise, the return value of the call to <code>f</code> is returned.</simpara></returns>
<throws><simpara><code><classname>bad_function_call</classname></code> if <code>!this-&gt;<methodname>empty</methodname>()</code>. Otherwise, may through any exception thrown by the target function <code>f</code>.</simpara></throws>
<throws><simpara><code><classname>bad_function_call</classname></code> if <code>this-&gt;<methodname>empty</methodname>()</code>. Otherwise, may through any exception thrown by the target function <code>f</code>.</simpara></throws>
</method>
</method-group>
@ -727,13 +750,11 @@
<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>
<throws><simpara>Will not throw.</simpara></throws>
</function>
</free-function-group>
@ -742,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
@ -823,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

@ -10,6 +10,8 @@
// William Kempf, Jesse Jones and Karl Nelson were all very helpful in the
// design of this library.
#include <functional> // unary_function, binary_function
#include <boost/preprocessor/iterate.hpp>
#include <boost/detail/workaround.hpp>
@ -22,7 +24,7 @@
#include <boost/function/detail/prologue.hpp>
// Visual Age C++ doesn't handle the file iteration well
#if BOOST_WORKAROUND(__IBMCPP__, <= 600)
#if BOOST_WORKAROUND(__IBMCPP__, >= 500)
# if BOOST_FUNCTION_MAX_ARGS >= 0
# include <boost/function/function0.hpp>
# endif

View File

@ -11,6 +11,7 @@
#define BOOST_FUNCTION_PROLOGUE_HPP
# include <cassert>
# include <algorithm>
# 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>
@ -21,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-2004. 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
@ -19,10 +20,10 @@
#include <boost/assert.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/composite_traits.hpp>
#include <boost/type_traits/is_stateless.hpp>
#include <boost/ref.hpp>
#include <boost/pending/ct_if.hpp>
#include <boost/mpl/if.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/type_traits/alignment_of.hpp>
#ifndef BOOST_NO_SFINAE
# include "boost/utility/enable_if.hpp"
#else
@ -30,6 +31,20 @@
#endif
#include <boost/function_equal.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.
#ifdef BOOST_NO_EXCEPTION_STD_NAMESPACE
// Embedded VC++ does not have type_info in namespace std
# define BOOST_FUNCTION_STD_NS
#else
# define BOOST_FUNCTION_STD_NS std
#endif
// Borrowed from Boost.Python library: determines the cases where we
// need to use std::type_info::name to compare instead of operator==.
# if (defined(__GNUC__) && __GNUC__ >= 3) \
@ -80,21 +95,12 @@ namespace boost { namespace python { namespace objects {
#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> >
template<typename Signature>
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)
template<typename Signature>
inline void swap(function<Signature>& f1,
function<Signature>& f2)
{
f1.swap(f2);
}
@ -105,42 +111,36 @@ inline void swap(function<Signature, Allocator>& f1,
namespace boost {
namespace detail {
namespace function {
class X;
/**
* A union of a function pointer and a void pointer. This is necessary
* because 5.2.10/6 allows reinterpret_cast<> to safely cast between
* function pointer types and 5.2.9/10 allows static_cast<> to safely
* cast between a void pointer and an object pointer. But it is not legal
* to cast between a function pointer and a void* (in either direction),
* so function requires a union of the two. */
union any_pointer
* A buffer used to store small function objects in
* boost::function. It is a union containing function pointers,
* object pointers, and a structure that resembles a bound
* member function pointer.
*/
union function_buffer
{
// For pointers to function objects
void* obj_ptr;
// For pointers to std::type_info objects
// (get_functor_type_tag, check_functor_type_tag).
const void* const_obj_ptr;
void (*func_ptr)();
char data[1];
// For function pointers of all kinds
mutable void (*func_ptr)();
// For bound member pointers
struct bound_memfunc_ptr_t {
void (X::*memfunc_ptr)(int);
void* obj_ptr;
} bound_memfunc_ptr;
// To relax aliasing constraints
mutable char data;
};
inline any_pointer make_any_pointer(void* o)
{
any_pointer p;
p.obj_ptr = o;
return p;
}
inline any_pointer make_any_pointer(const void* o)
{
any_pointer p;
p.const_obj_ptr = o;
return p;
}
inline any_pointer make_any_pointer(void (*f)())
{
any_pointer p;
p.func_ptr = f;
return p;
}
/**
* The unusable class is a placeholder for unused function arguments
* It is also completely unusable except that it constructable from
@ -169,7 +169,8 @@ namespace boost {
enum functor_manager_operation_type {
clone_functor_tag,
destroy_functor_tag,
check_functor_type_tag
check_functor_type_tag,
get_functor_type_tag
};
// Tags used to decide between different types of functions
@ -177,54 +178,86 @@ namespace boost {
struct function_obj_tag {};
struct member_ptr_tag {};
struct function_obj_ref_tag {};
struct stateless_function_obj_tag {};
template<typename F>
class get_function_tag
{
typedef typename ct_if<(is_pointer<F>::value),
function_ptr_tag,
function_obj_tag>::type ptr_or_obj_tag;
typedef typename mpl::if_c<(is_pointer<F>::value),
function_ptr_tag,
function_obj_tag>::type ptr_or_obj_tag;
typedef typename ct_if<(is_member_pointer<F>::value),
member_ptr_tag,
ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
typedef typename mpl::if_c<(is_member_pointer<F>::value),
member_ptr_tag,
ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
typedef typename ct_if<(is_reference_wrapper<F>::value),
function_obj_ref_tag,
ptr_or_obj_or_mem_tag>::type or_ref_tag;
typedef typename mpl::if_c<(is_reference_wrapper<F>::value),
function_obj_ref_tag,
ptr_or_obj_or_mem_tag>::type or_ref_tag;
public:
typedef typename ct_if<(is_stateless<F>::value),
stateless_function_obj_tag,
or_ref_tag>::type type;
typedef or_ref_tag type;
};
// The trivial manager does nothing but return the same pointer (if we
// are cloning) or return the null pointer (if we are deleting).
template<typename F>
struct trivial_manager
struct reference_manager
{
static inline any_pointer
get(any_pointer f, functor_manager_operation_type op)
static inline void
get(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op)
{
switch (op) {
case clone_functor_tag: return f;
case clone_functor_tag:
out_buffer.obj_ptr = in_buffer.obj_ptr;
return;
case destroy_functor_tag:
return make_any_pointer(reinterpret_cast<void*>(0));
out_buffer.obj_ptr = 0;
return;
case check_functor_type_tag:
{
std::type_info* t = static_cast<std::type_info*>(f.obj_ptr);
return BOOST_FUNCTION_COMPARE_TYPE_ID(typeid(F), *t)?
f
: make_any_pointer(reinterpret_cast<void*>(0));
// 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;
else
out_buffer.obj_ptr = 0;
}
}
return;
// Clears up a warning with GCC 3.2.3
return make_any_pointer(reinterpret_cast<void*>(0));
case get_functor_type_tag:
out_buffer.const_obj_ptr = &typeid(F);
return;
}
}
};
/**
* Determine if boost::function can use the small-object
* optimization with the function object type F.
*/
template<typename F>
struct function_allows_small_object_optimization
{
BOOST_STATIC_CONSTANT
(bool,
value = ((sizeof(F) <= sizeof(function_buffer) &&
(alignment_of<function_buffer>::value
% 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)
{
}
};
@ -232,95 +265,225 @@ namespace boost {
* 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 == 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;
}
}
// 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) {
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;
}
}
};
template<typename Functor>
struct functor_manager
{
private:
typedef Functor functor_type;
// For function pointers, the manager is trivial
static inline any_pointer
manager(any_pointer function_ptr,
functor_manager_operation_type op,
function_ptr_tag)
// 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)
return function_ptr;
else
return make_any_pointer(static_cast<void (*)()>(0));
functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
}
// For function object pointers, we clone the pointer to each
// function has its own version.
static inline any_pointer
manager(any_pointer function_obj_ptr,
functor_manager_operation_type op,
function_obj_tag)
// 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_)
{
#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) {
functor_type* f =
static_cast<functor_type*>(function_obj_ptr.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
// 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);
functor_type* new_f = new functor_type(*f);
# endif // BOOST_NO_STD_ALLOCATOR
return make_any_pointer(static_cast<void*>(new_f));
}
else {
out_buffer.obj_ptr = new_f;
} else if (op == destroy_functor_tag) {
/* Cast from the void pointer to the functor pointer type */
functor_type* f =
reinterpret_cast<functor_type*>(function_obj_ptr.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
static_cast<functor_type*>(out_buffer.obj_ptr);
delete f;
# endif // BOOST_NO_STD_ALLOCATOR
return make_any_pointer(static_cast<void*>(0));
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:
/* Dispatch to an appropriate manager based on whether we have a
function pointer or a function object pointer. */
static any_pointer
manage(any_pointer functor_ptr, functor_manager_operation_type op)
static inline void
manage(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op)
{
if (op == check_functor_type_tag) {
std::type_info* type =
static_cast<std::type_info*>(functor_ptr.obj_ptr);
return (BOOST_FUNCTION_COMPARE_TYPE_ID(typeid(Functor), *type)?
functor_ptr
: make_any_pointer(reinterpret_cast<void*>(0)));
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;
}
else {
typedef typename get_function_tag<functor_type>::type tag_type;
return manager(functor_ptr, op, tag_type());
}
};
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, 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
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:
/* 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.const_obj_ptr = &typeid(functor_type);
return;
default:
manager(in_buffer, out_buffer, op, tag_type());
return;
}
}
};
@ -386,6 +549,18 @@ namespace boost {
else return true;
}
#endif // BOOST_NO_SFINAE
/**
* Stores the "manager" portion of the vtable for a
* boost::function object.
*/
struct vtable_base
{
vtable_base() : manager(0) { }
void (*manager)(const function_buffer& in_buffer,
function_buffer& out_buffer,
functor_manager_operation_type op);
};
} // end namespace function
} // end namespace detail
@ -398,62 +573,61 @@ namespace boost {
class function_base
{
public:
function_base() : manager(0)
{
functor.obj_ptr = 0;
}
function_base() : vtable(0) { }
// Is this function empty?
bool empty() const { return !manager; }
/** Determine if the function is empty (i.e., has no target). */
bool empty() const { return !vtable; }
/** Retrieve the type of the stored function object, or typeid(void)
if this is empty. */
const BOOST_FUNCTION_STD_NS::type_info& target_type() const
{
if (!vtable) return typeid(void);
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);
}
template<typename Functor>
Functor* target()
{
if (!manager) return 0;
if (!vtable) return 0;
detail::function::any_pointer result =
manager(detail::function::make_any_pointer(&typeid(Functor)),
detail::function::check_functor_type_tag);
if (!result.obj_ptr) return 0;
else {
typedef typename detail::function::get_function_tag<Functor>::type tag;
return get_functor_pointer<Functor>(tag(), 0);
}
detail::function::function_buffer type_result;
type_result.const_obj_ptr = &typeid(Functor);
vtable->manager(functor, type_result,
detail::function::check_functor_type_tag);
return static_cast<Functor*>(type_result.obj_ptr);
}
template<typename Functor>
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
const Functor* target( Functor * = 0 ) const
#else
const Functor* target() const
#endif
{
if (!manager) return 0;
if (!vtable) return 0;
detail::function::any_pointer result =
manager(detail::function::make_any_pointer(&typeid(Functor)),
detail::function::check_functor_type_tag);
if (!result.obj_ptr) return 0;
else {
typedef typename detail::function::get_function_tag<Functor>::type tag;
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
return get_functor_pointer(tag(), 0, (Functor*)0);
#else
return get_functor_pointer<Functor>(tag(), 0);
#endif
}
detail::function::function_buffer type_result;
type_result.const_obj_ptr = &typeid(Functor);
vtable->manager(functor, type_result,
detail::function::check_functor_type_tag);
// GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do.
return (const Functor*)(type_result.obj_ptr);
}
template<typename F>
bool contains(const F& f) const
{
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
if (const F* fp = this->target( (F*)0 )) {
if (const F* fp = this->target( (F*)0 ))
#else
if (const F* fp = this->template target<F>()) {
if (const F* fp = this->template target<F>())
#endif
{
return function_equal(*fp, f);
} else {
return false;
@ -484,44 +658,8 @@ public:
#endif
public: // should be protected, but GCC 2.95.3 will fail to allow access
detail::function::any_pointer (*manager)(
detail::function::any_pointer,
detail::function::functor_manager_operation_type);
detail::function::any_pointer functor;
private:
template<typename Functor>
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
Functor* get_functor_pointer(detail::function::function_ptr_tag, int, Functor * = 0)
#else
Functor* get_functor_pointer(detail::function::function_ptr_tag, int)
#endif
{ return reinterpret_cast<Functor*>(&functor.func_ptr); }
template<typename Functor, typename Tag>
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
Functor* get_functor_pointer(Tag, long, Functor * = 0)
#else
Functor* get_functor_pointer(Tag, long)
#endif
{ return static_cast<Functor*>(functor.obj_ptr); }
template<typename Functor>
const Functor*
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
get_functor_pointer(detail::function::function_ptr_tag, int, Functor * = 0) const
#else
get_functor_pointer(detail::function::function_ptr_tag, int) const
#endif
{ return reinterpret_cast<const Functor*>(&functor.func_ptr); }
template<typename Functor, typename Tag>
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
const Functor* get_functor_pointer(Tag, long, Functor * = 0) const
#else
const Functor* get_functor_pointer(Tag, long) const
#endif
{ return static_cast<const Functor*>(functor.const_obj_ptr); }
detail::function::vtable_base* vtable;
mutable detail::function::function_buffer functor;
};
/**

View File

@ -1,8 +1,9 @@
// Boost.Function library
// Copyright Douglas Gregor 2001-2003. 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)
@ -22,17 +28,10 @@
#define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
#define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(arg, BOOST_PP_CAT(BOOST_PP_INC(I),_type));
typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type);
#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
@ -50,22 +49,23 @@
BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(stateless_void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_FUNCTION_REF_INVOKER \
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_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_STATELESS_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(get_stateless_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_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
#ifndef BOOST_NO_VOID_RETURNS
# define BOOST_FUNCTION_VOID_RETURN_TYPE void
# define BOOST_FUNCTION_RETURN(X) X
#else
# define BOOST_FUNCTION_VOID_RETURN_TYPE ::boost::detail::function::unusable
# define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable
# define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
#endif
@ -79,7 +79,7 @@ namespace boost {
>
struct BOOST_FUNCTION_FUNCTION_INVOKER
{
static R invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
@ -95,7 +95,7 @@ namespace boost {
struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
{
static BOOST_FUNCTION_VOID_RETURN_TYPE
invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
@ -111,11 +111,15 @@ namespace boost {
>
struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
{
static R invoke(any_pointer function_obj_ptr BOOST_FUNCTION_COMMA
static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
FunctionObj* f;
if (function_allows_small_object_optimization<FunctionObj>::value)
f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
else
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
return (*f)(BOOST_FUNCTION_ARGS);
}
};
@ -128,11 +132,15 @@ namespace boost {
struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
{
static BOOST_FUNCTION_VOID_RETURN_TYPE
invoke(any_pointer function_obj_ptr BOOST_FUNCTION_COMMA
invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
FunctionObj* f;
if (function_allows_small_object_optimization<FunctionObj>::value)
f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
else
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
}
};
@ -142,12 +150,15 @@ namespace boost {
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
struct BOOST_FUNCTION_FUNCTION_REF_INVOKER
{
static R invoke(any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS)
static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
FunctionObj f = FunctionObj();
return f(BOOST_FUNCTION_ARGS);
FunctionObj* f =
reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
return (*f)(BOOST_FUNCTION_ARGS);
}
};
@ -156,14 +167,16 @@ namespace boost {
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
{
static BOOST_FUNCTION_VOID_RETURN_TYPE
invoke(any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS)
invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
FunctionObj f = FunctionObj();
BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
FunctionObj* f =
reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
}
};
@ -174,7 +187,7 @@ namespace boost {
>
struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
{
typedef typename ct_if<(is_void<R>::value),
typedef typename mpl::if_c<(is_void<R>::value),
BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
FunctionPtr,
R BOOST_FUNCTION_COMMA
@ -195,7 +208,7 @@ namespace boost {
>
struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
{
typedef typename ct_if<(is_void<R>::value),
typedef typename mpl::if_c<(is_void<R>::value),
BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
@ -214,15 +227,15 @@ namespace boost {
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
{
typedef typename ct_if<(is_void<R>::value),
BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER<
typedef typename mpl::if_c<(is_void<R>::value),
BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>,
BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER<
BOOST_FUNCTION_FUNCTION_REF_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
@ -230,25 +243,333 @@ namespace boost {
>::type type;
};
/**
* vtable for a specific boost::function instance.
*/
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;
#else
typedef typename function_return_type<R>::type result_type;
#endif // BOOST_NO_VOID_RETURNS
typedef result_type (*invoker_type)(function_buffer&
BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS);
template<typename F>
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());
}
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)
{
if (manager)
manager(functor, functor, destroy_functor_tag);
}
private:
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)
{
this->clear(functor);
if (f) {
// should be a reinterpret cast, but some compilers insist
// on giving cv-qualifiers to free functions
functor.func_ptr = (void (*)())(f);
return true;
} else {
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>
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) {
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;
}
}
#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(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(FunctionObj f, function_buffer& functor, mpl::false_)
{
functor.obj_ptr = new FunctionObj(f);
}
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(FunctionObj f, function_buffer& functor, function_obj_tag)
{
if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
assign_functor(f, functor,
mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
return true;
} else {
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
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())) {
// 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();
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:
invoker_type invoker;
};
} // end namespace function
} // end namespace detail
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
#if BOOST_FUNCTION_NUM_ARGS == 1
, public std::unary_function<T0,R>
#elif BOOST_FUNCTION_NUM_ARGS == 2
, public std::binary_function<T0,T1,R>
#endif
{
public:
#ifndef BOOST_NO_VOID_RETURNS
typedef R result_type;
#else
typedef typename detail::function::function_return_type<R>::type
typedef typename boost::detail::function::function_return_type<R>::type
result_type;
#endif // BOOST_NO_VOID_RETURNS
private:
typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
vtable_type;
struct clear_type {};
public:
@ -271,11 +592,9 @@ 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()
, invoker(0) {}
BOOST_FUNCTION_FUNCTION() : function_base() { }
// MSVC chokes if the following two constructors are collapsed into
// one with a default parameter.
@ -283,36 +602,46 @@ namespace boost {
BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
#ifndef BOOST_NO_SFINAE
,typename enable_if_c<
(::boost::type_traits::ice_not<
(boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value),
int>::type = 0
#endif // BOOST_NO_SFINAE
) :
function_base(),
invoker(0)
function_base()
{
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(), invoker(0) {}
BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
#else
BOOST_FUNCTION_FUNCTION(int zero) : function_base(), invoker(0)
BOOST_FUNCTION_FUNCTION(int zero) : function_base()
{
BOOST_ASSERT(zero == 0);
}
#endif
BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) :
function_base(),
invoker(0)
BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
{
this->assign_to_own(f);
}
~BOOST_FUNCTION_FUNCTION() { clear(); }
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// MSVC 6.0 and prior require all definitions to be inline, but
// these definitions can become very costly.
result_type operator()(BOOST_FUNCTION_PARMS) const
@ -320,7 +649,8 @@ namespace boost {
if (this->empty())
boost::throw_exception(bad_function_call());
return invoker(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
return static_cast<vtable_type*>(vtable)->invoker
(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
}
#else
result_type operator()(BOOST_FUNCTION_PARMS) const;
@ -334,7 +664,7 @@ namespace boost {
template<typename Functor>
#ifndef BOOST_NO_SFINAE
typename enable_if_c<
(::boost::type_traits::ice_not<
(boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value),
BOOST_FUNCTION_FUNCTION&>::type
#else
@ -342,9 +672,26 @@ namespace boost {
#endif
operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{
self_type(f).swap(*this);
this->clear();
try {
this->assign_to(f);
} catch (...) {
vtable = 0;
throw;
}
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*)
@ -367,7 +714,13 @@ namespace boost {
if (&f == this)
return *this;
self_type(f).swap(*this);
this->clear();
try {
this->assign_to_own(f);
} catch (...) {
vtable = 0;
throw;
}
return *this;
}
@ -376,21 +729,18 @@ namespace boost {
if (&other == this)
return;
std::swap(this->manager, other.manager);
std::swap(this->functor, other.functor);
std::swap(invoker, other.invoker);
BOOST_FUNCTION_FUNCTION tmp = *this;
*this = other;
other = tmp;
}
// Clear out a target, if there is one
void clear()
{
if (this->manager) {
function_base::functor =
this->manager(this->functor, detail::function::destroy_functor_tag);
if (vtable) {
static_cast<vtable_type*>(vtable)->clear(this->functor);
vtable = 0;
}
this->manager = 0;
invoker = 0;
}
#if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
@ -416,188 +766,71 @@ namespace boost {
void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
{
if (!f.empty()) {
invoker = f.invoker;
this->manager = f.manager;
this->functor =
f.manager(f.functor, detail::function::clone_functor_tag);
this->vtable = f.vtable;
f.vtable->manager(f.functor, this->functor,
boost::detail::function::clone_functor_tag);
}
}
template<typename Functor>
void assign_to(Functor f)
{
typedef typename detail::function::get_function_tag<Functor>::type tag;
this->assign_to(f, tag());
static vtable_type stored_vtable(f);
if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable;
else vtable = 0;
}
template<typename FunctionPtr>
void assign_to(FunctionPtr f, detail::function::function_ptr_tag)
template<typename Functor,typename Allocator>
void assign_to_a(Functor f,Allocator a)
{
clear();
if (f) {
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
this->manager =
&detail::function::functor_manager<FunctionPtr, Allocator>::manage;
this->functor =
this->manager(detail::function::make_any_pointer(
// should be a reinterpret cast, but some compilers
// insist on giving cv-qualifiers to free functions
(void (*)())(f)
),
detail::function::clone_functor_tag);
}
static vtable_type stored_vtable(f,a);
if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable;
else vtable = 0;
}
#if BOOST_FUNCTION_NUM_ARGS > 0
template<typename MemberPtr>
void assign_to(MemberPtr f, detail::function::member_ptr_tag)
{
this->assign_to(mem_fn(f));
}
#endif // BOOST_FUNCTION_NUM_ARGS > 0
template<typename FunctionObj>
void assign_to(FunctionObj f, detail::function::function_obj_tag)
{
if (!detail::function::has_empty_target(boost::addressof(f))) {
typedef
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
this->manager = &detail::function::functor_manager<
FunctionObj, Allocator>::manage;
#ifndef BOOST_NO_STD_ALLOCATOR
typedef typename Allocator::template rebind<FunctionObj>::other
rebound_allocator_type;
typedef typename rebound_allocator_type::pointer pointer_type;
rebound_allocator_type allocator;
pointer_type copy = allocator.allocate(1);
allocator.construct(copy, f);
// Get back to the original pointer type
FunctionObj* new_f = static_cast<FunctionObj*>(copy);
#else
FunctionObj* new_f = new FunctionObj(f);
#endif // BOOST_NO_STD_ALLOCATOR
this->functor =
detail::function::make_any_pointer(static_cast<void*>(new_f));
}
}
template<typename FunctionObj>
void assign_to(const reference_wrapper<FunctionObj>& f,
detail::function::function_obj_ref_tag)
{
if (!detail::function::has_empty_target(f.get_pointer())) {
typedef
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
this->manager = &detail::function::trivial_manager<FunctionObj>::get;
this->functor =
this->manager(
detail::function::make_any_pointer(
const_cast<FunctionObj*>(f.get_pointer())),
detail::function::clone_functor_tag);
}
}
template<typename FunctionObj>
void assign_to(FunctionObj, detail::function::stateless_function_obj_tag)
{
typedef
typename detail::function::
BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
this->manager = &detail::function::trivial_manager<FunctionObj>::get;
this->functor = detail::function::make_any_pointer(this);
}
typedef result_type (*invoker_type)(detail::function::any_pointer
BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS);
invoker_type invoker;
};
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, <= 1200)
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
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 invoker(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
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)
@ -608,20 +841,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() {}
@ -629,7 +858,7 @@ public:
function(Functor f
#ifndef BOOST_NO_SFINAE
,typename enable_if_c<
(::boost::type_traits::ice_not<
(boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value),
int>::type = 0
#endif
@ -637,6 +866,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() {}
@ -655,7 +896,7 @@ public:
template<typename Functor>
#ifndef BOOST_NO_SFINAE
typename enable_if_c<
(::boost::type_traits::ice_not<
(boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value),
self_type&>::type
#else
@ -688,18 +929,18 @@ public:
} // end namespace boost
// Cleanup after ourselves...
#undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
#undef BOOST_FUNCTION_VTABLE
#undef BOOST_FUNCTION_COMMA
#undef BOOST_FUNCTION_FUNCTION
#undef BOOST_FUNCTION_FUNCTION_INVOKER
#undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
#undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
#undef BOOST_FUNCTION_TEMPLATE_PARMS
#undef BOOST_FUNCTION_TEMPLATE_ARGS
@ -710,3 +951,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

@ -1,9 +1,20 @@
<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>
<body>
Automatic redirection failed, please go to
<a href="../../doc/html/function.html">../../doc/html/function.html</a>
<a href="../../doc/html/function.html">../../doc/html/function.html</a> &nbsp;<hr>
<p><EFBFBD> Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
</body>
</html>
</html>

View File

@ -1,68 +0,0 @@
# Function library
# Copyright (C) 2001-2003 Douglas Gregor
# 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/
# Testing Jamfile autogenerated from XML source
subproject libs/function/test ;
# bring in rules for testing
SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
include testing.jam ;
# Make tests run by default.
DEPENDS all : test ;
{
# look in BOOST_ROOT for sources first, just in this Jamfile
local SEARCH_SOURCE = $(BOOST_ROOT) $(SEARCH_SOURCE) ;
test-suite function
:
[ run libs/function/test/function_test.cpp : : : : lib_function_test ]
[ run libs/function/test/function_n_test.cpp : : : : ]
[ run libs/function/test/allocator_test.cpp : : : : ]
[ run libs/function/test/stateless_test.cpp : : : : ]
[ run libs/function/test/lambda_test.cpp : : : : ]
[ compile-fail libs/function/test/function_test_fail1.cpp : : : : ]
[ compile-fail libs/function/test/function_test_fail2.cpp : : : : ]
[ compile libs/function/test/function_30.cpp : : : : ]
[ run libs/function/test/function_arith_cxx98.cpp : : : : ]
[ run libs/function/test/function_arith_portable.cpp : : : : ]
[ run libs/function/test/sum_avg_cxx98.cpp : : : : ]
[ run libs/function/test/sum_avg_portable.cpp : : : : ]
[ run libs/function/test/mem_fun_cxx98.cpp : : : : ]
[ run libs/function/test/mem_fun_portable.cpp : : : : ]
[ run libs/function/test/std_bind_cxx98.cpp : : : : ]
[ run libs/function/test/std_bind_portable.cpp : : : : ]
[ run libs/function/test/function_ref_cxx98.cpp : : : : ]
[ run libs/function/test/function_ref_portable.cpp : : : : ]
[ run libs/function/test/contains_test.cpp : : : : ]
[ run libs/function/test/contains2_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;
};
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;
};
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

@ -10,7 +10,6 @@
#include <boost/test/minimal.hpp>
#include <boost/function.hpp>
#include <functional>
#include <cassert>
#include <string>
#include <utility>
@ -653,12 +652,12 @@ static void test_implicit()
static void test_call_obj(boost::function<int (int, int)> f)
{
assert(!f.empty());
BOOST_CHECK(!f.empty());
}
static void test_call_cref(const boost::function<int (int, int)>& f)
{
assert(!f.empty());
BOOST_CHECK(!f.empty());
}
static void test_call()

View File

@ -1,6 +1,6 @@
// Boost.Function library
// Copyright Douglas Gregor 2001-2003. Use, modification and
// Copyright (C) Douglas Gregor 2001-2005. 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)
@ -22,7 +22,7 @@ test_main(int, char*[])
if (f1 == f2) {
}
BOOST_CRITICAL_ERROR("This should not have compiled.");
BOOST_ERROR("This should not have compiled.");
return 0;
}

View File

@ -1,6 +1,6 @@
// Boost.Function library
// Copyright Douglas Gregor 2001-2003. Use, modification and
// Copyright (C) Douglas Gregor 2001-2005. 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)
@ -21,7 +21,7 @@ test_main(int, char*[])
function0<int> f1;
f1 = bad_fn;
BOOST_CRITICAL_ERROR("This should not have compiled.");
BOOST_ERROR("This should not have compiled.");
return 0;
}

View File

@ -14,23 +14,21 @@
struct stateless_integer_add {
int operator()(int x, int y) const { return x+y; }
void* operator new(std::size_t, stateless_integer_add*)
void* operator new(std::size_t)
{
throw std::runtime_error("Cannot allocate a stateless_integer_add");
}
void operator delete(void*, stateless_integer_add*) throw()
void* operator new(std::size_t, void* p)
{
return p;
}
void operator delete(void*) throw()
{
}
};
namespace boost {
template<>
struct is_stateless<stateless_integer_add> {
BOOST_STATIC_CONSTANT(bool, value = true);
};
}
int test_main(int, char*[])
{
boost::function2<int, int, int> f;