Compare commits

...

27 Commits

Author SHA1 Message Date
nobody
31b04d14bf This commit was manufactured by cvs2svn to create tag
'Version_1_32_0'.

[SVN r26264]
2004-11-19 19:19:18 +00:00
nobody
f3250a605b This commit was manufactured by cvs2svn to create branch 'RC_1_32_0'.
[SVN r25797]
2004-10-20 08:26:43 +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
39 changed files with 1193 additions and 153 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>
</answer>
</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>
</section>

View File

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

View File

@@ -79,10 +79,46 @@
<method-group name="capacity">
<method name="empty" cv="const">
<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-group>
</class>
<class name="functionN">
@@ -199,7 +235,7 @@
<method-group name="capacity">
<method name="empty" cv="const">
<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>
@@ -216,6 +252,42 @@
</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-group>
<method-group name="invocation">
<method name="operator()" cv="const">
<type>result_type</type>
@@ -246,46 +318,208 @@
</function>
</free-function-group>
<free-function-group name="undefined operators">
<function name="operator==">
<template>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="U1"/>
<template-type-parameter name="U2"/>
<template-varargs/>
<template-type-parameter name="UN"/>
<template-type-parameter name="Allocator2"/>
</template>
<type>void</type>
<parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN, Allocator2&gt;&amp;</paramtype></parameter>
<notes><simpara>This function must be left undefined.</simpara></notes>
<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>
<free-function-group name="comparison operators">
<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-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="U1"/>
<template-type-parameter name="U2"/>
<template-varargs/>
<template-type-parameter name="UN"/>
<template-type-parameter name="Allocator2"/>
</template>
<type>void</type>
<parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN, Allocator2&gt;&amp;</paramtype></parameter>
</signature>
<function name="operator!=">
<template>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="U1"/>
<template-type-parameter name="U2"/>
<template-varargs/>
<template-type-parameter name="UN"/>
<template-type-parameter name="Allocator2"/>
</template>
<type>void</type>
<parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN, Allocator2&gt;&amp;</paramtype></parameter>
<notes><simpara>This function must be left undefined.</simpara></notes>
<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> 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-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="U1"/>
<template-type-parameter name="U2"/>
<template-varargs/>
<template-type-parameter name="UN"/>
<template-type-parameter name="Allocator2"/>
</template>
<type>void</type>
<parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN, Allocator2&gt;&amp;</paramtype></parameter>
</signature>
<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>
</class>
@@ -424,7 +658,7 @@
<method-group name="capacity">
<method name="empty" cv="const">
<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>
@@ -441,6 +675,41 @@
</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-group>
<method-group name="invocation">
<method name="operator()" cv="const">
<type>result_type</type>
@@ -468,36 +737,193 @@
</function>
</free-function-group>
<free-function-group name="undefined operators">
<function name="operator==">
<template>
<template-type-parameter name="Signature1"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="Signature2"/>
<template-type-parameter name="Allocator2"/>
</template>
<type>void</type>
<parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2, Allocator2&gt;&amp;</paramtype></parameter>
<notes><simpara>This function must be left undefined.</simpara></notes>
<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>
<free-function-group name="comparison operators">
<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-type-parameter name="Signature1"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="Signature2"/>
<template-type-parameter name="Allocator2"/>
</template>
<type>void</type>
<parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2, Allocator2&gt;&amp;</paramtype></parameter>
</signature>
<function name="operator!=">
<template>
<template-type-parameter name="Signature1"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="Signature2"/>
<template-type-parameter name="Allocator2"/>
</template>
<type>void</type>
<parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2, Allocator2&gt;&amp;</paramtype></parameter>
<notes><simpara>This function must be left undefined.</simpara></notes>
<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> 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-type-parameter name="Signature1"/>
<template-type-parameter name="Allocator1"/>
<template-type-parameter name="Signature2"/>
<template-type-parameter name="Allocator2"/>
</template>
<type>void</type>
<parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1, Allocator1&gt;&amp;</paramtype></parameter>
<parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2, Allocator2&gt;&amp;</paramtype></parameter>
</signature>
<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>
</class>
</namespace>
</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>

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>
</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">
<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>

View File

@@ -248,17 +248,17 @@ f(&amp;x, 5);</programlisting>
<row>
<entry>
<programlisting name="function.tutorial.std_bind.cxx98"> <classname>boost::function</classname>&lt;int (int)&gt; f;
X x;
f = std::bind1st(
std::mem_fun(&amp;X::foo), &amp;x);
f(5); // Call x.foo(5)</programlisting>
X x;
f = std::bind1st(
std::mem_fun(&amp;X::foo), &amp;x);
f(5); // Call x.foo(5)</programlisting>
</entry>
<entry>
<programlisting name="function.tutorial.std_bind.portable"> <classname alt="functionN">boost::function1</classname>&lt;int, int&gt; f;
X x;
f = std::bind1st(
std::mem_fun(&amp;X::foo), &amp;x);
f(5); // Call x.foo(5)</programlisting>
X x;
f = std::bind1st(
std::mem_fun(&amp;X::foo), &amp;x);
f(5); // Call x.foo(5)</programlisting>
</entry>
</row>
</tbody>
@@ -274,7 +274,7 @@ f(&amp;x, 5);</programlisting>
</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
function object. In such cases, it is possible to request that
Boost.Function keep only a reference to the actual function
@@ -293,18 +293,18 @@ f(&amp;x, 5);</programlisting>
<tbody>
<row>
<entry>
<programlisting name="function.tutorial.ref.cxx98"> stateful_type a_function_object;
<classname>boost::function</classname>&lt;int (int)&gt; f;
f = <functionname>boost::ref</functionname>(a_function_object);
<programlisting name="function.tutorial.ref.cxx98">stateful_type a_function_object;
<classname>boost::function</classname>&lt;int (int)&gt; f;
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>
<programlisting name="function.tutorial.ref.portable"> stateful_type a_function_object;
<classname alt="functionN">boost::function1</classname>&lt;int, int&gt; f;
f = <functionname>boost::ref</functionname>(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;
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>
</row>
</tbody>
@@ -321,5 +321,37 @@ using references to function objects, Boost.Function will not throw
exceptions during assignment or construction.
</para>
</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
<conceptname>EqualityComparable</conceptname>). 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>

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
#
# 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
# provided this copyright notice appears in all copies.

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// Boost.Function library
// Copyright Doug Gregor 2001-2003. Use, modification and
// Copyright Douglas Gregor 2001-2004. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -14,17 +14,32 @@
#include <string>
#include <memory>
#include <new>
#include <typeinfo>
#include <boost/config.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/is_stateless.hpp>
#include <boost/ref.hpp>
#include <boost/pending/ct_if.hpp>
#include <boost/detail/workaround.hpp>
#ifndef BOOST_NO_SFINAE
# include "boost/utility/enable_if.hpp"
#else
# include "boost/mpl/bool.hpp"
#endif
#include <boost/function_equal.hpp>
// 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
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
@@ -48,6 +63,12 @@ namespace boost { namespace python { namespace objects {
# define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
#endif
#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
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
namespace boost {
@@ -139,7 +160,8 @@ namespace boost {
// The operation type to perform on the given functor/function pointer
enum functor_manager_operation_type {
clone_functor_tag,
destroy_functor_tag
destroy_functor_tag,
check_functor_type_tag
};
// Tags used to decide between different types of functions
@@ -172,14 +194,31 @@ namespace boost {
// The trivial manager does nothing but return the same pointer (if we
// are cloning) or return the null pointer (if we are deleting).
inline any_pointer trivial_manager(any_pointer f,
functor_manager_operation_type op)
template<typename F>
struct trivial_manager
{
if (op == clone_functor_tag)
return f;
else
static inline any_pointer
get(any_pointer f, functor_manager_operation_type op)
{
switch (op) {
case clone_functor_tag: return f;
case destroy_functor_tag:
return make_any_pointer(reinterpret_cast<void*>(0));
case check_functor_type_tag:
{
std::type_info* t = static_cast<std::type_info*>(f.obj_ptr);
return BOOST_FUNCTION_COMPARE_TYPE_ID(typeid(F), *t)?
f
: make_any_pointer(reinterpret_cast<void*>(0));
}
}
// Clears up a warning with GCC 3.2.3
return make_any_pointer(reinterpret_cast<void*>(0));
}
}
};
/**
* The functor_manager class contains a static function "manage" which
@@ -264,13 +303,81 @@ namespace boost {
static any_pointer
manage(any_pointer functor_ptr, functor_manager_operation_type op)
{
typedef typename get_function_tag<functor_type>::type tag_type;
return manager(functor_ptr, op, tag_type());
if (op == check_functor_type_tag) {
std::type_info* type =
static_cast<std::type_info*>(functor_ptr.obj_ptr);
return (BOOST_FUNCTION_COMPARE_TYPE_ID(typeid(Functor), *type)?
functor_ptr
: make_any_pointer(reinterpret_cast<void*>(0)));
}
else {
typedef typename get_function_tag<functor_type>::type tag_type;
return manager(functor_ptr, op, tag_type());
}
}
};
// A type that is only used for comparisons against zero
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
} // end namespace function
} // end namespace detail
@@ -291,11 +398,92 @@ public:
// Is this function empty?
bool empty() const { return !manager; }
template<typename Functor>
Functor* target()
{
if (!manager) return 0;
detail::function::any_pointer result =
manager(detail::function::make_any_pointer(&typeid(Functor)),
detail::function::check_functor_type_tag);
if (!result.obj_ptr) return 0;
else {
typedef typename detail::function::get_function_tag<Functor>::type tag;
return get_functor_pointer<Functor>(tag(), 0);
}
}
template<typename Functor>
const Functor* target() const
{
if (!manager) return 0;
detail::function::any_pointer result =
manager(detail::function::make_any_pointer(&typeid(Functor)),
detail::function::check_functor_type_tag);
if (!result.obj_ptr) return 0;
else {
typedef typename detail::function::get_function_tag<Functor>::type tag;
return get_functor_pointer<Functor>(tag(), 0);
}
}
template<typename F>
bool contains(const F& f) const
{
if (const F* fp = this->template target<F>()) {
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
detail::function::any_pointer (*manager)(
detail::function::any_pointer,
detail::function::functor_manager_operation_type);
detail::function::any_pointer functor;
private:
template<typename Functor>
Functor* get_functor_pointer(detail::function::function_ptr_tag, int)
{ return reinterpret_cast<Functor*>(&functor.func_ptr); }
template<typename Functor, typename Tag>
Functor* get_functor_pointer(Tag, long)
{ return static_cast<Functor*>(functor.obj_ptr); }
template<typename Functor>
const Functor*
get_functor_pointer(detail::function::function_ptr_tag, int) const
{ return reinterpret_cast<const Functor*>(&functor.func_ptr); }
template<typename Functor, typename Tag>
const Functor* get_functor_pointer(Tag, long) const
{ return static_cast<const Functor*>(functor.const_obj_ptr); }
};
/**
@@ -308,16 +496,7 @@ public:
bad_function_call() : std::runtime_error("call to empty boost::function") {}
};
/* Poison comparison between Boost.Function objects (because it is
* 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)
#ifndef BOOST_NO_SFINAE
inline bool operator==(const function_base& f,
detail::function::useless_clear_type*)
{
@@ -343,6 +522,116 @@ inline bool operator!=(detail::function::useless_clear_type*,
}
#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 function {
inline bool has_empty_target(const function_base* f)
@@ -350,12 +639,22 @@ namespace detail {
return f->empty();
}
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
inline bool has_empty_target(const void*)
{
return false;
}
#else
inline bool has_empty_target(...)
{
return false;
}
#endif
} // end namespace function
} // end namespace detail
} // end namespace boost
#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
#undef BOOST_FUNCTION_COMPARE_TYPE_ID
#endif // BOOST_FUNCTION_BASE_HEADER

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -307,6 +307,9 @@ namespace boost {
~BOOST_FUNCTION_FUNCTION() { clear(); }
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
// 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
{
if (this->empty())
@@ -322,6 +325,9 @@ namespace boost {
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
// when to use self_type is obnoxious. MSVC cannot handle self_type as
@@ -438,9 +444,9 @@ namespace boost {
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
actual_invoker_type;
invoker = &invoker_type::invoke;
invoker = &actual_invoker_type::invoke;
this->manager =
&detail::function::functor_manager<FunctionPtr, Allocator>::manage;
this->functor =
@@ -471,16 +477,16 @@ namespace boost {
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
actual_invoker_type;
invoker = &invoker_type::invoke;
invoker = &actual_invoker_type::invoke;
this->manager = &detail::function::functor_manager<
FunctionObj, Allocator>::manage;
#ifndef BOOST_NO_STD_ALLOCATOR
typedef typename Allocator::template rebind<FunctionObj>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
rebound_allocator_type;
typedef typename rebound_allocator_type::pointer pointer_type;
rebound_allocator_type allocator;
pointer_type copy = allocator.allocate(1);
allocator.construct(copy, f);
@@ -505,10 +511,10 @@ namespace boost {
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
actual_invoker_type;
invoker = &invoker_type::invoke;
this->manager = &detail::function::trivial_manager;
invoker = &actual_invoker_type::invoke;
this->manager = &detail::function::trivial_manager<FunctionObj>::get;
this->functor =
this->manager(
detail::function::make_any_pointer(
@@ -527,9 +533,9 @@ namespace boost {
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
invoker = &invoker_type::invoke;
this->manager = &detail::function::trivial_manager;
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
this->manager = &detail::function::trivial_manager<FunctionObj>::get;
this->functor = detail::function::make_any_pointer(this);
}
@@ -556,6 +562,54 @@ namespace boost {
f1.swap(f2);
}
#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
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());
internal_result_type result = invoker(this->functor
BOOST_FUNCTION_COMMA
BOOST_FUNCTION_ARGS);
# ifndef BOOST_NO_VOID_RETURNS
return static_cast<result_type>(result);
# else
return result;
# endif // BOOST_NO_VOID_RETURNS
}
#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 BOOST_FUNCTION_NUM_ARGS == 0

View File

@@ -2,7 +2,7 @@
#
# 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
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -0,0 +1,24 @@
// 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)
// For more information, see http://www.boost.org
#ifndef BOOST_FUNCTION_EQUAL_HPP
#define BOOST_FUNCTION_EQUAL_HPP
namespace boost {
namespace detail {
template<typename F, typename G>
bool function_equal_impl(const F& f, const G& g, long)
{ return f == g; }
} // end namespace boost::function
template<typename F, typename G>
bool function_equal(const F& f, const G& g)
{ return ::boost::detail::function_equal_impl(f, g, 0); }
} // end namespace boost
#endif // BOOST_FUNCTION_EQUAL_HPP

View File

@@ -60,6 +60,8 @@ DEPENDS all : test ;
[ run libs/function/test/function_ref_cxx98.cpp : : : : ]
[ run libs/function/test/function_ref_portable.cpp : : : : ]
[ run libs/function/test/contains_test.cpp : : : : ]
;
}

View File

@@ -1,6 +1,6 @@
# 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
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
@@ -53,6 +53,9 @@ import testing ;
[ run libs/function/test/function_ref_cxx98.cpp : : : : ]
[ run libs/function/test/function_ref_portable.cpp : : : : ]
[ run libs/function/test/contains_test.cpp : : : : ]
;
}

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

174
test/contains_test.cpp Normal file
View File

@@ -0,0 +1,174 @@
// 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; }
static void target_test()
{
boost::function0<int> f;
f = &forty_two;
BOOST_TEST(*f.target<int (*)()>() == &forty_two);
BOOST_TEST(!f.target<Seventeen>());
f = Seventeen();
BOOST_TEST(!f.target<int (*)()>());
BOOST_TEST(f.target<Seventeen>());
Seventeen this_seventeen;
f = boost::ref(this_seventeen);
BOOST_TEST(!f.target<int (*)()>());
BOOST_TEST(f.target<Seventeen>());
BOOST_TEST(f.target<Seventeen>() == &this_seventeen);
}
static void equal_test()
{
boost::function0<int> f;
f = &forty_two;
BOOST_TEST(f == &forty_two);
BOOST_TEST(f != ReturnInt(17));
#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_TEST(&forty_two == f);
BOOST_TEST(ReturnInt(17) != f);
#endif
BOOST_TEST(f.contains(&forty_two));
f = ReturnInt(17);
BOOST_TEST(f != &forty_two);
BOOST_TEST(f == ReturnInt(17));
BOOST_TEST(f != ReturnInt(16));
#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_TEST(&forty_two != f);
BOOST_TEST(ReturnInt(17) == f);
BOOST_TEST(ReturnInt(16) != f);
#endif
BOOST_TEST(f.contains(ReturnInt(17)));
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
boost::function<int(void)> g;
g = &forty_two;
BOOST_TEST(g == &forty_two);
BOOST_TEST(g != ReturnInt(17));
# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_TEST(&forty_two == g);
BOOST_TEST(ReturnInt(17) != g);
# endif
g = ReturnInt(17);
BOOST_TEST(g != &forty_two);
BOOST_TEST(g == ReturnInt(17));
BOOST_TEST(g != ReturnInt(16));
# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_TEST(&forty_two != g);
BOOST_TEST(ReturnInt(17) == g);
BOOST_TEST(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_TEST(f == boost::ref(ri));
BOOST_TEST(f == ri);
BOOST_TEST(boost::ref(ri) == f);
BOOST_TEST(!(f != boost::ref(ri)));
BOOST_TEST(!(f != ri));
BOOST_TEST(!(boost::ref(ri) != f));
#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_TEST(ri == f);
BOOST_TEST(!(ri != f));
#endif
// Values equal, references inequal
ReturnInt ri2(17);
BOOST_TEST(f == ri2);
BOOST_TEST(f != boost::ref(ri2));
BOOST_TEST(boost::ref(ri2) != f);
BOOST_TEST(!(f != ri2));
BOOST_TEST(!(f == boost::ref(ri2)));
BOOST_TEST(!(boost::ref(ri2) == f));
#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_TEST(ri2 == f);
BOOST_TEST(!(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_TEST(f == boost::ref(ri));
BOOST_TEST(f == ri);
BOOST_TEST(boost::ref(ri) == f);
BOOST_TEST(!(f != boost::ref(ri)));
BOOST_TEST(!(f != ri));
BOOST_TEST(!(boost::ref(ri) != f));
# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_TEST(ri == f);
BOOST_TEST(!(ri != f));
# endif
// Values equal, references inequal
ReturnInt ri2(17);
BOOST_TEST(f == ri2);
BOOST_TEST(f != boost::ref(ri2));
BOOST_TEST(boost::ref(ri2) != f);
BOOST_TEST(!(f != ri2));
BOOST_TEST(!(f == boost::ref(ri2)));
BOOST_TEST(!(boost::ref(ri2) == f));
# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
BOOST_TEST(ri2 == f);
BOOST_TEST(!(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
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,6 +1,6 @@
// 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
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)