Compare commits

..

63 Commits

Author SHA1 Message Date
Ronald Garcia
687dff0782 Created a branch from trunk
[SVN r38959]
2007-08-26 05:34:35 +00:00
Douglas Gregor
80a3f47099 Committed patch to eliminate warnings with GCC's -Wundef. Fixes #1197
[SVN r38827]
2007-08-21 15:35:19 +00:00
Vladimir Prus
2a85edbd31 Remove V1 Jamfiles
[SVN r38516]
2007-08-08 19:02:26 +00:00
Douglas Gregor
5c514ebe35 Try to work around EC++4 bug
[SVN r37471]
2007-04-18 12:13:53 +00:00
Beman Dawes
6a3f0df553 Add copyright, license
[SVN r35905]
2006-11-07 19:11:57 +00:00
Douglas Gregor
64c8d10fa8 Eliminate MSVC 8.0 warning
[SVN r35588]
2006-10-13 14:29:56 +00:00
Peter Dimov
a2a810d2c1 Put back #include <functional> in case functionN.hpp is used directly
[SVN r34519]
2006-07-12 22:12:01 +00:00
Peter Dimov
d84481361f TR1 cyclic dependency fixes.
[SVN r34499]
2006-07-10 13:17:41 +00:00
Peter Dimov
872f12efee TR1 conformance: derive from unary_function/binary_function
[SVN r34481]
2006-07-08 18:07:33 +00:00
Peter Dimov
69ee6e2375 Fixed an 'unused parameter' warning.
[SVN r33204]
2006-03-02 21:24:57 +00:00
Dave Abrahams
fdd91dbf91 Stop using assert() in tests
[SVN r33181]
2006-02-28 22:56:33 +00:00
Dave Abrahams
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
Douglas Gregor
9fe1351ab7 Workaround for Borland compilers, from Alistair
[SVN r32394]
2006-01-24 13:57:25 +00:00
Ralf W. Grosse-Kunstleve
58b61efb5f trivial adjustments to enable warning-free compilation with gcc -Wall -W -Werror
[SVN r32364]
2006-01-20 16:53:30 +00:00
Douglas Gregor
f195b6c10a Fixes for GCC 2.95.3
[SVN r32319]
2006-01-13 19:32:58 +00:00
Douglas Gregor
2b4f81ca67 Workaround for GCC 2.95.3
[SVN r32302]
2006-01-13 02:45:33 +00:00
Ralf W. Grosse-Kunstleve
1f51812589 EDG 238 compatibility (and potentially other compilers)
[SVN r32294]
2006-01-12 15:31:46 +00:00
Douglas Gregor
78f6b385d5 Small buffer optimization for Boost.Function
[SVN r32282]
2006-01-10 23:52:35 +00:00
Douglas Gregor
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
Douglas Gregor
c5e64fab99 BOOST_CRITICAL_ERROR is no longer usable
[SVN r32185]
2005-12-30 02:27:13 +00:00
Hartmut Kaiser
6023ff5608 Workaround for a problem in Wave.
[SVN r32094]
2005-12-18 21:06:32 +00:00
Douglas Gregor
944c2ea72a Merged from Version_1_33_1
[SVN r31949]
2005-12-08 03:23:02 +00:00
John Maddock
35e2ff56a0 Large patch from Ulrich Eckhardt to fix support for EVC++ 4.
[SVN r30670]
2005-08-25 16:27:28 +00:00
Douglas Gregor
b5b12295c2 Try to work around Borland parsing bug
[SVN r30645]
2005-08-24 14:12:03 +00:00
Douglas Gregor
eea010ef80 Fully-qualify detail namespace accesses to work around compiler bugs
[SVN r30627]
2005-08-22 12:55:34 +00:00
Douglas Gregor
b8ef34c043 Merged from 1.33.0 release
[SVN r30540]
2005-08-12 13:02:37 +00:00
Douglas Gregor
8b816138bc Fix tests for compilers that actually have a real is_stateless
[SVN r28784]
2005-05-10 13:30:35 +00:00
Douglas Gregor
24ce3091d0 Peter Dimov's ADL workarounds
[SVN r27808]
2005-03-24 19:13:33 +00:00
Douglas Gregor
354b8b802e Test use of function_equal
[SVN r27733]
2005-03-18 05:01:49 +00:00
Douglas Gregor
db089615a2 Be more precise about EqualityComparable and function_equal
[SVN r27732]
2005-03-18 04:54:32 +00:00
Peter Dimov
3b269d5de7 contains2_test added
[SVN r27722]
2005-03-17 12:48:40 +00:00
Peter Dimov
795964f63d bind_function_test added.
[SVN r27721]
2005-03-17 12:09:35 +00:00
Peter Dimov
0f15ba9450 bind_t now implements function_equal instead of operator==
[SVN r27630]
2005-03-13 17:25:42 +00:00
Stefan Slapeta
bb669b4fb5 Replaced BOOST_TEST
[SVN r27049]
2005-02-03 11:09:28 +00:00
Douglas Gregor
dc61dc6dc8 Fix for Borland, from Tobias Schwinger
[SVN r26886]
2005-01-28 07:04:32 +00:00
Douglas Gregor
d0fe22e9bf Use bold element now
[SVN r26820]
2005-01-23 16:23:09 +00:00
Douglas Gregor
e2a7fea741 Workarounds for CW 9.2, from Reece Dunn
[SVN r26583]
2004-12-26 22:05:19 +00:00
Douglas Gregor
e14e57a678 Fix BOOST_NO_VOID_RETURNS workaround
[SVN r26518]
2004-12-15 21:40:30 +00:00
Rene Rivera
c9d7858ff0 Remove tabs in file.
[SVN r24040]
2004-07-25 15:53:20 +00:00
Douglas Gregor
fdbbc2b3ff Doug Gregor->Douglas Gregor
[SVN r24018]
2004-07-25 02:59:30 +00:00
Douglas Gregor
520ee97c82 Doug Gregor -> Douglas Gregor
[SVN r24016]
2004-07-25 02:29:29 +00:00
Douglas Gregor
e4f632e5ca function_template.hpp: Move definition of operator() out-of-line for
any compiler that isn't VC++ 6.0 (Vladimir Prus)


[SVN r23436]
2004-07-11 03:09:35 +00:00
Douglas Gregor
5b4dc38727 boost/function/function_base.hpp:
- Work around a GCC <= 3.3 bug where the return type of a function template
    that cannot possibly match is instantiated when it should not be, causing
    errors in the use of operator==. This results in slightly reduced
    functionality.

libs/function/test/contains_test.cpp:
  - Don't test that which GCC cannot now handle


[SVN r23170]
2004-06-23 16:00:01 +00:00
Douglas Gregor
22fd23b00f function_template.hpp, function_base.hpp:
- Comparison operators are now written in terms of function_base so that
    implicit conversions to function<...> or functionN<...> don't allow
    arbitrary comparisons.


[SVN r23126]
2004-06-20 05:32:28 +00:00
Vladimir Prus
d929aaf814 Update V2 Jamfile
[SVN r23078]
2004-06-10 12:37:31 +00:00
Douglas Gregor
ae11f21513 Try to make IBM VisualAge C++ 6 happy
[SVN r22795]
2004-05-12 00:39:00 +00:00
Douglas Gregor
dc14c35c38 function_base.hpp:
- Fix silly typo where it returned "false" instead of the NULL
    pointer.


[SVN r22760]
2004-05-07 11:43:41 +00:00
Douglas Gregor
1b27dc8f86 Fix some shadow warnings
[SVN r22670]
2004-04-20 00:32:48 +00:00
Douglas Gregor
2c0e633307 Added contains() and function_equal()
[SVN r22483]
2004-03-12 03:38:20 +00:00
Douglas Gregor
e80a00545c Added FAQ entry from Matt Hurd about boost::function overhead.
[SVN r22309]
2004-02-18 06:37:13 +00:00
Douglas Gregor
1a142a2f94 Fix on GCC 2.9x from Ralf
[SVN r22249]
2004-02-12 22:48:22 +00:00
Douglas Gregor
f0c5e5e95b Work around a GCC 2.95.3 bug triggered by the workaround to a VC++ 7.1 bug...
[SVN r22242]
2004-02-11 18:16:55 +00:00
Douglas Gregor
2fb242eae1 Work around CLR bug in .NET 2003
[SVN r22234]
2004-02-11 04:26:53 +00:00
Douglas Gregor
03c7fdcf37 Fix the documentation of empty() (Angus Leeming)
[SVN r22193]
2004-02-08 00:11:22 +00:00
Douglas Gregor
b7608dff24 type_info::operator== fixes (Peter Dimov)
[SVN r22083]
2004-01-30 17:15:03 +00:00
Douglas Gregor
5f0426a80d Stupid deprecated XInclude namespace
[SVN r22013]
2004-01-28 01:31:00 +00:00
Douglas Gregor
fdb37c35ff Some aesthetic tweaks
[SVN r21905]
2004-01-25 01:17:35 +00:00
Douglas Gregor
b7650282df tutorial.xml: Add short discussion of the comparison of Boost.Function
objects to function objects.


[SVN r21904]
2004-01-25 01:15:57 +00:00
Douglas Gregor
c5d8d03b76 libs/function/doc/reference.xml:
- Document target() member function
  - Documented new comparison operators

libs/function/doc/tests.xml: Include contains_test.cpp
libs/function/doc/function.xml: Use the new XInclude name


[SVN r21903]
2004-01-25 00:38:26 +00:00
Douglas Gregor
746676d274 Fix semantics for comparison against reference_wrappers
[SVN r21901]
2004-01-24 23:31:40 +00:00
Douglas Gregor
c31ad8700e Cast pointers, not lvalues
[SVN r21897]
2004-01-24 18:29:18 +00:00
Douglas Gregor
cb1bcd5410 "contains" -> "target"
[SVN r21845]
2004-01-20 18:07:13 +00:00
Douglas Gregor
7d30d98efd boost/function/function_template.hpp, boost/function/function_base.hpp:
- Added "contains" member function to extract a pointer to the target
    function object if you know its type
  - Added operator== that can compare a Boost.Function object against a
    function object

libs/function/test/Jamfile, libs/function/test/contains_test.cpp:
  - Test contains() and equality comparison operators


[SVN r21844]
2004-01-20 18:02:02 +00:00
42 changed files with 2118 additions and 837 deletions

View File

@@ -132,6 +132,25 @@ function objects with parameters that don't exactly match.</para>
application a reference-counting allocator could be used.</para> application a reference-counting allocator could be used.</para>
</answer> </answer>
</qandaentry> </qandaentry>
<qandaentry>
<question><para>How much overhead does a call through <code><classname>boost::function</classname></code> incur?</para></question>
<answer>
<para>The cost of <code>boost::function</code> can be reasonably
consistently measured at around 20ns +/- 10 ns on a modern >2GHz
platform versus directly inlining the code.</para>
<para>However, the performance of your application may benefit
from or be disadvantaged by <code>boost::function</code>
depending on how your C++ optimiser optimises. Similar to a
standard function pointer, differences of order of 10% have been
noted to the benefit or disadvantage of using
<code>boost::function</code> to call a function that contains a
tight loop depending on your compilation circumstances.</para>
<para>[Answer provided by Matt Hurd. See <ulink url="http://article.gmane.org/gmane.comp.lib.boost.devel/33278"/>]</para>
</answer>
</qandaentry>
</qandaset> </qandaset>
</section> </section>

View File

@@ -8,13 +8,14 @@
<author> <author>
<firstname>Douglas</firstname> <firstname>Douglas</firstname>
<surname>Gregor</surname> <surname>Gregor</surname>
<email>gregod@cs.rpi.edu</email> <email>dgregor -at- cs.indiana.edu</email>
</author> </author>
<copyright> <copyright>
<year>2001</year> <year>2001</year>
<year>2002</year> <year>2002</year>
<year>2003</year> <year>2003</year>
<year>2004</year>
<holder>Douglas Gregor</holder> <holder>Douglas Gregor</holder>
</copyright> </copyright>

View File

@@ -5,7 +5,14 @@
<title>History &amp; Compatibility Notes</title> <title>History &amp; Compatibility Notes</title>
<itemizedlist spacing="compact"> <itemizedlist spacing="compact">
<listitem><para><emphasis role="bold">Version 1.30.0</emphasis>: </para>
<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"> <itemizedlist spacing="compact">
<listitem><para>All features deprecated in version 1.29.0 have <listitem><para>All features deprecated in version 1.29.0 have
been removed from Boost.Function.</para></listitem> been removed from Boost.Function.</para></listitem>
@@ -32,7 +39,7 @@
</itemizedlist> </itemizedlist>
</listitem> </listitem>
<listitem><para><emphasis role="bold">Version 1.29.0</emphasis>: <listitem><para><bold>Version 1.29.0</bold>:
Boost.Function has been partially redesigned to minimize the Boost.Function has been partially redesigned to minimize the
interface and make it cleaner. Several seldom- or never-used interface and make it cleaner. Several seldom- or never-used
features of the older Boost.Function have been deprecated and will features of the older Boost.Function have been deprecated and will

View File

@@ -79,7 +79,49 @@
<method-group name="capacity"> <method-group name="capacity">
<method name="empty" cv="const"> <method name="empty" cv="const">
<type>bool</type> <type>bool</type>
<returns><simpara><code>true</code> if <code>this</code> has a target, and <code>false</code> otherwise.</simpara></returns> <returns><simpara><code>false</code> if <code>this</code> has a target, and <code>true</code> otherwise.</simpara></returns>
<throws><simpara>Will not throw.</simpara></throws>
</method>
</method-group>
<method-group name="target access">
<overloaded-method name="target">
<signature>
<template>
<template-type-parameter name="Functor"/>
</template>
<type>Functor*</type>
</signature>
<signature cv="const">
<template>
<template-type-parameter name="Functor"/>
</template>
<type>const Functor*</type>
</signature>
<returns><simpara>If <code>this</code> stores a target of type
<code>Functor</code>, returns the address of the
target. Otherwise, returns the NULL
pointer.</simpara></returns>
<throws><simpara>Will not throw.</simpara></throws>
</overloaded-method>
<method name="contains" cv="const">
<template>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="f">
<paramtype>const Functor&amp;</paramtype>
</parameter>
<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> <throws><simpara>Will not throw.</simpara></throws>
</method> </method>
</method-group> </method-group>
@@ -146,7 +188,7 @@
</struct> </struct>
<constructor> <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> <throws><simpara>Will not throw.</simpara></throws>
</constructor> </constructor>
@@ -165,11 +207,10 @@
<parameter name="f"><paramtype>F</paramtype></parameter> <parameter name="f"><paramtype>F</paramtype></parameter>
<requires><simpara>F is a function object Callable from <code>this</code>.</simpara></requires> <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> <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>
<destructor> <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> </destructor>
@@ -177,8 +218,7 @@
<parameter name="f"> <parameter name="f">
<paramtype>const <classname>functionN</classname>&amp;</paramtype> <paramtype>const <classname>functionN</classname>&amp;</paramtype>
</parameter> </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> <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>
<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>
</copy-assignment> </copy-assignment>
<method-group name="modifiers"> <method-group name="modifiers">
@@ -186,20 +226,18 @@
<type>void</type> <type>void</type>
<parameter name="f"><paramtype>const <classname>functionN</classname>&amp;</paramtype></parameter> <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> <effects><simpara>Interchanges the targets of <code>*this</code> and <code>f</code>.</simpara></effects>
<throws><simpara>Will not throw.</simpara></throws>
</method> </method>
<method name="clear"> <method name="clear">
<type>void</type> <type>void</type>
<postconditions><simpara>this-&gt;<methodname>empty</methodname>()</simpara></postconditions> <postconditions><simpara>this-&gt;<methodname>empty</methodname>()</simpara></postconditions>
<throws><simpara>Will not throw.</simpara></throws>
</method> </method>
</method-group> </method-group>
<method-group name="capacity"> <method-group name="capacity">
<method name="empty" cv="const"> <method name="empty" cv="const">
<type>bool</type> <type>bool</type>
<returns><simpara><code>true</code> if <code>this</code> has a target, and <code>false</code> otherwise.</simpara></returns> <returns><simpara><code>false</code> if <code>this</code> has a target, and <code>true</code> otherwise.</simpara></returns>
<throws><simpara>Will not throw.</simpara></throws> <throws><simpara>Will not throw.</simpara></throws>
</method> </method>
@@ -216,6 +254,49 @@
</method> </method>
</method-group> </method-group>
<method-group name="target access">
<overloaded-method name="target">
<signature>
<template>
<template-type-parameter name="Functor"/>
</template>
<type>Functor*</type>
</signature>
<signature cv="const">
<template>
<template-type-parameter name="Functor"/>
</template>
<type>const Functor*</type>
</signature>
<returns><simpara>If <code>this</code> stores a target of type
<code>Functor</code>, returns the address of the
target. Otherwise, returns the NULL
pointer.</simpara></returns>
<throws><simpara>Will not throw.</simpara></throws>
</overloaded-method>
<method name="contains" cv="const">
<template>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="f">
<paramtype>const Functor&amp;</paramtype>
</parameter>
<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"> <method-group name="invocation">
<method name="operator()" cv="const"> <method name="operator()" cv="const">
<type>result_type</type> <type>result_type</type>
@@ -225,7 +306,7 @@
<parameter name="aN"><paramtype>argN_type</paramtype></parameter> <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> <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> <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>
</method-group> </method-group>
@@ -242,12 +323,64 @@
<parameter name="f1"><paramtype><classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter> <parameter name="f1"><paramtype><classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype><classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter> <parameter name="f2"><paramtype><classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
<effects><simpara><code>f1.<methodname>swap</methodname>(f2)</code></simpara></effects> <effects><simpara><code>f1.<methodname>swap</methodname>(f2)</code></simpara></effects>
<throws><simpara>Will not throw.</simpara></throws>
</function> </function>
</free-function-group> </free-function-group>
<free-function-group name="undefined operators"> <free-function-group name="comparison operators">
<function name="operator=="> <overloaded-function name="operator==">
<signature>
<template>
<template-type-parameter name="T1"/>
<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="g"><paramtype>Functor</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="T1"/>
<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>
</signature>
<signature>
<template>
<template-type-parameter name="T1"/>
<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="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="T1"/>
<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>
</signature>
<signature>
<template> <template>
<template-type-parameter name="T1"/> <template-type-parameter name="T1"/>
<template-type-parameter name="T2"/> <template-type-parameter name="T2"/>
@@ -263,11 +396,92 @@
<type>void</type> <type>void</type>
<parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator1&gt;&amp;</paramtype></parameter> <parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN, Allocator2&gt;&amp;</paramtype></parameter> <parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN, Allocator2&gt;&amp;</paramtype></parameter>
<notes><simpara>This function must be left undefined.</simpara></notes> </signature>
<rationale><simpara>The <code>safe_bool</code> conversion opens a loophole whereby two function instances can be compared via <code>==</code>. This undefined <code>void operator ==</code> closes the loophole and ensures a compile-time or link-time error.</simpara></rationale>
</function>
<function name="operator!="> <returns><simpara>True when <code>f</code> stores an object of
type <code>Functor</code> and one of the following conditions applies:
<itemizedlist>
<listitem><simpara><code>g</code> is of type
<code><classname>reference_wrapper</classname>&lt;Functor&gt;</code>
and <code>f.target&lt;Functor&gt;() == g.<methodname
alt="reference_wrapper::get_pointer">get_pointer</methodname>()</code>.</simpara></listitem>
<listitem><simpara><code>g</code> is not of type
<code><classname>reference_wrapper</classname>&lt;Functor&gt;</code>
and
<code><functionname>function_equal</functionname>(*(f.target&lt;Functor&gt;()),
g)</code>.</simpara></listitem>
</itemizedlist>
</simpara></returns>
<notes><simpara><code><classname>functionN</classname></code>
objects are not
<conceptname>EqualityComparable</conceptname>.</simpara></notes>
<rationale><simpara>The <code>safe_bool</code> conversion
opens a loophole whereby two <code>functionN</code>
instances can be compared via <code>==</code>, although this
is not feasible to implement. The undefined <code>void
operator==</code> closes the loophole and ensures a
compile-time or link-time error.</simpara></rationale>
</overloaded-function>
<overloaded-function name="operator!=">
<signature>
<template>
<template-type-parameter name="T1"/>
<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="g"><paramtype>Functor</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="T1"/>
<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>
</signature>
<signature>
<template>
<template-type-parameter name="T1"/>
<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="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="T1"/>
<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>
</signature>
<signature>
<template> <template>
<template-type-parameter name="T1"/> <template-type-parameter name="T1"/>
<template-type-parameter name="T2"/> <template-type-parameter name="T2"/>
@@ -283,9 +497,37 @@
<type>void</type> <type>void</type>
<parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator1&gt;&amp;</paramtype></parameter> <parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN, Allocator2&gt;&amp;</paramtype></parameter> <parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN, Allocator2&gt;&amp;</paramtype></parameter>
<notes><simpara>This function must be left undefined.</simpara></notes> </signature>
<rationale><simpara>The <code>safe_bool</code> conversion opens a loophole whereby two function instances can be compared via <code>!=</code>. This undefined <code>void operator !=</code> closes the loophole and ensures a compile-time or link-time error.</simpara></rationale>
</function> <returns><simpara>True when <code>f</code> does not store an
object of type <code>Functor</code> or it stores an object of
type <code>Functor</code> and one of the following conditions
applies:
<itemizedlist>
<listitem><simpara><code>g</code> is of type
<code><classname>reference_wrapper</classname>&lt;Functor&gt;</code>
and <code>f.target&lt;Functor&gt;() != g.<methodname
alt="reference_wrapper::get_pointer">get_pointer</methodname>()</code>.</simpara></listitem>
<listitem><simpara><code>g</code> is not of type
<code><classname>reference_wrapper</classname>&lt;Functor&gt;</code>
and <code>!<functionname>function_equal</functionname>(*(f.target&lt;Functor&gt;()), g)</code>.</simpara></listitem>
</itemizedlist>
</simpara></returns>
<notes><simpara><code><classname>functionN</classname></code>
objects are not
<conceptname>EqualityComparable</conceptname>.</simpara></notes>
<rationale><simpara>The <code>safe_bool</code> conversion
opens a loophole whereby two <code>functionN</code>
instances can be compared via <code>!=</code>, although this
is not feasible to implement. The undefined <code>void
operator!=</code> closes the loophole and ensures a
compile-time or link-time error.</simpara></rationale>
</overloaded-function>
</free-function-group> </free-function-group>
</class> </class>
@@ -355,7 +597,7 @@
</struct> </struct>
<constructor> <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> <throws><simpara>Will not throw.</simpara></throws>
</constructor> </constructor>
@@ -382,28 +624,26 @@
<parameter name="f"><paramtype>F</paramtype></parameter> <parameter name="f"><paramtype>F</paramtype></parameter>
<requires><simpara>F is a function object Callable from <code>this</code>.</simpara></requires> <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> <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>
<destructor> <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> </destructor>
<copy-assignment> <copy-assignment>
<parameter name="f"> <parameter name="f">
<paramtype>const <classname>functionN</classname>&amp;</paramtype> <paramtype>const <classname>function</classname>&amp;</paramtype>
</parameter> </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> <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>
<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>
</copy-assignment> </copy-assignment>
<copy-assignment> <copy-assignment>
<parameter name="f"> <parameter name="f">
<paramtype>const <classname>function</classname>&amp;</paramtype> <paramtype>const <classname>function</classname>&amp;</paramtype>
</parameter> </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> <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.</simpara></throws> <throws><simpara>Will not throw when the target of <code>f</code> is a stateless function object or a reference to the function object. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></throws>
</copy-assignment> </copy-assignment>
<method-group name="modifiers"> <method-group name="modifiers">
@@ -411,7 +651,6 @@
<type>void</type> <type>void</type>
<parameter name="f"><paramtype>const <classname>function</classname>&amp;</paramtype></parameter> <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> <effects><simpara>Interchanges the targets of <code>*this</code> and <code>f</code>.</simpara></effects>
<throws><simpara>Will not throw.</simpara></throws>
</method> </method>
<method name="clear"> <method name="clear">
@@ -424,7 +663,7 @@
<method-group name="capacity"> <method-group name="capacity">
<method name="empty" cv="const"> <method name="empty" cv="const">
<type>bool</type> <type>bool</type>
<returns><simpara><code>true</code> if <code>this</code> has a target, and <code>false</code> otherwise.</simpara></returns> <returns><simpara><code>false</code> if <code>this</code> has a target, and <code>true</code> otherwise.</simpara></returns>
<throws><simpara>Will not throw.</simpara></throws> <throws><simpara>Will not throw.</simpara></throws>
</method> </method>
@@ -441,6 +680,47 @@
</method> </method>
</method-group> </method-group>
<method-group name="target access">
<overloaded-method name="target">
<signature>
<template>
<template-type-parameter name="Functor"/>
</template>
<type>Functor*</type>
</signature>
<signature cv="const">
<template>
<template-type-parameter name="Functor"/>
</template>
<type>const Functor*</type>
</signature>
<returns><simpara>If <code>this</code> stores a target of type
<code>Functor</code>, returns the address of the
target. Otherwise, returns the NULL
pointer.</simpara></returns>
<throws><simpara>Will not throw.</simpara></throws>
</overloaded-method>
<method name="contains" cv="const">
<template>
<template-type-parameter name="Functor"/>
</template>
<type>bool</type>
<parameter name="f">
<paramtype>const Functor&amp;</paramtype>
</parameter>
<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"> <method-group name="invocation">
<method name="operator()" cv="const"> <method name="operator()" cv="const">
<type>result_type</type> <type>result_type</type>
@@ -450,7 +730,7 @@
<parameter name="aN"><paramtype>argN_type</paramtype></parameter> <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> <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> <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>
</method-group> </method-group>
@@ -464,12 +744,52 @@
<parameter name="f1"><paramtype><classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter> <parameter name="f1"><paramtype><classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype><classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter> <parameter name="f2"><paramtype><classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
<effects><simpara><code>f1.<methodname>swap</methodname>(f2)</code></simpara></effects> <effects><simpara><code>f1.<methodname>swap</methodname>(f2)</code></simpara></effects>
<throws><simpara>Will not throw.</simpara></throws>
</function> </function>
</free-function-group> </free-function-group>
<free-function-group name="undefined operators"> <free-function-group name="comparison operators">
<function name="operator=="> <overloaded-function name="operator==">
<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="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>
</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="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>
</signature>
<signature>
<template> <template>
<template-type-parameter name="Signature1"/> <template-type-parameter name="Signature1"/>
<template-type-parameter name="Allocator1"/> <template-type-parameter name="Allocator1"/>
@@ -479,11 +799,78 @@
<type>void</type> <type>void</type>
<parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1, Allocator1&gt;&amp;</paramtype></parameter> <parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2, Allocator2&gt;&amp;</paramtype></parameter> <parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2, Allocator2&gt;&amp;</paramtype></parameter>
<notes><simpara>This function must be left undefined.</simpara></notes> </signature>
<rationale><simpara>The <code>safe_bool</code> conversion opens a loophole whereby two function instances can be compared via <code>==</code>. This undefined <code>void operator ==</code> closes the loophole and ensures a compile-time or link-time error.</simpara></rationale>
</function>
<function name="operator!="> <returns><simpara>True when <code>f</code> stores an object of
type <code>Functor</code> and one of the following conditions applies:
<itemizedlist>
<listitem><simpara><code>g</code> is of type
<code><classname>reference_wrapper</classname>&lt;Functor&gt;</code>
and <code>f.target&lt;Functor&gt;() == g.<methodname
alt="reference_wrapper::get_pointer">get_pointer</methodname>()</code>.</simpara></listitem>
<listitem><simpara><code>g</code> is not of type
<code><classname>reference_wrapper</classname>&lt;Functor&gt;</code>
and <code><functionname>function_equals</functionname>(*(f.target&lt;Functor&gt;()), g)</code>.</simpara></listitem>
</itemizedlist>
</simpara></returns>
<notes><simpara><code><classname>function</classname></code>
objects are not
<conceptname>EqualityComparable</conceptname>.</simpara></notes>
<rationale><simpara>The <code>safe_bool</code> conversion
opens a loophole whereby two <code>function</code>
instances can be compared via <code>==</code>, although this
is not feasible to implement. The undefined <code>void
operator==</code> closes the loophole and ensures a
compile-time or link-time error.</simpara></rationale>
</overloaded-function>
<overloaded-function name="operator!=">
<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="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>
</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="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>
</signature>
<signature>
<template> <template>
<template-type-parameter name="Signature1"/> <template-type-parameter name="Signature1"/>
<template-type-parameter name="Allocator1"/> <template-type-parameter name="Allocator1"/>
@@ -493,11 +880,60 @@
<type>void</type> <type>void</type>
<parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1, Allocator1&gt;&amp;</paramtype></parameter> <parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2, Allocator2&gt;&amp;</paramtype></parameter> <parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2, Allocator2&gt;&amp;</paramtype></parameter>
<notes><simpara>This function must be left undefined.</simpara></notes> </signature>
<rationale><simpara>The <code>safe_bool</code> conversion opens a loophole whereby two function instances can be compared via <code>!=</code>. This undefined <code>void operator !=</code> closes the loophole and ensures a compile-time or link-time error.</simpara></rationale>
</function> <returns><simpara>True when <code>f</code> does not store an
object of type <code>Functor</code> or it stores an object of
type <code>Functor</code> and one of the following conditions
applies:
<itemizedlist>
<listitem><simpara><code>g</code> is of type
<code><classname>reference_wrapper</classname>&lt;Functor&gt;</code>
and <code>f.target&lt;Functor&gt;() != g.<methodname
alt="reference_wrapper::get_pointer">get_pointer</methodname>()</code>.</simpara></listitem>
<listitem><simpara><code>g</code> is not of type
<code><classname>reference_wrapper</classname>&lt;Functor&gt;</code>
and <code>!<functionname>function_equals</functionname>(*(f.target&lt;Functor&gt;()), g)</code>.</simpara></listitem>
</itemizedlist>
</simpara></returns>
<notes><simpara><code><classname>function</classname></code>
objects are not
<conceptname>EqualityComparable</conceptname>.</simpara></notes>
<rationale><simpara>The <code>safe_bool</code> conversion
opens a loophole whereby two <code>function</code>
instances can be compared via <code>!=</code>, although this
is not feasible to implement. The undefined <code>void
operator!=</code> closes the loophole and ensures a
compile-time or link-time error.</simpara></rationale>
</overloaded-function>
</free-function-group> </free-function-group>
</class> </class>
</namespace> </namespace>
</header> </header>
<header name="boost/function_equal.hpp">
<namespace name="boost">
<function name="function_equal">
<template>
<template-type-parameter name="F"/>
<template-type-parameter name="G"/>
</template>
<type>bool</type>
<parameter name="f">
<paramtype>const F&amp;</paramtype>
</parameter>
<parameter name="g">
<paramtype>const G&amp;</paramtype>
</parameter>
<purpose><simpara>Compare two function objects for equality.</simpara></purpose>
<returns><simpara><code>f == g</code>.</simpara></returns>
<throws><simpara>Only if <code>f == g</code> throws.</simpara></throws>
</function>
</namespace>
</header>
</library-reference> </library-reference>

View File

@@ -26,6 +26,12 @@
<if-fails><para>Either Boost.Lambda does not work on the platform, or Boost.Function cannot safely be applied without the use of <functionname>boost::unlambda</functionname>.</para></if-fails> <if-fails><para>Either Boost.Lambda does not work on the platform, or Boost.Function cannot safely be applied without the use of <functionname>boost::unlambda</functionname>.</para></if-fails>
</run-test> </run-test>
<run-test filename="contains_test.cpp">
<purpose><para>Test the operation of the
<code><methodname>target</methodname></code> member function and the
equality operators.</para></purpose>
</run-test>
<compile-fail-test filename="function_test_fail1.cpp"> <compile-fail-test filename="function_test_fail1.cpp">
<purpose><para>Test the (incorrect!) use of comparisons between Boost.Function function objects.</para></purpose> <purpose><para>Test the (incorrect!) use of comparisons between Boost.Function function objects.</para></purpose>
<if-fails><para>Intuitive (but incorrect!) code may compile and will give meaningless results.</para></if-fails> <if-fails><para>Intuitive (but incorrect!) code may compile and will give meaningless results.</para></if-fails>

View File

@@ -248,17 +248,17 @@ f(&amp;x, 5);</programlisting>
<row> <row>
<entry> <entry>
<programlisting name="function.tutorial.std_bind.cxx98"> <classname>boost::function</classname>&lt;int (int)&gt; f; <programlisting name="function.tutorial.std_bind.cxx98"> <classname>boost::function</classname>&lt;int (int)&gt; f;
X x; X x;
f = std::bind1st( f = std::bind1st(
std::mem_fun(&amp;X::foo), &amp;x); std::mem_fun(&amp;X::foo), &amp;x);
f(5); // Call x.foo(5)</programlisting> f(5); // Call x.foo(5)</programlisting>
</entry> </entry>
<entry> <entry>
<programlisting name="function.tutorial.std_bind.portable"> <classname alt="functionN">boost::function1</classname>&lt;int, int&gt; f; <programlisting name="function.tutorial.std_bind.portable"> <classname alt="functionN">boost::function1</classname>&lt;int, int&gt; f;
X x; X x;
f = std::bind1st( f = std::bind1st(
std::mem_fun(&amp;X::foo), &amp;x); std::mem_fun(&amp;X::foo), &amp;x);
f(5); // Call x.foo(5)</programlisting> f(5); // Call x.foo(5)</programlisting>
</entry> </entry>
</row> </row>
</tbody> </tbody>
@@ -274,7 +274,7 @@ f(&amp;x, 5);</programlisting>
</section> </section>
<section> <section>
<title>References to Functions</title> <para> In some cases it is <title>References to Function Objects</title> <para> In some cases it is
expensive (or semantically incorrect) to have Boost.Function clone a expensive (or semantically incorrect) to have Boost.Function clone a
function object. In such cases, it is possible to request that function object. In such cases, it is possible to request that
Boost.Function keep only a reference to the actual function Boost.Function keep only a reference to the actual function
@@ -293,18 +293,18 @@ f(&amp;x, 5);</programlisting>
<tbody> <tbody>
<row> <row>
<entry> <entry>
<programlisting name="function.tutorial.ref.cxx98"> stateful_type a_function_object; <programlisting name="function.tutorial.ref.cxx98">stateful_type a_function_object;
<classname>boost::function</classname>&lt;int (int)&gt; f; <classname>boost::function</classname>&lt;int (int)&gt; f;
f = <functionname>boost::ref</functionname>(a_function_object); f = <functionname>boost::ref</functionname>(a_function_object);
<classname>boost::function</classname>&lt;int (int)&gt; f2(f);</programlisting> <classname>boost::function</classname>&lt;int (int)&gt; f2(f);</programlisting>
</entry> </entry>
<entry> <entry>
<programlisting name="function.tutorial.ref.portable"> stateful_type a_function_object; <programlisting name="function.tutorial.ref.portable">stateful_type a_function_object;
<classname alt="functionN">boost::function1</classname>&lt;int, int&gt; f; <classname alt="functionN">boost::function1</classname>&lt;int, int&gt; f;
f = <functionname>boost::ref</functionname>(a_function_object); f = <functionname>boost::ref</functionname>(a_function_object);
<classname alt="functionN">boost::function1</classname>&lt;int, int&gt; f2(f);</programlisting> <classname alt="functionN">boost::function1</classname>&lt;int, int&gt; f2(f);</programlisting>
</entry> </entry>
</row> </row>
</tbody> </tbody>
@@ -321,5 +321,37 @@ using references to function objects, Boost.Function will not throw
exceptions during assignment or construction. exceptions during assignment or construction.
</para> </para>
</section> </section>
<section>
<title>Comparing Boost.Function function objects</title>
<para>Function object wrappers can be compared via <code>==</code>
or <code>!=</code> against any function object that can be stored
within the wrapper. If the function object wrapper contains a
function object of that type, it will be compared against the given
function object (which must be either be
<conceptname>EqualityComparable</conceptname> or have an overloaded <functionname>boost::function_equal</functionname>). For instance:</para>
<programlisting name="function.tutorial.compare">int compute_with_X(X*, int);
f = &amp;X::foo;
assert(f == &amp;X::foo);
assert(&amp;compute_with_X != f);</programlisting>
<para>When comparing against an instance of
<code><classname>reference_wrapper</classname></code>, the address
of the object in the
<code><classname>reference_wrapper</classname></code> is compared
against the address of the object stored by the function object
wrapper:</para>
<programlisting name="function.tutorial.compare-ref">a_stateful_object so1, so2;
f = <functionname>boost::ref</functionname>(so1);
assert(f == <functionname>boost::ref</functionname>(so1));
assert(f == so1); <emphasis>// Only if a_stateful_object is <conceptname>EqualityComparable</conceptname></emphasis>
assert(f != <functionname>boost::ref</functionname>(so2));</programlisting>
</section>
</section> </section>

View File

@@ -1,6 +1,6 @@
// Boost.Function library examples // Boost.Function library examples
// Copyright Doug Gregor 2001-2003. Use, modification and // Copyright Douglas Gregor 2001-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library examples // Boost.Function library examples
// Copyright Doug Gregor 2001-2003. Use, modification and // Copyright Douglas Gregor 2001-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library examples // Boost.Function library examples
// Copyright Doug Gregor 2001-2003. Use, modification and // Copyright Douglas Gregor 2001-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2001-2003. Use, modification and // Copyright Douglas Gregor 2001-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@@ -10,6 +10,8 @@
// William Kempf, Jesse Jones and Karl Nelson were all very helpful in the // William Kempf, Jesse Jones and Karl Nelson were all very helpful in the
// design of this library. // design of this library.
#include <functional> // unary_function, binary_function
#include <boost/preprocessor/iterate.hpp> #include <boost/preprocessor/iterate.hpp>
#include <boost/detail/workaround.hpp> #include <boost/detail/workaround.hpp>
@@ -22,7 +24,7 @@
#include <boost/function/detail/prologue.hpp> #include <boost/function/detail/prologue.hpp>
// Visual Age C++ doesn't handle the file iteration well // 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 # if BOOST_FUNCTION_MAX_ARGS >= 0
# include <boost/function/function0.hpp> # include <boost/function/function0.hpp>
# endif # endif

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2003. Use, modification and // Copyright Douglas Gregor 2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
# #
# Boost.Function library # Boost.Function library
# #
# Copyright (C) 2001-2003 Doug Gregor (gregod@cs.rpi.edu) # Copyright (C) 2001-2003 Douglas Gregor (gregod@cs.rpi.edu)
# #
# Permission to copy, use, sell and distribute this software is granted # Permission to copy, use, sell and distribute this software is granted
# provided this copyright notice appears in all copies. # provided this copyright notice appears in all copies.

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2003. Use, modification and // Copyright Douglas Gregor 2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2002-2003. Use, modification and // Copyright Douglas Gregor 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@@ -11,6 +11,7 @@
#define BOOST_FUNCTION_PROLOGUE_HPP #define BOOST_FUNCTION_PROLOGUE_HPP
# include <cassert> # include <cassert>
# include <algorithm> # include <algorithm>
# include <functional> // unary_function, binary_function
# include <boost/throw_exception.hpp> # include <boost/throw_exception.hpp>
# include <boost/config.hpp> # include <boost/config.hpp>
# include <boost/function/function_base.hpp> # include <boost/function/function_base.hpp>

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2002-2003. Use, modification and // Copyright Douglas Gregor 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2002-2003. Use, modification and // Copyright Douglas Gregor 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2002-2003. Use, modification and // Copyright Douglas Gregor 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2002-2003. Use, modification and // Copyright Douglas Gregor 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2002-2003. Use, modification and // Copyright Douglas Gregor 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2002-2003. Use, modification and // Copyright Douglas Gregor 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2002-2003. Use, modification and // Copyright Douglas Gregor 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2002-2003. Use, modification and // Copyright Douglas Gregor 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2002-2003. Use, modification and // Copyright Douglas Gregor 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2002-2003. Use, modification and // Copyright Douglas Gregor 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2002-2003. Use, modification and // Copyright Douglas Gregor 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2001-2003. Use, modification and // Copyright Douglas Gregor 2001-2006. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@@ -14,17 +14,40 @@
#include <string> #include <string>
#include <memory> #include <memory>
#include <new> #include <new>
#include <typeinfo>
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/type_traits/arithmetic_traits.hpp> #include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/composite_traits.hpp> #include <boost/type_traits/composite_traits.hpp>
#include <boost/type_traits/is_stateless.hpp>
#include <boost/ref.hpp> #include <boost/ref.hpp>
#include <boost/pending/ct_if.hpp> #include <boost/mpl/if.hpp>
#include <boost/detail/workaround.hpp> #include <boost/detail/workaround.hpp>
#include <boost/type_traits/alignment_of.hpp>
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
# include "boost/utility/enable_if.hpp" # include "boost/utility/enable_if.hpp"
#else
# include "boost/mpl/bool.hpp"
#endif
#include <boost/function_equal.hpp>
// 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) \
|| defined(_AIX) \
|| ( defined(__sgi) && defined(__host_mips))
# include <cstring>
# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \
(std::strcmp((X).name(),(Y).name()) == 0)
# else
# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
#endif #endif
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG) #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
@@ -44,10 +67,24 @@ namespace boost { namespace python { namespace objects {
#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ #if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|| defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \ || defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
|| !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540) || !(defined(BOOST_STRICT_CONFIG) || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
# define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX # define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
#endif #endif
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x600)
# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \
(::boost::is_integral<Functor>::value)>::value), \
Type>::type
#else
// BCC doesn't recognize this depends on a template argument and complains
// about the use of 'typename'
# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
::boost::enable_if_c<(::boost::type_traits::ice_not< \
(::boost::is_integral<Functor>::value)>::value), \
Type>::type
#endif
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
namespace boost { namespace boost {
@@ -76,42 +113,36 @@ inline void swap(function<Signature, Allocator>& f1,
namespace boost { namespace boost {
namespace detail { namespace detail {
namespace function { namespace function {
class X;
/** /**
* A union of a function pointer and a void pointer. This is necessary * A buffer used to store small function objects in
* because 5.2.10/6 allows reinterpret_cast<> to safely cast between * boost::function. It is a union containing function pointers,
* function pointer types and 5.2.9/10 allows static_cast<> to safely * object pointers, and a structure that resembles a bound
* cast between a void pointer and an object pointer. But it is not legal * member function pointer.
* to cast between a function pointer and a void* (in either direction), */
* so function requires a union of the two. */ union function_buffer
union any_pointer
{ {
// For pointers to function objects
void* obj_ptr; void* obj_ptr;
// For pointers to std::type_info objects
// (get_functor_type_tag, check_functor_type_tag).
const void* const_obj_ptr; 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 * The unusable class is a placeholder for unused function arguments
* It is also completely unusable except that it constructable from * It is also completely unusable except that it constructable from
@@ -139,7 +170,9 @@ namespace boost {
// The operation type to perform on the given functor/function pointer // The operation type to perform on the given functor/function pointer
enum functor_manager_operation_type { enum functor_manager_operation_type {
clone_functor_tag, clone_functor_tag,
destroy_functor_tag destroy_functor_tag,
check_functor_type_tag,
get_functor_type_tag
}; };
// Tags used to decide between different types of functions // Tags used to decide between different types of functions
@@ -147,39 +180,78 @@ namespace boost {
struct function_obj_tag {}; struct function_obj_tag {};
struct member_ptr_tag {}; struct member_ptr_tag {};
struct function_obj_ref_tag {}; struct function_obj_ref_tag {};
struct stateless_function_obj_tag {};
template<typename F> template<typename F>
class get_function_tag class get_function_tag
{ {
typedef typename ct_if<(is_pointer<F>::value), typedef typename mpl::if_c<(is_pointer<F>::value),
function_ptr_tag, function_ptr_tag,
function_obj_tag>::type ptr_or_obj_tag; function_obj_tag>::type ptr_or_obj_tag;
typedef typename ct_if<(is_member_pointer<F>::value), typedef typename mpl::if_c<(is_member_pointer<F>::value),
member_ptr_tag, member_ptr_tag,
ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag; ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
typedef typename ct_if<(is_reference_wrapper<F>::value), typedef typename mpl::if_c<(is_reference_wrapper<F>::value),
function_obj_ref_tag, function_obj_ref_tag,
ptr_or_obj_or_mem_tag>::type or_ref_tag; ptr_or_obj_or_mem_tag>::type or_ref_tag;
public: public:
typedef typename ct_if<(is_stateless<F>::value), typedef or_ref_tag type;
stateless_function_obj_tag,
or_ref_tag>::type type;
}; };
// The trivial manager does nothing but return the same pointer (if we // The trivial manager does nothing but return the same pointer (if we
// are cloning) or return the null pointer (if we are deleting). // are cloning) or return the null pointer (if we are deleting).
inline any_pointer trivial_manager(any_pointer f, template<typename F>
struct reference_manager
{
static inline void
get(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
if (op == clone_functor_tag) switch (op) {
return f; case clone_functor_tag:
out_buffer.obj_ptr = in_buffer.obj_ptr;
return;
case destroy_functor_tag:
out_buffer.obj_ptr = 0;
return;
case check_functor_type_tag:
{
// DPG TBD: Since we're only storing a pointer, it's
// possible that the user could ask for a base class or
// derived class. Is that okay?
const BOOST_FUNCTION_STD_NS::type_info& check_type =
*static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F)))
out_buffer.obj_ptr = in_buffer.obj_ptr;
else else
return make_any_pointer(reinterpret_cast<void*>(0)); out_buffer.obj_ptr = 0;
} }
return;
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))));
};
/** /**
* The functor_manager class contains a static function "manage" which * The functor_manager class contains a static function "manage" which
@@ -192,23 +264,50 @@ namespace boost {
typedef Functor functor_type; typedef Functor functor_type;
// For function pointers, the manager is trivial // For function pointers, the manager is trivial
static inline any_pointer static inline void
manager(any_pointer function_ptr, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, functor_manager_operation_type op, function_ptr_tag)
function_ptr_tag)
{ {
if (op == clone_functor_tag) if (op == clone_functor_tag)
return function_ptr; 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 else
return make_any_pointer(static_cast<void (*)()>(0)); out_buffer.obj_ptr = 0;
}
} }
// For function object pointers, we clone the pointer to each // Function objects that fit in the small-object buffer.
// function has its own version. static inline void
static inline any_pointer manager(const function_buffer& in_buffer, function_buffer& out_buffer,
manager(any_pointer function_obj_ptr, functor_manager_operation_type op, mpl::true_)
functor_manager_operation_type op, {
function_obj_tag) 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;
}
}
// 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 #ifndef BOOST_NO_STD_ALLOCATOR
typedef typename Allocator::template rebind<functor_type>::other typedef typename Allocator::template rebind<functor_type>::other
@@ -223,8 +322,10 @@ namespace boost {
# endif // BOOST_NO_STD_ALLOCATOR # endif // BOOST_NO_STD_ALLOCATOR
if (op == clone_functor_tag) { if (op == clone_functor_tag) {
functor_type* f = // GCC 2.95.3 gets the CV qualifiers wrong here, so we
static_cast<functor_type*>(function_obj_ptr.obj_ptr); // can't do the static_cast that we should do.
const functor_type* f =
(const functor_type*)(in_buffer.obj_ptr);
// Clone the functor // Clone the functor
# ifndef BOOST_NO_STD_ALLOCATOR # ifndef BOOST_NO_STD_ALLOCATOR
@@ -236,12 +337,11 @@ namespace boost {
# else # else
functor_type* new_f = new functor_type(*f); functor_type* new_f = new functor_type(*f);
# endif // BOOST_NO_STD_ALLOCATOR # endif // BOOST_NO_STD_ALLOCATOR
return make_any_pointer(static_cast<void*>(new_f)); out_buffer.obj_ptr = new_f;
} } else if (op == destroy_functor_tag) {
else {
/* Cast from the void pointer to the functor pointer type */ /* Cast from the void pointer to the functor pointer type */
functor_type* f = functor_type* f =
reinterpret_cast<functor_type*>(function_obj_ptr.obj_ptr); static_cast<functor_type*>(out_buffer.obj_ptr);
# ifndef BOOST_NO_STD_ALLOCATOR # ifndef BOOST_NO_STD_ALLOCATOR
/* Cast from the functor pointer type to the allocator's pointer /* Cast from the functor pointer type to the allocator's pointer
@@ -254,23 +354,121 @@ namespace boost {
# else # else
delete f; delete f;
# endif // BOOST_NO_STD_ALLOCATOR # endif // BOOST_NO_STD_ALLOCATOR
out_buffer.obj_ptr = 0;
} else /* op == check_functor_type_tag */ {
const BOOST_FUNCTION_STD_NS::type_info& check_type =
*static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = in_buffer.obj_ptr;
else
out_buffer.obj_ptr = 0;
}
}
return make_any_pointer(static_cast<void*>(0)); // For function objects, we determine whether the function
} // object can use the small-object optimization buffer or
// whether we need to allocate it on the heap.
static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_obj_tag)
{
manager(in_buffer, out_buffer, op,
mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
} }
public: public:
/* Dispatch to an appropriate manager based on whether we have a /* Dispatch to an appropriate manager based on whether we have a
function pointer or a function object pointer. */ function pointer or a function object pointer. */
static any_pointer static inline void
manage(any_pointer functor_ptr, functor_manager_operation_type op) 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; typedef typename get_function_tag<functor_type>::type tag_type;
return manager(functor_ptr, op, 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;
}
} }
}; };
// A type that is only used for comparisons against zero // A type that is only used for comparisons against zero
struct useless_clear_type {}; struct useless_clear_type {};
#ifdef BOOST_NO_SFINAE
// These routines perform comparisons between a Boost.Function
// object and an arbitrary function object (when the last
// parameter is mpl::bool_<false>) or against zero (when the
// last parameter is mpl::bool_<true>). They are only necessary
// for compilers that don't support SFINAE.
template<typename Function, typename Functor>
bool
compare_equal(const Function& f, const Functor&, int, mpl::bool_<true>)
{ return f.empty(); }
template<typename Function, typename Functor>
bool
compare_not_equal(const Function& f, const Functor&, int,
mpl::bool_<true>)
{ return !f.empty(); }
template<typename Function, typename Functor>
bool
compare_equal(const Function& f, const Functor& g, long,
mpl::bool_<false>)
{
if (const Functor* fp = f.template target<Functor>())
return function_equal(*fp, g);
else return false;
}
template<typename Function, typename Functor>
bool
compare_equal(const Function& f, const reference_wrapper<Functor>& g,
int, mpl::bool_<false>)
{
if (const Functor* fp = f.template target<Functor>())
return fp == g.get_pointer();
else return false;
}
template<typename Function, typename Functor>
bool
compare_not_equal(const Function& f, const Functor& g, long,
mpl::bool_<false>)
{
if (const Functor* fp = f.template target<Functor>())
return !function_equal(*fp, g);
else return true;
}
template<typename Function, typename Functor>
bool
compare_not_equal(const Function& f,
const reference_wrapper<Functor>& g, int,
mpl::bool_<false>)
{
if (const Functor* fp = f.template target<Functor>())
return fp != g.get_pointer();
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 function
} // end namespace detail } // end namespace detail
@@ -283,19 +481,93 @@ namespace boost {
class function_base class function_base
{ {
public: public:
function_base() : manager(0) function_base() : vtable(0) { }
/** 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
{ {
functor.obj_ptr = 0; 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);
} }
// Is this function empty? template<typename Functor>
bool empty() const { return !manager; } Functor* target()
{
if (!vtable) return 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 (!vtable) return 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);
// 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 ))
#else
if (const F* fp = this->template target<F>())
#endif
{
return function_equal(*fp, f);
} else {
return false;
}
}
#if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
// GCC 3.3 and newer cannot copy with the global operator==, due to
// problems with instantiation of function return types before it
// has been verified that the argument types match up.
template<typename Functor>
BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
operator==(Functor g) const
{
if (const Functor* fp = target<Functor>())
return function_equal(*fp, g);
else return false;
}
template<typename Functor>
BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
operator!=(Functor g) const
{
if (const Functor* fp = target<Functor>())
return !function_equal(*fp, g);
else return true;
}
#endif
public: // should be protected, but GCC 2.95.3 will fail to allow access public: // should be protected, but GCC 2.95.3 will fail to allow access
detail::function::any_pointer (*manager)( detail::function::vtable_base* vtable;
detail::function::any_pointer, mutable detail::function::function_buffer functor;
detail::function::functor_manager_operation_type);
detail::function::any_pointer functor;
}; };
/** /**
@@ -308,16 +580,7 @@ public:
bad_function_call() : std::runtime_error("call to empty boost::function") {} bad_function_call() : std::runtime_error("call to empty boost::function") {}
}; };
/* Poison comparison between Boost.Function objects (because it is #ifndef BOOST_NO_SFINAE
* meaningless). The comparisons would otherwise be allowed because of the
* conversion required to allow syntax such as:
* boost::function<int, int> f;
* if (f) { f(5); }
*/
void operator==(const function_base&, const function_base&);
void operator!=(const function_base&, const function_base&);
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
inline bool operator==(const function_base& f, inline bool operator==(const function_base& f,
detail::function::useless_clear_type*) detail::function::useless_clear_type*)
{ {
@@ -343,6 +606,116 @@ inline bool operator!=(detail::function::useless_clear_type*,
} }
#endif #endif
#ifdef BOOST_NO_SFINAE
// Comparisons between boost::function objects and arbitrary function objects
template<typename Functor>
inline bool operator==(const function_base& f, Functor g)
{
typedef mpl::bool_<(is_integral<Functor>::value)> integral;
return detail::function::compare_equal(f, g, 0, integral());
}
template<typename Functor>
inline bool operator==(Functor g, const function_base& f)
{
typedef mpl::bool_<(is_integral<Functor>::value)> integral;
return detail::function::compare_equal(f, g, 0, integral());
}
template<typename Functor>
inline bool operator!=(const function_base& f, Functor g)
{
typedef mpl::bool_<(is_integral<Functor>::value)> integral;
return detail::function::compare_not_equal(f, g, 0, integral());
}
template<typename Functor>
inline bool operator!=(Functor g, const function_base& f)
{
typedef mpl::bool_<(is_integral<Functor>::value)> integral;
return detail::function::compare_not_equal(f, g, 0, integral());
}
#else
# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
// Comparisons between boost::function objects and arbitrary function
// objects. GCC 3.3 and before has an obnoxious bug that prevents this
// from working.
template<typename Functor>
BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
operator==(const function_base& f, Functor g)
{
if (const Functor* fp = f.template target<Functor>())
return function_equal(*fp, g);
else return false;
}
template<typename Functor>
BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
operator==(Functor g, const function_base& f)
{
if (const Functor* fp = f.template target<Functor>())
return function_equal(g, *fp);
else return false;
}
template<typename Functor>
BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
operator!=(const function_base& f, Functor g)
{
if (const Functor* fp = f.template target<Functor>())
return !function_equal(*fp, g);
else return true;
}
template<typename Functor>
BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
operator!=(Functor g, const function_base& f)
{
if (const Functor* fp = f.template target<Functor>())
return !function_equal(g, *fp);
else return true;
}
# endif
template<typename Functor>
BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
operator==(const function_base& f, reference_wrapper<Functor> g)
{
if (const Functor* fp = f.template target<Functor>())
return fp == g.get_pointer();
else return false;
}
template<typename Functor>
BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
operator==(reference_wrapper<Functor> g, const function_base& f)
{
if (const Functor* fp = f.template target<Functor>())
return g.get_pointer() == fp;
else return false;
}
template<typename Functor>
BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
operator!=(const function_base& f, reference_wrapper<Functor> g)
{
if (const Functor* fp = f.template target<Functor>())
return fp != g.get_pointer();
else return true;
}
template<typename Functor>
BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
operator!=(reference_wrapper<Functor> g, const function_base& f)
{
if (const Functor* fp = f.template target<Functor>())
return g.get_pointer() != fp;
else return true;
}
#endif // Compiler supporting SFINAE
namespace detail { namespace detail {
namespace function { namespace function {
inline bool has_empty_target(const function_base* f) inline bool has_empty_target(const function_base* f)
@@ -350,12 +723,22 @@ namespace detail {
return f->empty(); return f->empty();
} }
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
inline bool has_empty_target(const void*)
{
return false;
}
#else
inline bool has_empty_target(...) inline bool has_empty_target(...)
{ {
return false; return false;
} }
#endif
} // end namespace function } // end namespace function
} // end namespace detail } // end namespace detail
} // end namespace boost } // end namespace boost
#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
#undef BOOST_FUNCTION_COMPARE_TYPE_ID
#endif // BOOST_FUNCTION_BASE_HEADER #endif // BOOST_FUNCTION_BASE_HEADER

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2001-2003. Use, modification and // Copyright Douglas Gregor 2001-2006. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@@ -22,7 +22,7 @@
#define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a) #define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
#define BOOST_FUNCTION_ARG_TYPE(J,I,D) \ #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(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) #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
@@ -50,16 +50,25 @@
BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \ #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER \ #define BOOST_FUNCTION_FUNCTION_REF_INVOKER \
BOOST_JOIN(stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER \ #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
BOOST_JOIN(stateless_void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_INVOKER \ #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \ #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER \ #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
BOOST_JOIN(get_stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) 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_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
#endif
namespace boost { namespace boost {
namespace detail { namespace detail {
@@ -71,7 +80,7 @@ namespace boost {
> >
struct BOOST_FUNCTION_FUNCTION_INVOKER 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) BOOST_FUNCTION_PARMS)
{ {
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr); FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
@@ -86,13 +95,13 @@ namespace boost {
> >
struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
{ {
static unusable invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA static BOOST_FUNCTION_VOID_RETURN_TYPE
invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr); FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
f(BOOST_FUNCTION_ARGS); BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
return unusable();
} }
}; };
@@ -103,11 +112,15 @@ namespace boost {
> >
struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER 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) 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); return (*f)(BOOST_FUNCTION_ARGS);
} }
}; };
@@ -119,14 +132,17 @@ namespace boost {
> >
struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
{ {
static unusable invoke(any_pointer function_obj_ptr static BOOST_FUNCTION_VOID_RETURN_TYPE
BOOST_FUNCTION_COMMA invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr); FunctionObj* f;
(*f)(BOOST_FUNCTION_ARGS); if (function_allows_small_object_optimization<FunctionObj>::value)
return unusable(); 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));
} }
}; };
@@ -135,12 +151,15 @@ namespace boost {
typename R BOOST_FUNCTION_COMMA typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS 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(); FunctionObj* f =
return f(BOOST_FUNCTION_ARGS); reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
return (*f)(BOOST_FUNCTION_ARGS);
} }
}; };
@@ -149,15 +168,16 @@ namespace boost {
typename R BOOST_FUNCTION_COMMA typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS BOOST_FUNCTION_TEMPLATE_PARMS
> >
struct BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
{ {
static unusable invoke(any_pointer BOOST_FUNCTION_COMMA static BOOST_FUNCTION_VOID_RETURN_TYPE
invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionObj f = FunctionObj(); FunctionObj* f =
f(BOOST_FUNCTION_ARGS); reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
return unusable(); BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
} }
}; };
@@ -168,7 +188,7 @@ namespace boost {
> >
struct BOOST_FUNCTION_GET_FUNCTION_INVOKER 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< BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
FunctionPtr, FunctionPtr,
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
@@ -189,7 +209,7 @@ namespace boost {
> >
struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER 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< BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
FunctionObj, FunctionObj,
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
@@ -208,15 +228,15 @@ namespace boost {
typename R BOOST_FUNCTION_COMMA typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS 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), typedef typename mpl::if_c<(is_void<R>::value),
BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER< BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER<
FunctionObj, FunctionObj,
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS BOOST_FUNCTION_TEMPLATE_ARGS
>, >,
BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER< BOOST_FUNCTION_FUNCTION_REF_INVOKER<
FunctionObj, FunctionObj,
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS BOOST_FUNCTION_TEMPLATE_ARGS
@@ -224,6 +244,199 @@ namespace boost {
>::type type; >::type type;
}; };
/**
* vtable for a specific boost::function instance.
*/
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
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>
bool assign_to(F f, function_buffer& functor)
{
typedef typename get_function_tag<F>::type tag;
return assign_to(f, functor, tag());
}
void clear(function_buffer& functor)
{
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());
}
// 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, 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;
}
}
// 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 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;
}
}
#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, 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);
}
// Assign to a function object allocated on the heap.
template<typename FunctionObj>
void
assign_functor(FunctionObj f, function_buffer& functor, mpl::false_)
{
#ifndef BOOST_NO_STD_ALLOCATOR
typedef typename Allocator::template rebind<FunctionObj>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
allocator.construct(copy, f);
// Get back to the original pointer type
functor.obj_ptr = static_cast<FunctionObj*>(copy);
# else
functor.obj_ptr = new FunctionObj(f);
# endif // BOOST_NO_STD_ALLOCATOR
}
template<typename FunctionObj>
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;
}
}
// 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 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;
}
}
public:
invoker_type invoker;
};
} // end namespace function } // end namespace function
} // end namespace detail } // end namespace detail
@@ -233,12 +446,31 @@ namespace boost {
typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR
> >
class BOOST_FUNCTION_FUNCTION : public function_base 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: public:
typedef typename detail::function::function_return_type<R>::type #ifndef BOOST_NO_VOID_RETURNS
internal_result_type; typedef R result_type;
#else
typedef typename boost::detail::function::function_return_type<R>::type
result_type;
#endif // BOOST_NO_VOID_RETURNS
private: private:
typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, Allocator>
vtable_type;
struct clear_type {}; struct clear_type {};
public: public:
@@ -248,7 +480,7 @@ namespace boost {
template<typename Args> template<typename Args>
struct sig struct sig
{ {
typedef internal_result_type type; typedef result_type type;
}; };
#if BOOST_FUNCTION_NUM_ARGS == 1 #if BOOST_FUNCTION_NUM_ARGS == 1
@@ -261,16 +493,10 @@ namespace boost {
BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS); BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
BOOST_FUNCTION_ARG_TYPES BOOST_FUNCTION_ARG_TYPES
#ifndef BOOST_NO_VOID_RETURNS
typedef R result_type;
#else
typedef internal_result_type result_type;
#endif // BOOST_NO_VOID_RETURNS
typedef Allocator allocator_type; typedef Allocator allocator_type;
typedef BOOST_FUNCTION_FUNCTION self_type; typedef BOOST_FUNCTION_FUNCTION self_type;
BOOST_FUNCTION_FUNCTION() : function_base() BOOST_FUNCTION_FUNCTION() : function_base() { }
, invoker(0) {}
// MSVC chokes if the following two constructors are collapsed into // MSVC chokes if the following two constructors are collapsed into
// one with a default parameter. // one with a default parameter.
@@ -278,50 +504,46 @@ namespace boost {
BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
,typename enable_if_c< ,typename enable_if_c<
(::boost::type_traits::ice_not< (boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value), (is_integral<Functor>::value)>::value),
int>::type = 0 int>::type = 0
#endif // BOOST_NO_SFINAE #endif // BOOST_NO_SFINAE
) : ) :
function_base(), function_base()
invoker(0)
{ {
this->assign_to(f); this->assign_to(f);
} }
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
BOOST_FUNCTION_FUNCTION(clear_type*) : function_base(), invoker(0) {} BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
#else #else
BOOST_FUNCTION_FUNCTION(int zero) : function_base(), invoker(0) BOOST_FUNCTION_FUNCTION(int zero) : function_base()
{ {
BOOST_ASSERT(zero == 0); BOOST_ASSERT(zero == 0);
} }
#endif #endif
BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
function_base(),
invoker(0)
{ {
this->assign_to_own(f); this->assign_to_own(f);
} }
~BOOST_FUNCTION_FUNCTION() { clear(); } ~BOOST_FUNCTION_FUNCTION() { clear(); }
#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 result_type operator()(BOOST_FUNCTION_PARMS) const
{ {
if (this->empty()) if (this->empty())
boost::throw_exception(bad_function_call()); boost::throw_exception(bad_function_call());
internal_result_type result = invoker(this->functor return static_cast<vtable_type*>(vtable)->invoker
BOOST_FUNCTION_COMMA (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
BOOST_FUNCTION_ARGS);
#ifndef BOOST_NO_VOID_RETURNS
return static_cast<result_type>(result);
#else
return result;
#endif // BOOST_NO_VOID_RETURNS
} }
#else
result_type operator()(BOOST_FUNCTION_PARMS) const;
#endif
// The distinction between when to use BOOST_FUNCTION_FUNCTION and // The distinction between when to use BOOST_FUNCTION_FUNCTION and
// when to use self_type is obnoxious. MSVC cannot handle self_type as // when to use self_type is obnoxious. MSVC cannot handle self_type as
@@ -331,7 +553,7 @@ namespace boost {
template<typename Functor> template<typename Functor>
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
typename enable_if_c< typename enable_if_c<
(::boost::type_traits::ice_not< (boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value), (is_integral<Functor>::value)>::value),
BOOST_FUNCTION_FUNCTION&>::type BOOST_FUNCTION_FUNCTION&>::type
#else #else
@@ -339,7 +561,13 @@ namespace boost {
#endif #endif
operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) 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; return *this;
} }
@@ -364,7 +592,13 @@ namespace boost {
if (&f == this) if (&f == this)
return *this; return *this;
self_type(f).swap(*this); this->clear();
try {
this->assign_to_own(f);
} catch (...) {
vtable = 0;
throw;
}
return *this; return *this;
} }
@@ -373,21 +607,18 @@ namespace boost {
if (&other == this) if (&other == this)
return; return;
std::swap(this->manager, other.manager); BOOST_FUNCTION_FUNCTION tmp = *this;
std::swap(this->functor, other.functor); *this = other;
std::swap(invoker, other.invoker); other = tmp;
} }
// Clear out a target, if there is one // Clear out a target, if there is one
void clear() void clear()
{ {
if (this->manager) { if (vtable) {
function_base::functor = static_cast<vtable_type*>(vtable)->clear(this->functor);
this->manager(this->functor, detail::function::destroy_functor_tag); vtable = 0;
} }
this->manager = 0;
invoker = 0;
} }
#if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG) #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
@@ -413,131 +644,19 @@ namespace boost {
void assign_to_own(const BOOST_FUNCTION_FUNCTION& f) void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
{ {
if (!f.empty()) { if (!f.empty()) {
invoker = f.invoker; this->vtable = f.vtable;
this->manager = f.manager; f.vtable->manager(f.functor, this->functor,
this->functor = boost::detail::function::clone_functor_tag);
f.manager(f.functor, detail::function::clone_functor_tag);
} }
} }
template<typename Functor> template<typename Functor>
void assign_to(Functor f) void assign_to(Functor f)
{ {
typedef typename detail::function::get_function_tag<Functor>::type tag; static vtable_type stored_vtable(f);
this->assign_to(f, tag()); 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)
{
clear();
if (f) {
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
invoker = &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);
}
}
#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(addressof(f))) {
typedef
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
invoker = &invoker_type::invoke;
this->manager = &detail::function::functor_manager<
FunctionObj, Allocator>::manage;
#ifndef BOOST_NO_STD_ALLOCATOR
typedef typename Allocator::template rebind<FunctionObj>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
allocator.construct(copy, f);
// Get back to the original pointer type
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
invoker_type;
invoker = &invoker_type::invoke;
this->manager = &detail::function::trivial_manager;
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
invoker_type;
invoker = &invoker_type::invoke;
this->manager = &detail::function::trivial_manager;
this->functor = detail::function::make_any_pointer(this);
}
typedef internal_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 , template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
@@ -556,6 +675,47 @@ namespace boost {
f1.swap(f2); f1.swap(f2);
} }
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
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>
::operator()(BOOST_FUNCTION_PARMS) const
{
if (this->empty())
boost::throw_exception(bad_function_call());
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>
void operator==(const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS ,
Allocator>&,
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>
void operator!=(const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS ,
Allocator>&,
const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS ,
Allocator>&);
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
#if BOOST_FUNCTION_NUM_ARGS == 0 #if BOOST_FUNCTION_NUM_ARGS == 0
@@ -586,7 +746,7 @@ public:
function(Functor f function(Functor f
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
,typename enable_if_c< ,typename enable_if_c<
(::boost::type_traits::ice_not< (boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value), (is_integral<Functor>::value)>::value),
int>::type = 0 int>::type = 0
#endif #endif
@@ -612,7 +772,7 @@ public:
template<typename Functor> template<typename Functor>
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
typename enable_if_c< typename enable_if_c<
(::boost::type_traits::ice_not< (boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value), (is_integral<Functor>::value)>::value),
self_type&>::type self_type&>::type
#else #else
@@ -645,6 +805,7 @@ public:
} // end namespace boost } // end namespace boost
// Cleanup after ourselves... // Cleanup after ourselves...
#undef BOOST_FUNCTION_VTABLE
#undef BOOST_FUNCTION_DEFAULT_ALLOCATOR #undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
#undef BOOST_FUNCTION_COMMA #undef BOOST_FUNCTION_COMMA
#undef BOOST_FUNCTION_FUNCTION #undef BOOST_FUNCTION_FUNCTION
@@ -652,11 +813,11 @@ public:
#undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
#undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_INVOKER #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
#undef BOOST_FUNCTION_TEMPLATE_PARMS #undef BOOST_FUNCTION_TEMPLATE_PARMS
#undef BOOST_FUNCTION_TEMPLATE_ARGS #undef BOOST_FUNCTION_TEMPLATE_ARGS
@@ -665,3 +826,5 @@ public:
#undef BOOST_FUNCTION_ARGS #undef BOOST_FUNCTION_ARGS
#undef BOOST_FUNCTION_ARG_TYPE #undef BOOST_FUNCTION_ARG_TYPE
#undef BOOST_FUNCTION_ARG_TYPES #undef BOOST_FUNCTION_ARG_TYPES
#undef BOOST_FUNCTION_VOID_RETURN_TYPE
#undef BOOST_FUNCTION_RETURN

View File

@@ -2,7 +2,7 @@
# #
# Boost.Function library # Boost.Function library
# #
# Copyright Doug Gregor 2001-2003. Use, modification and # Copyright Douglas Gregor 2001-2003. Use, modification and
# distribution is subject to the Boost Software License, Version # distribution is subject to the Boost Software License, Version
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at # 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt) # http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -0,0 +1,28 @@
// Copyright Douglas Gregor 2004.
// Copyright 2005 Peter Dimov
// Use, modification and distribution is subject to
// the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// For more information, see http://www.boost.org
#ifndef BOOST_FUNCTION_EQUAL_HPP
#define BOOST_FUNCTION_EQUAL_HPP
namespace boost {
template<typename F, typename G>
bool function_equal_impl(const F& f, const G& g, long)
{ return f == g; }
// function_equal_impl needs to be unqualified to pick
// user overloads on two-phase compilers
template<typename F, typename G>
bool function_equal(const F& f, const G& g)
{ return function_equal_impl(f, g, 0); }
} // end namespace boost
#endif // BOOST_FUNCTION_EQUAL_HPP

View File

@@ -4,6 +4,10 @@
</head> </head>
<body> <body>
Automatic redirection failed, please go to 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>© 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> </body>
</html> </html>

View File

@@ -1,65 +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 : : : : ]
;
}

View File

@@ -1,6 +1,6 @@
# Function library # Function library
# Copyright Doug Gregor 2001-2003. Use, modification and # Copyright Douglas Gregor 2001-2003. Use, modification and
# distribution is subject to the Boost Software License, Version # distribution is subject to the Boost Software License, Version
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at # 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt) # http://www.boost.org/LICENSE_1_0.txt)
@@ -53,6 +53,11 @@ import testing ;
[ run libs/function/test/function_ref_cxx98.cpp : : : : ] [ run libs/function/test/function_ref_cxx98.cpp : : : : ]
[ run libs/function/test/function_ref_portable.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

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2001-2003. Use, modification and // Copyright Douglas Gregor 2001-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@@ -41,11 +41,20 @@ struct counting_allocator : public std::allocator<T>
} }
}; };
struct plus_int
{
int operator()(int x, int y) const { return x + y; }
int unused_state_data[32];
};
static int do_minus(int x, int y) { return x-y; } static int do_minus(int x, int y) { return x-y; }
struct DoNothing struct DoNothing
{ {
void operator()() const {} void operator()() const {}
int unused_state_data[32];
}; };
static void do_nothing() {} static void do_nothing() {}
@@ -54,28 +63,32 @@ int
test_main(int, char*[]) test_main(int, char*[])
{ {
function2<int, int, int, counting_allocator<int> > f; function2<int, int, int, counting_allocator<int> > f;
f = plus<int>(); f = plus_int();
f.clear(); f.clear();
BOOST_TEST(alloc_count == 1); BOOST_CHECK(alloc_count == 1);
BOOST_TEST(dealloc_count == 1); BOOST_CHECK(dealloc_count == 1);
alloc_count = 0; alloc_count = 0;
dealloc_count = 0; dealloc_count = 0;
f = &do_minus; f = &do_minus;
f.clear(); f.clear();
BOOST_CHECK(alloc_count == 0);
BOOST_CHECK(dealloc_count == 0);
function0<void, counting_allocator<int> > fv; function0<void, counting_allocator<int> > fv;
alloc_count = 0; alloc_count = 0;
dealloc_count = 0; dealloc_count = 0;
fv = DoNothing(); fv = DoNothing();
fv.clear(); fv.clear();
BOOST_TEST(alloc_count == 1); BOOST_CHECK(alloc_count == 1);
BOOST_TEST(dealloc_count == 1); BOOST_CHECK(dealloc_count == 1);
alloc_count = 0; alloc_count = 0;
dealloc_count = 0; dealloc_count = 0;
fv = &do_nothing; fv = &do_nothing;
fv.clear(); fv.clear();
BOOST_CHECK(alloc_count == 0);
BOOST_CHECK(dealloc_count == 0);
return 0; return 0;
} }

88
test/contains2_test.cpp Normal file
View File

@@ -0,0 +1,88 @@
// Boost.Function library
// Copyright Douglas Gregor 2004.
// Copyright 2005 Peter Dimov
// 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)
#include <boost/function.hpp>
#include <boost/detail/lightweight_test.hpp>
static int forty_two()
{
return 42;
}
struct Seventeen
{
int operator()() const
{
return 17;
}
};
bool operator==(const Seventeen&, const Seventeen&)
{
return true;
}
struct ReturnInt
{
explicit ReturnInt(int value) : value(value)
{
}
int operator()() const
{
return value;
}
int value;
};
bool operator==(const ReturnInt& x, const ReturnInt& y)
{
return x.value == y.value;
}
bool operator!=(const ReturnInt& x, const ReturnInt& y)
{
return x.value != y.value;
}
int main()
{
boost::function0<int> fn;
fn = &forty_two;
BOOST_TEST( fn() == 42 );
BOOST_TEST( fn.contains(&forty_two) );
BOOST_TEST( !fn.contains( Seventeen() ) );
BOOST_TEST( !fn.contains( ReturnInt(0) ) );
BOOST_TEST( !fn.contains( ReturnInt(12) ) );
fn = Seventeen();
BOOST_TEST( fn() == 17 );
BOOST_TEST( !fn.contains( &forty_two ) );
BOOST_TEST( fn.contains( Seventeen() ) );
BOOST_TEST( !fn.contains( ReturnInt(0) ) );
BOOST_TEST( !fn.contains( ReturnInt(12) ) );
fn = ReturnInt(12);
BOOST_TEST( fn() == 12 );
BOOST_TEST( !fn.contains( &forty_two ) );
BOOST_TEST( !fn.contains( Seventeen() ) );
BOOST_TEST( !fn.contains( ReturnInt(0) ) );
BOOST_TEST( fn.contains( ReturnInt(12) ) );
return boost::report_errors();
}

226
test/contains_test.cpp Normal file
View File

@@ -0,0 +1,226 @@
// Boost.Function library
// Copyright Douglas Gregor 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
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/test/minimal.hpp>
#include <boost/function.hpp>
#include <boost/ref.hpp>
static int forty_two() { return 42; }
struct Seventeen
{
int operator()() const { return 17; }
};
struct ReturnInt
{
explicit ReturnInt(int value) : value(value) {}
int operator()() const { return value; }
int value;
};
bool operator==(const ReturnInt& x, const ReturnInt& y)
{ return x.value == y.value; }
bool operator!=(const ReturnInt& x, const ReturnInt& y)
{ return x.value != y.value; }
namespace contain_test {
struct ReturnIntFE
{
explicit ReturnIntFE(int value) : value(value) {}
int operator()() const { return value; }
int value;
};
}
#ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
namespace contain_test {
# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
bool function_equal(const ReturnIntFE& x, const ReturnIntFE& y)
{ return x.value == y.value; }
# else
bool function_equal_impl(const ReturnIntFE& x, const ReturnIntFE& y, int)
{ return x.value == y.value; }
# endif // #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
}
#else // BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
namespace boost {
# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
bool
function_equal(const contain_test::ReturnIntFE& x,
const contain_test::ReturnIntFE& y)
{ return x.value == y.value; }
# else
bool
function_equal_impl(const contain_test::ReturnIntFE& x,
const contain_test::ReturnIntFE& y, int)
{ return x.value == y.value; }
# endif
}
#endif
static void target_test()
{
boost::function0<int> f;
f = &forty_two;
BOOST_CHECK(*f.target<int (*)()>() == &forty_two);
BOOST_CHECK(!f.target<Seventeen>());
f = Seventeen();
BOOST_CHECK(!f.target<int (*)()>());
BOOST_CHECK(f.target<Seventeen>());
Seventeen this_seventeen;
f = boost::ref(this_seventeen);
BOOST_CHECK(!f.target<int (*)()>());
BOOST_CHECK(f.target<Seventeen>());
BOOST_CHECK(f.target<Seventeen>() == &this_seventeen);
}
static void equal_test()
{
boost::function0<int> f;
f = &forty_two;
BOOST_CHECK(f == &forty_two);
BOOST_CHECK(f != ReturnInt(17));
#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_CHECK(&forty_two == f);
BOOST_CHECK(ReturnInt(17) != f);
#endif
BOOST_CHECK(f.contains(&forty_two));
f = ReturnInt(17);
BOOST_CHECK(f != &forty_two);
BOOST_CHECK(f == ReturnInt(17));
BOOST_CHECK(f != ReturnInt(16));
#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_CHECK(&forty_two != f);
BOOST_CHECK(ReturnInt(17) == f);
BOOST_CHECK(ReturnInt(16) != f);
#endif
BOOST_CHECK(f.contains(ReturnInt(17)));
f = contain_test::ReturnIntFE(17);
BOOST_CHECK(f != &forty_two);
BOOST_CHECK(f == contain_test::ReturnIntFE(17));
BOOST_CHECK(f != contain_test::ReturnIntFE(16));
#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_CHECK(&forty_two != f);
BOOST_CHECK(contain_test::ReturnIntFE(17) == f);
BOOST_CHECK(contain_test::ReturnIntFE(16) != f);
#endif
BOOST_CHECK(f.contains(contain_test::ReturnIntFE(17)));
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
boost::function<int(void)> g;
g = &forty_two;
BOOST_CHECK(g == &forty_two);
BOOST_CHECK(g != ReturnInt(17));
# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_CHECK(&forty_two == g);
BOOST_CHECK(ReturnInt(17) != g);
# endif
g = ReturnInt(17);
BOOST_CHECK(g != &forty_two);
BOOST_CHECK(g == ReturnInt(17));
BOOST_CHECK(g != ReturnInt(16));
# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_CHECK(&forty_two != g);
BOOST_CHECK(ReturnInt(17) == g);
BOOST_CHECK(ReturnInt(16) != g);
# endif
#endif
}
static void ref_equal_test()
{
{
ReturnInt ri(17);
boost::function0<int> f = boost::ref(ri);
// References and values are equal
BOOST_CHECK(f == boost::ref(ri));
BOOST_CHECK(f == ri);
BOOST_CHECK(boost::ref(ri) == f);
BOOST_CHECK(!(f != boost::ref(ri)));
BOOST_CHECK(!(f != ri));
BOOST_CHECK(!(boost::ref(ri) != f));
#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_CHECK(ri == f);
BOOST_CHECK(!(ri != f));
#endif
// Values equal, references inequal
ReturnInt ri2(17);
BOOST_CHECK(f == ri2);
BOOST_CHECK(f != boost::ref(ri2));
BOOST_CHECK(boost::ref(ri2) != f);
BOOST_CHECK(!(f != ri2));
BOOST_CHECK(!(f == boost::ref(ri2)));
BOOST_CHECK(!(boost::ref(ri2) == f));
#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_CHECK(ri2 == f);
BOOST_CHECK(!(ri2 != f));
#endif
}
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
{
ReturnInt ri(17);
boost::function<int(void)> f = boost::ref(ri);
// References and values are equal
BOOST_CHECK(f == boost::ref(ri));
BOOST_CHECK(f == ri);
BOOST_CHECK(boost::ref(ri) == f);
BOOST_CHECK(!(f != boost::ref(ri)));
BOOST_CHECK(!(f != ri));
BOOST_CHECK(!(boost::ref(ri) != f));
# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_CHECK(ri == f);
BOOST_CHECK(!(ri != f));
# endif
// Values equal, references inequal
ReturnInt ri2(17);
BOOST_CHECK(f == ri2);
BOOST_CHECK(f != boost::ref(ri2));
BOOST_CHECK(boost::ref(ri2) != f);
BOOST_CHECK(!(f != ri2));
BOOST_CHECK(!(f == boost::ref(ri2)));
BOOST_CHECK(!(boost::ref(ri2) == f));
# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_CHECK(ri2 == f);
BOOST_CHECK(!(ri2 != f));
# endif
}
#endif
}
int test_main(int, char*[])
{
target_test();
equal_test();
ref_equal_test();
return 0;
}

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2002-2003. Use, modification and // Copyright Douglas Gregor 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2001-2003. Use, modification and // Copyright Douglas Gregor 2001-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@@ -56,30 +56,30 @@ test_zero_args()
// Default construction // Default construction
func_void_type v1; func_void_type v1;
BOOST_TEST(v1.empty()); BOOST_CHECK(v1.empty());
// Assignment to an empty function // Assignment to an empty function
v1 = five; v1 = five;
BOOST_TEST(!v1.empty()); BOOST_CHECK(!v1.empty());
// Invocation of a function // Invocation of a function
global_int = 0; global_int = 0;
v1(); v1();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() method // clear() method
v1.clear(); v1.clear();
BOOST_TEST(!v1); BOOST_CHECK(!v1);
// Assignment to an empty function // Assignment to an empty function
v1 = three; v1 = three;
BOOST_TEST(!v1.empty()); BOOST_CHECK(!v1.empty());
// Invocation and self-assignment // Invocation and self-assignment
global_int = 0; global_int = 0;
v1 = v1; v1 = v1;
v1(); v1();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function // Assignment to a non-empty function
v1 = five; v1 = five;
@@ -88,61 +88,61 @@ test_zero_args()
global_int = 0; global_int = 0;
v1 = (v1); v1 = (v1);
v1(); v1();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear // clear
v1 = 0; v1 = 0;
BOOST_TEST(v1.empty()); BOOST_CHECK(v1.empty());
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
v1 = &write_five; v1 = &write_five;
BOOST_TEST(!v1.empty()); BOOST_CHECK(!v1.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v1(); v1();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v1 = &write_three; v1 = &write_three;
BOOST_TEST(!v1.empty()); BOOST_CHECK(!v1.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v1(); v1();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment // Assignment
v1 = five; v1 = five;
BOOST_TEST(!v1.empty()); BOOST_CHECK(!v1.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v1(); v1();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v1 = write_three; v1 = write_three;
BOOST_TEST(!v1.empty()); BOOST_CHECK(!v1.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v1(); v1();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Construction from another function (that is empty) // Construction from another function (that is empty)
v1.clear(); v1.clear();
func_void_type v2(v1); func_void_type v2(v1);
BOOST_TEST(!v2? true : false); BOOST_CHECK(!v2? true : false);
// Assignment to an empty function // Assignment to an empty function
v2 = three; v2 = three;
BOOST_TEST(!v2.empty()); BOOST_CHECK(!v2.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function // Assignment to a non-empty function
v2 = (five); v2 = (five);
@@ -150,86 +150,86 @@ test_zero_args()
// Invocation // Invocation
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
v2.clear(); v2.clear();
BOOST_TEST(v2.empty()); BOOST_CHECK(v2.empty());
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
v2 = (&write_five); v2 = (&write_five);
BOOST_TEST(v2? true : false); BOOST_CHECK(v2? true : false);
// Invocation // Invocation
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v2 = &write_three; v2 = &write_three;
BOOST_TEST(!v2.empty()); BOOST_CHECK(!v2.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Swapping // Swapping
v1 = five; v1 = five;
swap(v1, v2); swap(v1, v2);
v2(); v2();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
v1(); v1();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
swap(v1, v2); swap(v1, v2);
v1.clear(); v1.clear();
// Assignment // Assignment
v2 = five; v2 = five;
BOOST_TEST(!v2.empty()); BOOST_CHECK(!v2.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v2 = &write_three; v2 = &write_three;
BOOST_TEST(!v2.empty()); BOOST_CHECK(!v2.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment to a function from an empty function // Assignment to a function from an empty function
v2 = v1; v2 = v1;
BOOST_TEST(v2.empty()); BOOST_CHECK(v2.empty());
// Assignment to a function from a function with a functor // Assignment to a function from a function with a functor
v1 = three; v1 = three;
v2 = v1; v2 = v1;
BOOST_TEST(!v1.empty()); BOOST_CHECK(!v1.empty());
BOOST_TEST(!v2.empty()); BOOST_CHECK(!v2.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v1(); v1();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assign to a function from a function with a function // Assign to a function from a function with a function
v2 = &write_five; v2 = &write_five;
v1 = v2; v1 = v2;
BOOST_TEST(!v1.empty()); BOOST_CHECK(!v1.empty());
BOOST_TEST(!v2.empty()); BOOST_CHECK(!v2.empty());
global_int = 0; global_int = 0;
v1(); v1();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Construct a function given another function containing a function // Construct a function given another function containing a function
func_void_type v3(v1); func_void_type v3(v1);
@@ -237,20 +237,20 @@ test_zero_args()
// Invocation of a function // Invocation of a function
global_int = 0; global_int = 0;
v3(); v3();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() method // clear() method
v3.clear(); v3.clear();
BOOST_TEST(!v3? true : false); BOOST_CHECK(!v3? true : false);
// Assignment to an empty function // Assignment to an empty function
v3 = three; v3 = three;
BOOST_TEST(!v3.empty()); BOOST_CHECK(!v3.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v3(); v3();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function // Assignment to a non-empty function
v3 = five; v3 = five;
@@ -258,38 +258,38 @@ test_zero_args()
// Invocation // Invocation
global_int = 0; global_int = 0;
v3(); v3();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() // clear()
v3.clear(); v3.clear();
BOOST_TEST(v3.empty()); BOOST_CHECK(v3.empty());
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
v3 = &write_five; v3 = &write_five;
BOOST_TEST(!v3.empty()); BOOST_CHECK(!v3.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v3(); v3();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v3 = &write_three; v3 = &write_three;
BOOST_TEST(!v3.empty()); BOOST_CHECK(!v3.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v3(); v3();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment // Assignment
v3 = five; v3 = five;
BOOST_TEST(!v3.empty()); BOOST_CHECK(!v3.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v3(); v3();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Construction of a function from a function containing a functor // Construction of a function from a function containing a functor
func_void_type v4(v3); func_void_type v4(v3);
@@ -297,20 +297,20 @@ test_zero_args()
// Invocation of a function // Invocation of a function
global_int = 0; global_int = 0;
v4(); v4();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() method // clear() method
v4.clear(); v4.clear();
BOOST_TEST(v4.empty()); BOOST_CHECK(v4.empty());
// Assignment to an empty function // Assignment to an empty function
v4 = three; v4 = three;
BOOST_TEST(!v4.empty()); BOOST_CHECK(!v4.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v4(); v4();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function // Assignment to a non-empty function
v4 = five; v4 = five;
@@ -318,38 +318,38 @@ test_zero_args()
// Invocation // Invocation
global_int = 0; global_int = 0;
v4(); v4();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() // clear()
v4.clear(); v4.clear();
BOOST_TEST(v4.empty()); BOOST_CHECK(v4.empty());
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
v4 = &write_five; v4 = &write_five;
BOOST_TEST(!v4.empty()); BOOST_CHECK(!v4.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v4(); v4();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v4 = &write_three; v4 = &write_three;
BOOST_TEST(!v4.empty()); BOOST_CHECK(!v4.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v4(); v4();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment // Assignment
v4 = five; v4 = five;
BOOST_TEST(!v4.empty()); BOOST_CHECK(!v4.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v4(); v4();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Construction of a function from a functor // Construction of a function from a functor
func_void_type v5(five); func_void_type v5(five);
@@ -357,20 +357,20 @@ test_zero_args()
// Invocation of a function // Invocation of a function
global_int = 0; global_int = 0;
v5(); v5();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() method // clear() method
v5.clear(); v5.clear();
BOOST_TEST(v5.empty()); BOOST_CHECK(v5.empty());
// Assignment to an empty function // Assignment to an empty function
v5 = three; v5 = three;
BOOST_TEST(!v5.empty()); BOOST_CHECK(!v5.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v5(); v5();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function // Assignment to a non-empty function
v5 = five; v5 = five;
@@ -378,38 +378,38 @@ test_zero_args()
// Invocation // Invocation
global_int = 0; global_int = 0;
v5(); v5();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() // clear()
v5.clear(); v5.clear();
BOOST_TEST(v5.empty()); BOOST_CHECK(v5.empty());
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
v5 = &write_five; v5 = &write_five;
BOOST_TEST(!v5.empty()); BOOST_CHECK(!v5.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v5(); v5();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v5 = &write_three; v5 = &write_three;
BOOST_TEST(!v5.empty()); BOOST_CHECK(!v5.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v5(); v5();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment // Assignment
v5 = five; v5 = five;
BOOST_TEST(!v5.empty()); BOOST_CHECK(!v5.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v5(); v5();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Construction of a function from a function // Construction of a function from a function
func_void_type v6(&write_five); func_void_type v6(&write_five);
@@ -417,20 +417,20 @@ test_zero_args()
// Invocation of a function // Invocation of a function
global_int = 0; global_int = 0;
v6(); v6();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() method // clear() method
v6.clear(); v6.clear();
BOOST_TEST(v6.empty()); BOOST_CHECK(v6.empty());
// Assignment to an empty function // Assignment to an empty function
v6 = three; v6 = three;
BOOST_TEST(!v6.empty()); BOOST_CHECK(!v6.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v6(); v6();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function // Assignment to a non-empty function
v6 = five; v6 = five;
@@ -438,38 +438,38 @@ test_zero_args()
// Invocation // Invocation
global_int = 0; global_int = 0;
v6(); v6();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() // clear()
v6.clear(); v6.clear();
BOOST_TEST(v6.empty()); BOOST_CHECK(v6.empty());
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
v6 = &write_five; v6 = &write_five;
BOOST_TEST(!v6.empty()); BOOST_CHECK(!v6.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v6(); v6();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v6 = &write_three; v6 = &write_three;
BOOST_TEST(!v6.empty()); BOOST_CHECK(!v6.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v6(); v6();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment // Assignment
v6 = five; v6 = five;
BOOST_TEST(!v6.empty()); BOOST_CHECK(!v6.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v6(); v6();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Const vs. non-const // Const vs. non-const
// Initialization for Borland C++ 5.5 // Initialization for Borland C++ 5.5
@@ -479,19 +479,19 @@ test_zero_args()
global_int = 0; global_int = 0;
v7(); v7();
BOOST_TEST(global_int == 2); BOOST_CHECK(global_int == 2);
global_int = 0; global_int = 0;
v8(); v8();
BOOST_TEST(global_int == 2); BOOST_CHECK(global_int == 2);
// Test construction from 0 and comparison to 0 // Test construction from 0 and comparison to 0
func_void_type v9(0); func_void_type v9(0);
BOOST_TEST(v9 == 0); BOOST_CHECK(v9 == 0);
# if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540 || defined(BOOST_STRICT_CONFIG) # if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540 || defined(BOOST_STRICT_CONFIG)
BOOST_TEST(0 == v9); BOOST_CHECK(0 == v9);
#else #else
BOOST_TEST(v9.empty()); BOOST_CHECK(v9.empty());
#endif #endif
// Test return values // Test return values
@@ -501,31 +501,31 @@ test_zero_args()
generate_three_obj gen_three = generate_three_obj(); generate_three_obj gen_three = generate_three_obj();
func_int_type i0(gen_five); func_int_type i0(gen_five);
BOOST_TEST(i0() == 5); BOOST_CHECK(i0() == 5);
i0 = gen_three; i0 = gen_three;
BOOST_TEST(i0() == 3); BOOST_CHECK(i0() == 3);
i0 = &generate_five; i0 = &generate_five;
BOOST_TEST(i0() == 5); BOOST_CHECK(i0() == 5);
i0 = &generate_three; i0 = &generate_three;
BOOST_TEST(i0() == 3); BOOST_CHECK(i0() == 3);
BOOST_TEST(i0? true : false); BOOST_CHECK(i0? true : false);
i0.clear(); i0.clear();
BOOST_TEST(!i0? true : false); BOOST_CHECK(!i0? true : false);
// Test return values with compatible types // Test return values with compatible types
typedef function0<long> func_long_type; typedef function0<long> func_long_type;
func_long_type i1(gen_five); func_long_type i1(gen_five);
BOOST_TEST(i1() == 5); BOOST_CHECK(i1() == 5);
i1 = gen_three; i1 = gen_three;
BOOST_TEST(i1() == 3); BOOST_CHECK(i1() == 3);
i1 = &generate_five; i1 = &generate_five;
BOOST_TEST(i1() == 5); BOOST_CHECK(i1() == 5);
i1 = &generate_three; i1 = &generate_three;
BOOST_TEST(i1() == 3); BOOST_CHECK(i1() == 3);
BOOST_TEST(i1? true : false); BOOST_CHECK(i1? true : false);
i1.clear(); i1.clear();
BOOST_TEST(!i1? true : false); BOOST_CHECK(!i1? true : false);
} }
static void static void
@@ -534,45 +534,45 @@ test_one_arg()
negate<int> neg = negate<int>(); // Initialization for Borland C++ 5.5 negate<int> neg = negate<int>(); // Initialization for Borland C++ 5.5
function1<int, int> f1(neg); function1<int, int> f1(neg);
BOOST_TEST(f1(5) == -5); BOOST_CHECK(f1(5) == -5);
function1<string, string> id(&identity_str); function1<string, string> id(&identity_str);
BOOST_TEST(id("str") == "str"); BOOST_CHECK(id("str") == "str");
function1<std::string, const char*> id2(&identity_str); function1<std::string, const char*> id2(&identity_str);
BOOST_TEST(id2("foo") == "foo"); BOOST_CHECK(id2("foo") == "foo");
add_to_obj add_to(5); add_to_obj add_to(5);
function1<int, int> f2(add_to); function1<int, int> f2(add_to);
BOOST_TEST(f2(3) == 8); BOOST_CHECK(f2(3) == 8);
const function1<int, int> cf2(add_to); const function1<int, int> cf2(add_to);
BOOST_TEST(cf2(3) == 8); BOOST_CHECK(cf2(3) == 8);
} }
static void static void
test_two_args() test_two_args()
{ {
function2<string, const string&, const string&> cat(&string_cat); function2<string, const string&, const string&> cat(&string_cat);
BOOST_TEST(cat("str", "ing") == "string"); BOOST_CHECK(cat("str", "ing") == "string");
function2<int, short, short> sum(&sum_ints); function2<int, short, short> sum(&sum_ints);
BOOST_TEST(sum(2, 3) == 5); BOOST_CHECK(sum(2, 3) == 5);
} }
static void static void
test_emptiness() test_emptiness()
{ {
function0<float> f1; function0<float> f1;
BOOST_TEST(f1.empty()); BOOST_CHECK(f1.empty());
function0<float> f2; function0<float> f2;
f2 = f1; f2 = f1;
BOOST_TEST(f2.empty()); BOOST_CHECK(f2.empty());
function0<double> f3; function0<double> f3;
f3 = f2; f3 = f2;
BOOST_TEST(f3.empty()); BOOST_CHECK(f3.empty());
} }
struct X { struct X {
@@ -593,18 +593,18 @@ test_member_functions()
X one(1); X one(1);
X five(5); X five(5);
BOOST_TEST(f1(&one) == 2); BOOST_CHECK(f1(&one) == 2);
BOOST_TEST(f1(&five) == 10); BOOST_CHECK(f1(&five) == 10);
boost::function1<int, X*> f1_2; boost::function1<int, X*> f1_2;
f1_2 = &X::twice; f1_2 = &X::twice;
BOOST_TEST(f1_2(&one) == 2); BOOST_CHECK(f1_2(&one) == 2);
BOOST_TEST(f1_2(&five) == 10); BOOST_CHECK(f1_2(&five) == 10);
boost::function2<int, X&, int> f2(&X::plus); boost::function2<int, X&, int> f2(&X::plus);
BOOST_TEST(f2(one, 3) == 4); BOOST_CHECK(f2(one, 3) == 4);
BOOST_TEST(f2(five, 4) == 9); BOOST_CHECK(f2(five, 4) == 9);
} }
struct add_with_throw_on_copy { struct add_with_throw_on_copy {
@@ -629,7 +629,7 @@ test_ref()
add_with_throw_on_copy atc; add_with_throw_on_copy atc;
try { try {
boost::function2<int, int, int> f(ref(atc)); boost::function2<int, int, int> f(ref(atc));
BOOST_TEST(f(1, 3) == 4); BOOST_CHECK(f(1, 3) == 4);
} }
catch(std::runtime_error e) { catch(std::runtime_error e) {
BOOST_ERROR("Nonthrowing constructor threw an exception"); BOOST_ERROR("Nonthrowing constructor threw an exception");

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2001-2003. Use, modification and // Copyright Douglas Gregor 2001-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@@ -10,7 +10,6 @@
#include <boost/test/minimal.hpp> #include <boost/test/minimal.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <functional> #include <functional>
#include <cassert>
#include <string> #include <string>
#include <utility> #include <utility>
@@ -56,30 +55,30 @@ test_zero_args()
// Default construction // Default construction
func_void_type v1; func_void_type v1;
BOOST_TEST(v1.empty()); BOOST_CHECK(v1.empty());
// Assignment to an empty function // Assignment to an empty function
v1 = five; v1 = five;
BOOST_TEST(v1 != 0); BOOST_CHECK(v1 != 0);
// Invocation of a function // Invocation of a function
global_int = 0; global_int = 0;
v1(); v1();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() method // clear() method
v1.clear(); v1.clear();
BOOST_TEST(v1 == 0); BOOST_CHECK(v1 == 0);
// Assignment to an empty function // Assignment to an empty function
v1 = three; v1 = three;
BOOST_TEST(!v1.empty()); BOOST_CHECK(!v1.empty());
// Invocation and self-assignment // Invocation and self-assignment
global_int = 0; global_int = 0;
v1 = v1; v1 = v1;
v1(); v1();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function // Assignment to a non-empty function
v1 = five; v1 = five;
@@ -88,61 +87,61 @@ test_zero_args()
global_int = 0; global_int = 0;
v1 = (v1); v1 = (v1);
v1(); v1();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear // clear
v1 = 0; v1 = 0;
BOOST_TEST(0 == v1); BOOST_CHECK(0 == v1);
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
v1 = BOOST_FUNCTION_TARGET_FIX(&) write_five; v1 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
BOOST_TEST(0 != v1); BOOST_CHECK(0 != v1);
// Invocation // Invocation
global_int = 0; global_int = 0;
v1(); v1();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v1 = BOOST_FUNCTION_TARGET_FIX(&) write_three; v1 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
BOOST_TEST(!v1.empty()); BOOST_CHECK(!v1.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v1(); v1();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment // Assignment
v1 = five; v1 = five;
BOOST_TEST(!v1.empty()); BOOST_CHECK(!v1.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v1(); v1();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v1 = &write_three; v1 = &write_three;
BOOST_TEST(!v1.empty()); BOOST_CHECK(!v1.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v1(); v1();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Construction from another function (that is empty) // Construction from another function (that is empty)
v1.clear(); v1.clear();
func_void_type v2(v1); func_void_type v2(v1);
BOOST_TEST(!v2? true : false); BOOST_CHECK(!v2? true : false);
// Assignment to an empty function // Assignment to an empty function
v2 = three; v2 = three;
BOOST_TEST(!v2.empty()); BOOST_CHECK(!v2.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function // Assignment to a non-empty function
v2 = (five); v2 = (five);
@@ -150,86 +149,86 @@ test_zero_args()
// Invocation // Invocation
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
v2.clear(); v2.clear();
BOOST_TEST(v2.empty()); BOOST_CHECK(v2.empty());
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
v2 = (BOOST_FUNCTION_TARGET_FIX(&) write_five); v2 = (BOOST_FUNCTION_TARGET_FIX(&) write_five);
BOOST_TEST(v2? true : false); BOOST_CHECK(v2? true : false);
// Invocation // Invocation
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v2 = BOOST_FUNCTION_TARGET_FIX(&) write_three; v2 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
BOOST_TEST(!v2.empty()); BOOST_CHECK(!v2.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Swapping // Swapping
v1 = five; v1 = five;
swap(v1, v2); swap(v1, v2);
v2(); v2();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
v1(); v1();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
swap(v1, v2); swap(v1, v2);
v1.clear(); v1.clear();
// Assignment // Assignment
v2 = five; v2 = five;
BOOST_TEST(!v2.empty()); BOOST_CHECK(!v2.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v2 = &write_three; v2 = &write_three;
BOOST_TEST(!v2.empty()); BOOST_CHECK(!v2.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment to a function from an empty function // Assignment to a function from an empty function
v2 = v1; v2 = v1;
BOOST_TEST(v2.empty()); BOOST_CHECK(v2.empty());
// Assignment to a function from a function with a functor // Assignment to a function from a function with a functor
v1 = three; v1 = three;
v2 = v1; v2 = v1;
BOOST_TEST(!v1.empty()); BOOST_CHECK(!v1.empty());
BOOST_TEST(!v2.empty()); BOOST_CHECK(!v2.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v1(); v1();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assign to a function from a function with a function // Assign to a function from a function with a function
v2 = BOOST_FUNCTION_TARGET_FIX(&) write_five; v2 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
v1 = v2; v1 = v2;
BOOST_TEST(!v1.empty()); BOOST_CHECK(!v1.empty());
BOOST_TEST(!v2.empty()); BOOST_CHECK(!v2.empty());
global_int = 0; global_int = 0;
v1(); v1();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
global_int = 0; global_int = 0;
v2(); v2();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Construct a function given another function containing a function // Construct a function given another function containing a function
func_void_type v3(v1); func_void_type v3(v1);
@@ -237,20 +236,20 @@ test_zero_args()
// Invocation of a function // Invocation of a function
global_int = 0; global_int = 0;
v3(); v3();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() method // clear() method
v3.clear(); v3.clear();
BOOST_TEST(!v3? true : false); BOOST_CHECK(!v3? true : false);
// Assignment to an empty function // Assignment to an empty function
v3 = three; v3 = three;
BOOST_TEST(!v3.empty()); BOOST_CHECK(!v3.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v3(); v3();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function // Assignment to a non-empty function
v3 = five; v3 = five;
@@ -258,38 +257,38 @@ test_zero_args()
// Invocation // Invocation
global_int = 0; global_int = 0;
v3(); v3();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() // clear()
v3.clear(); v3.clear();
BOOST_TEST(v3.empty()); BOOST_CHECK(v3.empty());
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
v3 = &write_five; v3 = &write_five;
BOOST_TEST(!v3.empty()); BOOST_CHECK(!v3.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v3(); v3();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v3 = &write_three; v3 = &write_three;
BOOST_TEST(!v3.empty()); BOOST_CHECK(!v3.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v3(); v3();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment // Assignment
v3 = five; v3 = five;
BOOST_TEST(!v3.empty()); BOOST_CHECK(!v3.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v3(); v3();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Construction of a function from a function containing a functor // Construction of a function from a function containing a functor
func_void_type v4(v3); func_void_type v4(v3);
@@ -297,20 +296,20 @@ test_zero_args()
// Invocation of a function // Invocation of a function
global_int = 0; global_int = 0;
v4(); v4();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() method // clear() method
v4.clear(); v4.clear();
BOOST_TEST(v4.empty()); BOOST_CHECK(v4.empty());
// Assignment to an empty function // Assignment to an empty function
v4 = three; v4 = three;
BOOST_TEST(!v4.empty()); BOOST_CHECK(!v4.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v4(); v4();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function // Assignment to a non-empty function
v4 = five; v4 = five;
@@ -318,38 +317,38 @@ test_zero_args()
// Invocation // Invocation
global_int = 0; global_int = 0;
v4(); v4();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() // clear()
v4.clear(); v4.clear();
BOOST_TEST(v4.empty()); BOOST_CHECK(v4.empty());
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
v4 = &write_five; v4 = &write_five;
BOOST_TEST(!v4.empty()); BOOST_CHECK(!v4.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v4(); v4();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v4 = &write_three; v4 = &write_three;
BOOST_TEST(!v4.empty()); BOOST_CHECK(!v4.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v4(); v4();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment // Assignment
v4 = five; v4 = five;
BOOST_TEST(!v4.empty()); BOOST_CHECK(!v4.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v4(); v4();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Construction of a function from a functor // Construction of a function from a functor
func_void_type v5(five); func_void_type v5(five);
@@ -357,20 +356,20 @@ test_zero_args()
// Invocation of a function // Invocation of a function
global_int = 0; global_int = 0;
v5(); v5();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() method // clear() method
v5.clear(); v5.clear();
BOOST_TEST(v5.empty()); BOOST_CHECK(v5.empty());
// Assignment to an empty function // Assignment to an empty function
v5 = three; v5 = three;
BOOST_TEST(!v5.empty()); BOOST_CHECK(!v5.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v5(); v5();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function // Assignment to a non-empty function
v5 = five; v5 = five;
@@ -378,38 +377,38 @@ test_zero_args()
// Invocation // Invocation
global_int = 0; global_int = 0;
v5(); v5();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() // clear()
v5.clear(); v5.clear();
BOOST_TEST(v5.empty()); BOOST_CHECK(v5.empty());
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
v5 = &write_five; v5 = &write_five;
BOOST_TEST(!v5.empty()); BOOST_CHECK(!v5.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v5(); v5();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v5 = &write_three; v5 = &write_three;
BOOST_TEST(!v5.empty()); BOOST_CHECK(!v5.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v5(); v5();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment // Assignment
v5 = five; v5 = five;
BOOST_TEST(!v5.empty()); BOOST_CHECK(!v5.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v5(); v5();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Construction of a function from a function // Construction of a function from a function
func_void_type v6(&write_five); func_void_type v6(&write_five);
@@ -417,20 +416,20 @@ test_zero_args()
// Invocation of a function // Invocation of a function
global_int = 0; global_int = 0;
v6(); v6();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() method // clear() method
v6.clear(); v6.clear();
BOOST_TEST(v6.empty()); BOOST_CHECK(v6.empty());
// Assignment to an empty function // Assignment to an empty function
v6 = three; v6 = three;
BOOST_TEST(!v6.empty()); BOOST_CHECK(!v6.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v6(); v6();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function // Assignment to a non-empty function
v6 = five; v6 = five;
@@ -438,38 +437,38 @@ test_zero_args()
// Invocation // Invocation
global_int = 0; global_int = 0;
v6(); v6();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// clear() // clear()
v6.clear(); v6.clear();
BOOST_TEST(v6.empty()); BOOST_CHECK(v6.empty());
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
v6 = &write_five; v6 = &write_five;
BOOST_TEST(!v6.empty()); BOOST_CHECK(!v6.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v6(); v6();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function // Assignment to a non-empty function from a free function
v6 = &write_three; v6 = &write_three;
BOOST_TEST(!v6.empty()); BOOST_CHECK(!v6.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v6(); v6();
BOOST_TEST(global_int == 3); BOOST_CHECK(global_int == 3);
// Assignment // Assignment
v6 = five; v6 = five;
BOOST_TEST(!v6.empty()); BOOST_CHECK(!v6.empty());
// Invocation // Invocation
global_int = 0; global_int = 0;
v6(); v6();
BOOST_TEST(global_int == 5); BOOST_CHECK(global_int == 5);
// Const vs. non-const // Const vs. non-const
write_const_1_nonconst_2 one_or_two; write_const_1_nonconst_2 one_or_two;
@@ -478,16 +477,16 @@ test_zero_args()
global_int = 0; global_int = 0;
v7(); v7();
BOOST_TEST(global_int == 2); BOOST_CHECK(global_int == 2);
global_int = 0; global_int = 0;
v8(); v8();
BOOST_TEST(global_int == 2); BOOST_CHECK(global_int == 2);
// Test construction from 0 and comparison to 0 // Test construction from 0 and comparison to 0
func_void_type v9(0); func_void_type v9(0);
BOOST_TEST(v9 == 0); BOOST_CHECK(v9 == 0);
BOOST_TEST(0 == v9); BOOST_CHECK(0 == v9);
// Test return values // Test return values
typedef function<int ()> func_int_type; typedef function<int ()> func_int_type;
@@ -496,31 +495,31 @@ test_zero_args()
func_int_type i0(gen_five); func_int_type i0(gen_five);
BOOST_TEST(i0() == 5); BOOST_CHECK(i0() == 5);
i0 = gen_three; i0 = gen_three;
BOOST_TEST(i0() == 3); BOOST_CHECK(i0() == 3);
i0 = &generate_five; i0 = &generate_five;
BOOST_TEST(i0() == 5); BOOST_CHECK(i0() == 5);
i0 = &generate_three; i0 = &generate_three;
BOOST_TEST(i0() == 3); BOOST_CHECK(i0() == 3);
BOOST_TEST(i0? true : false); BOOST_CHECK(i0? true : false);
i0.clear(); i0.clear();
BOOST_TEST(!i0? true : false); BOOST_CHECK(!i0? true : false);
// Test return values with compatible types // Test return values with compatible types
typedef function<long ()> func_long_type; typedef function<long ()> func_long_type;
func_long_type i1(gen_five); func_long_type i1(gen_five);
BOOST_TEST(i1() == 5); BOOST_CHECK(i1() == 5);
i1 = gen_three; i1 = gen_three;
BOOST_TEST(i1() == 3); BOOST_CHECK(i1() == 3);
i1 = &generate_five; i1 = &generate_five;
BOOST_TEST(i1() == 5); BOOST_CHECK(i1() == 5);
i1 = &generate_three; i1 = &generate_three;
BOOST_TEST(i1() == 3); BOOST_CHECK(i1() == 3);
BOOST_TEST(i1? true : false); BOOST_CHECK(i1? true : false);
i1.clear(); i1.clear();
BOOST_TEST(!i1? true : false); BOOST_CHECK(!i1? true : false);
} }
static void static void
@@ -529,45 +528,45 @@ test_one_arg()
negate<int> neg; negate<int> neg;
function<int (int)> f1(neg); function<int (int)> f1(neg);
BOOST_TEST(f1(5) == -5); BOOST_CHECK(f1(5) == -5);
function<string (string)> id(&identity_str); function<string (string)> id(&identity_str);
BOOST_TEST(id("str") == "str"); BOOST_CHECK(id("str") == "str");
function<string (const char*)> id2(&identity_str); function<string (const char*)> id2(&identity_str);
BOOST_TEST(id2("foo") == "foo"); BOOST_CHECK(id2("foo") == "foo");
add_to_obj add_to(5); add_to_obj add_to(5);
function<int (int)> f2(add_to); function<int (int)> f2(add_to);
BOOST_TEST(f2(3) == 8); BOOST_CHECK(f2(3) == 8);
const function<int (int)> cf2(add_to); const function<int (int)> cf2(add_to);
BOOST_TEST(cf2(3) == 8); BOOST_CHECK(cf2(3) == 8);
} }
static void static void
test_two_args() test_two_args()
{ {
function<string (const string&, const string&)> cat(&string_cat); function<string (const string&, const string&)> cat(&string_cat);
BOOST_TEST(cat("str", "ing") == "string"); BOOST_CHECK(cat("str", "ing") == "string");
function<int (short, short)> sum(&sum_ints); function<int (short, short)> sum(&sum_ints);
BOOST_TEST(sum(2, 3) == 5); BOOST_CHECK(sum(2, 3) == 5);
} }
static void static void
test_emptiness() test_emptiness()
{ {
function<float ()> f1; function<float ()> f1;
BOOST_TEST(f1.empty()); BOOST_CHECK(f1.empty());
function<float ()> f2; function<float ()> f2;
f2 = f1; f2 = f1;
BOOST_TEST(f2.empty()); BOOST_CHECK(f2.empty());
function<double ()> f3; function<double ()> f3;
f3 = f2; f3 = f2;
BOOST_TEST(f3.empty()); BOOST_CHECK(f3.empty());
} }
struct X { struct X {
@@ -587,18 +586,18 @@ test_member_functions()
X one(1); X one(1);
X five(5); X five(5);
BOOST_TEST(f1(&one) == 2); BOOST_CHECK(f1(&one) == 2);
BOOST_TEST(f1(&five) == 10); BOOST_CHECK(f1(&five) == 10);
boost::function<int (X*)> f1_2; boost::function<int (X*)> f1_2;
f1_2 = &X::twice; f1_2 = &X::twice;
BOOST_TEST(f1_2(&one) == 2); BOOST_CHECK(f1_2(&one) == 2);
BOOST_TEST(f1_2(&five) == 10); BOOST_CHECK(f1_2(&five) == 10);
boost::function<int (X&, int)> f2(&X::plus); boost::function<int (X&, int)> f2(&X::plus);
BOOST_TEST(f2(one, 3) == 4); BOOST_CHECK(f2(one, 3) == 4);
BOOST_TEST(f2(five, 4) == 9); BOOST_CHECK(f2(five, 4) == 9);
} }
struct add_with_throw_on_copy { struct add_with_throw_on_copy {
@@ -623,83 +622,19 @@ test_ref()
add_with_throw_on_copy atc; add_with_throw_on_copy atc;
try { try {
boost::function<int (int, int)> f(ref(atc)); boost::function<int (int, int)> f(ref(atc));
BOOST_TEST(f(1, 3) == 4); BOOST_CHECK(f(1, 3) == 4);
} }
catch(runtime_error e) { catch(runtime_error e) {
BOOST_ERROR("Nonthrowing constructor threw an exception"); BOOST_ERROR("Nonthrowing constructor threw an exception");
} }
} }
static int alloc_count = 0;
static int dealloc_count = 0;
template<typename T>
struct counting_allocator : public allocator<T>
{
template<typename U>
struct rebind
{
typedef counting_allocator<U> other;
};
T* allocate(size_t n)
{
alloc_count++;
return allocator<T>::allocate(n);
}
void deallocate(T* p, size_t n)
{
dealloc_count++;
allocator<T>::deallocate(p, n);
}
};
static int do_minus(int x, int y) { return x-y; }
struct DoNothing
{
void operator()() const {}
};
static void do_nothing() {}
static void test_allocator()
{
#ifndef BOOST_NO_STD_ALLOCATOR
boost::function<int (int, int), counting_allocator<int> > f;
f = plus<int>();
f.clear();
BOOST_TEST(alloc_count == 1);
BOOST_TEST(dealloc_count == 1);
alloc_count = 0;
dealloc_count = 0;
f = &do_minus;
f.clear();
boost::function<void (), counting_allocator<int> > fv;
alloc_count = 0;
dealloc_count = 0;
fv = DoNothing();
fv.clear();
BOOST_TEST(alloc_count == 1);
BOOST_TEST(dealloc_count == 1);
alloc_count = 0;
dealloc_count = 0;
fv = &do_nothing;
fv.clear();
#endif // ndef BOOST_NO_STD_ALLOCATOR
}
static void test_exception() static void test_exception()
{ {
boost::function<int (int, int)> f; boost::function<int (int, int)> f;
try { try {
f(5, 4); f(5, 4);
BOOST_TEST(false); BOOST_CHECK(false);
} }
catch(boost::bad_function_call) { catch(boost::bad_function_call) {
// okay // okay
@@ -717,12 +652,12 @@ static void test_implicit()
static void test_call_obj(boost::function<int (int, int)> f) 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) static void test_call_cref(const boost::function<int (int, int)>& f)
{ {
assert(!f.empty()); BOOST_CHECK(!f.empty());
} }
static void test_call() static void test_call()
@@ -739,7 +674,6 @@ int test_main(int, char* [])
test_emptiness(); test_emptiness();
test_member_functions(); test_member_functions();
test_ref(); test_ref();
test_allocator();
test_exception(); test_exception();
test_implicit(); test_implicit();
test_call(); test_call();

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2001-2003. Use, modification and // Copyright (C) Douglas Gregor 2001-2005. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@@ -22,7 +22,7 @@ test_main(int, char*[])
if (f1 == f2) { if (f1 == f2) {
} }
BOOST_CRITICAL_ERROR("This should not have compiled."); BOOST_ERROR("This should not have compiled.");
return 0; return 0;
} }

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2001-2003. Use, modification and // Copyright (C) Douglas Gregor 2001-2005. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@@ -21,7 +21,7 @@ test_main(int, char*[])
function0<int> f1; function0<int> f1;
f1 = bad_fn; f1 = bad_fn;
BOOST_CRITICAL_ERROR("This should not have compiled."); BOOST_ERROR("This should not have compiled.");
return 0; return 0;
} }

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2002-2003. Use, modification and // Copyright Douglas Gregor 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright Doug Gregor 2001-2003. Use, modification and // Copyright Douglas Gregor 2001-2003. Use, modification and
// distribution is subject to the Boost Software License, Version // distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@@ -14,23 +14,21 @@
struct stateless_integer_add { struct stateless_integer_add {
int operator()(int x, int y) const { return x+y; } 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"); 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*[]) int test_main(int, char*[])
{ {
boost::function2<int, int, int> f; boost::function2<int, int, int> f;