Compare commits

...

39 Commits

Author SHA1 Message Date
659326b45f This commit was manufactured by cvs2svn to create branch
'python-v2-dev'.

[SVN r14785]
2002-08-12 13:35:54 +00:00
893069311a function_base.hpp:
- Use the BOOST_FUNCTION_SILENT_DEPRECATED macro as a signal to turn off all
    "deprecated" warnings


[SVN r14756]
2002-08-09 14:34:23 +00:00
0db4ad9f55 Attempted Borland fix
[SVN r14709]
2002-08-06 14:20:08 +00:00
d59b93384b Report success on Compaq cxx 6.2
[SVN r14697]
2002-08-05 15:07:34 +00:00
e837b20127 Report the sad fate of CodeWarrior
[SVN r14696]
2002-08-05 15:05:57 +00:00
39e2be08cb Don't test allocators if they aren't supported
[SVN r14695]
2002-08-05 15:05:34 +00:00
021063eddf Attempted fix for Compaq CXX 6.2
[SVN r14693]
2002-08-05 13:32:25 +00:00
0ff1daa573 Proper HTML, please
[SVN r14690]
2002-08-05 06:29:07 +00:00
8b734dac5a Added Sun CC to the bad side of the syntax table
[SVN r14689]
2002-08-05 06:24:18 +00:00
5010a0beb0 tutorial.html:
- Use tables to show both preferred/compatible syntaxes
  - Include a table describing which syntax is right for each compiler


[SVN r14687]
2002-08-05 06:20:30 +00:00
39687e1a05 Describe BOOST_FUNCTION_NO_DEPRECATED
[SVN r14686]
2002-08-05 06:19:47 +00:00
688df3d137 function_base.hpp:
- Use <boost/pending/ct_if.hpp>

all:
  - Add BOOST_FUNCTION_NO_DEPRECATED macro hackery to get rid of ALL deprecated
    features


[SVN r14685]
2002-08-05 06:19:17 +00:00
232069aa00 allocator_test.cpp:
- Remove partial specialization-specific code

function_test.cpp:
  - Uses BOOST_FUNCTION_NO_DEPRECATED
  - Use only the new syntax
  - Test the allocator parameter

deprecated_syntax_test.cpp:
  - Test the deprecated syntax


[SVN r14684]
2002-08-05 06:13:32 +00:00
694ebbb301 Use built-in deprecation facilities, when available
[SVN r14677]
2002-08-05 03:08:08 +00:00
837591456f Remove the unused is_not_same
[SVN r14676]
2002-08-05 02:34:02 +00:00
2d8a4b136a Use function_traits in type_traits library
[SVN r14675]
2002-08-05 02:33:26 +00:00
4f5147f96e function.hpp:
- When determining if a type is a function type, don't blindly add a pointer
    but instead use add_pointer


[SVN r14586]
2002-07-24 13:27:49 +00:00
9db8577d16 Removed all of the deprecated parameters and made them variables
[SVN r14578]
2002-07-23 21:57:57 +00:00
2963cb89a8 function_test.cpp: Don't use void() directly because of broken compilers
[SVN r14571]
2002-07-23 13:47:01 +00:00
d62193624e VC6/7 workaround
[SVN r14552]
2002-07-21 11:09:23 +00:00
461e51a592 Expand on the compatibility note
[SVN r14542]
2002-07-19 21:21:56 +00:00
7ad9e2afee Tutorial now describes the new syntax (and the old syntax)
[SVN r14541]
2002-07-19 21:18:01 +00:00
e9ce99dede test/function_n_test.cpp:
test/function_test.cpp:
  - Don't use deprecated functions

index.html:
doc/reference.html:
  - Describe deprecations


[SVN r14540]
2002-07-19 20:45:36 +00:00
3264064074 Removed some cruft
Deprecated the 'set' methods


[SVN r14538]
2002-07-19 20:09:29 +00:00
84bdb40567 Don't test new syntax if partial specialization is unavailable
[SVN r14536]
2002-07-19 19:42:25 +00:00
a0bd17560f Don't fail on compilers without partial specialization (but don't allow the new syntax either)
[SVN r14535]
2002-07-19 19:41:53 +00:00
97f72b7f8b Don't try to use function types inline for those silly compilers that can't handle it (e.g., Borland C++ 5.5.1)
[SVN r14534]
2002-07-19 19:17:14 +00:00
fca8413df6 Support for Borland C++ 5.5.1
[SVN r14533]
2002-07-19 19:16:33 +00:00
fff815d58b allocator_test.cpp:
function_test.cpp:
  - Test out the new function syntax


[SVN r14532]
2002-07-19 18:31:41 +00:00
9e49833a8c function.hpp:
- Support Peter Dimov's rockin' new syntax:
      function<string (int x, double y, float z)> f;


[SVN r14531]
2002-07-19 18:30:48 +00:00
df34714340 Removed 'truth' template, which isn't needed
[SVN r14060]
2002-05-29 17:27:59 +00:00
d50e9729ea Fixed conflicts in 1.28.0 merge
[SVN r13946]
2002-05-16 02:18:29 +00:00
e975d1e0c2 Lambda is now a Boost library
[SVN r13831]
2002-05-13 12:33:19 +00:00
a3e9eb5db2 Removed tabs
[SVN r13812]
2002-05-10 17:54:40 +00:00
57ee7e962a function.hpp:
- Remove default parameters in real_get_function_impl (Fixed Borland C++
    Builder 6)


[SVN r13595]
2002-04-30 20:05:32 +00:00
48943fec83 Removed some unused macros
[SVN r13594]
2002-04-30 19:41:37 +00:00
a0b89d0a30 function_base.hpp:
- Workaround for Sun CC


[SVN r13566]
2002-04-26 17:45:53 +00:00
82226cb9d6 Changed IF to ct_if because IF is sometimes used as a macro (ewww)
[SVN r13420]
2002-04-10 04:10:06 +00:00
28984e4f23 function_base.hpp:
- has_empty_target modified to deal only with function objects, and to not
    require pointers to the function objects.

function_template.hpp:
  - Don't use '&' operation on incoming function objects


[SVN r13318]
2002-03-30 18:45:28 +00:00
9 changed files with 1591 additions and 442 deletions

View File

@ -22,19 +22,19 @@
}; };
// For <i>N</i> in [0, <i>MAX_ARGS</i>] // For <i>N</i> in [0, <i>MAX_ARGS</i>]
<b>template</b>&lt;<b>typename</b> ResultType, <b>template</b>&lt;<b>typename</b> Signature,
<b>typename</b> Arg1, <b>typename</b> Arg1,
<b>typename</b> Arg2, <b>typename</b> Arg2,
<i>...</i> <i>...</i>
<b>typename</b> Arg<i>N</i>, <b>typename</b> Arg<i>N</i>,
<b>typename</b> Policy = empty_function_policy, <b>typename</b> Policy = empty_function_policy, <em>// Deprecated</em>
<b>typename</b> Mixin = empty_function_mixin, <b>typename</b> Mixin = empty_function_mixin, <em>// Deprecated</em>
<b>typename</b> Allocator = std::allocator&lt;function_base&gt; &gt; <b>typename</b> Allocator = std::allocator&lt;function_base&gt; &gt;
<b>class</b> <a href="#functionN">function<i>N</i></a> : <b>public</b> <a href="#function_base">function_base</a>, <b>public</b> Mixin <b>class</b> <a href="#functionN">function<i>N</i></a> : <b>public</b> <a href="#function_base">function_base</a>, <b>public</b> Mixin
{ {
<b>typedef</b> ResultType result_type; <em>// <a href="#novoid">[1]</a></em> <b>typedef</b> ResultType result_type; <em>// <a href="#novoid">[1]</a></em>
<b>typedef</b> Policy policy_type; <b>typedef</b> Policy policy_type; <em>// Deprecated</em>
<b>typedef</b> Mixin mixin_type; <b>typedef</b> Mixin mixin_type; <em>// Deprecated</em>
<b>typedef</b> Allocator allocator_type; <b>typedef</b> Allocator allocator_type;
<b>typedef</b> Arg1 argument_type; <i>// If N == 1</i> <b>typedef</b> Arg1 argument_type; <i>// If N == 1</i>
@ -52,8 +52,8 @@
<a href="#functionN_copy_assn">function<i>N</i><b>&amp;</b> <b>operator</b>=(<b>const</b> function<i>N</i><b>&amp;</b>)</a>; <a href="#functionN_copy_assn">function<i>N</i><b>&amp;</b> <b>operator</b>=(<b>const</b> function<i>N</i><b>&amp;</b>)</a>;
<a href="#functionN_target_assn"><b>template</b>&lt;<b>typename</b> F&gt; function<i>N</i><b>&amp;</b> <b>operator</b>=(F)</a>; <a href="#functionN_target_assn"><b>template</b>&lt;<b>typename</b> F&gt; function<i>N</i><b>&amp;</b> <b>operator</b>=(F)</a>;
<a href="#functionN_target_ref_assn"><b>template</b>&lt;<b>typename</b> F&gt; function<i>N</i><b>&amp;</b> <b>operator</b>=(reference_wrapper&lt;F&gt;)</a>; <a href="#functionN_target_ref_assn"><b>template</b>&lt;<b>typename</b> F&gt; function<i>N</i><b>&amp;</b> <b>operator</b>=(reference_wrapper&lt;F&gt;)</a>;
<a href="#functionN_copy_set"><b>void</b> set(<b>const</b> function<i>N</i><b>&amp;</b>)</a>; <a href="#functionN_copy_set"><b>void</b> set(<b>const</b> function<i>N</i><b>&amp;</b>)</a>; <em>// Deprecated</em>
<a href="#functionN_target_set"><b>template</b>&lt;<b>typename</b> F&gt; <b>void</b> set(F)</a>; <a href="#functionN_target_set"><b>template</b>&lt;<b>typename</b> F&gt; <b>void</b> set(F)</a>; <em>// Deprecated</em>
<a href="#functionN_swap"><b>void</b> swap(function<i>N</i><b>&amp;</b>)</a>; <a href="#functionN_swap"><b>void</b> swap(function<i>N</i><b>&amp;</b>)</a>;
<a href="#functionN_clear"><b>void</b> clear()</a>; <a href="#functionN_clear"><b>void</b> clear()</a>;
@ -66,22 +66,17 @@
<b>typename</b> Arg2, <b>typename</b> Arg2,
<i>...</i> <i>...</i>
<b>typename</b> Arg<i>N</i>, <b>typename</b> Arg<i>N</i>,
<b>typename</b> Policy, <b>typename</b> Policy, <em>// Deprecated</em>
<b>typename</b> Mixin, <b>typename</b> Mixin, <em>// Deprecated</em>
<b>typename</b> Allocator&gt; <b>typename</b> Allocator&gt;
<b>void</b> <a href="#swap_functionN">swap</a>(function<em>N</em>&lt;ResultType, Arg1, Arg2, <i>...</i>, Arg<i>N</i>, Policy, Mixin, Allocator&gt;<b>&amp;</b>, <b>void</b> <a href="#swap_functionN">swap</a>(function<em>N</em>&lt;ResultType, Arg1, Arg2, <i>...</i>, Arg<i>N</i>, Policy, Mixin, Allocator&gt;<b>&amp;</b>,
function<em>N</em>&lt;ResultType, Arg1, Arg2, <i>...</i>, Arg<i>N</i>, Policy, Mixin, Allocator&gt;<b>&amp;</b>); function<em>N</em>&lt;ResultType, Arg1, Arg2, <i>...</i>, Arg<i>N</i>, Policy, Mixin, Allocator&gt;<b>&amp;</b>);
// For any <i>N</i> in [0, <i>MAX_ARGS</i>] // For any <i>N</i> in [0, <i>MAX_ARGS</i>]
<b>template</b>&lt;<b>typename</b> ResultType, <b>template</b>&lt;<b>typename</b> Signature, <em>// Function type: ResultType (Arg1, Arg2, ..., Arg<em>N</em>)</em>
<b>typename</b> Arg1, <b>typename</b> Policy = empty_function_policy, <em>// Deprecated</em>
<b>typename</b> Arg2, <b>typename</b> Mixin = empty_function_mixin, <em>// Deprecated</em>
<i>...</i> <b>typename</b> Allocator = std::allocator&lt;function_base&gt; &gt;
<b>typename</b> Arg<i>N</i>,
<b>typename</b> Arg<i>N+1</i> = <i>implementation-defined</i>,
<b>typename</b> Arg<i>N+2</i> = <i>implementation-defined</i>,
<i>...</i>
<b>typename</b> Arg<i>MAX_ARGS</i> = <i>implementation-defined</i>&gt;
<b>class</b> <a href="#function">function</a> : <b>public</b> <a href="#functionN">function<i>N</i></a>&lt;ResultType, Arg1, Arg2, <i>...</i>, Arg<i>N</i>&gt; <b>class</b> <a href="#function">function</a> : <b>public</b> <a href="#functionN">function<i>N</i></a>&lt;ResultType, Arg1, Arg2, <i>...</i>, Arg<i>N</i>&gt;
{ {
<i>// Construction</i> <i>// Construction</i>
@ -94,18 +89,14 @@
function<b>&amp;</b> <b>operator</b>=(<b>const</b> function<b>&amp;</b>); function<b>&amp;</b> <b>operator</b>=(<b>const</b> function<b>&amp;</b>);
function<b>&amp;</b> <b>operator</b>=(<b>const</b> function<i>N</i>&lt;ResultType, Arg1, Arg2, ..., Arg<i>N</i>&gt;<b>&amp;</b>); function<b>&amp;</b> <b>operator</b>=(<b>const</b> function<i>N</i>&lt;ResultType, Arg1, Arg2, ..., Arg<i>N</i>&gt;<b>&amp;</b>);
<b>template</b>&lt;<b>typename</b> F&gt; function<b>&amp;</b> <b>operator</b>=(F); <b>template</b>&lt;<b>typename</b> F&gt; function<b>&amp;</b> <b>operator</b>=(F);
<b>void</b> set(<b>const</b> function<b>&amp;</b>); <b>void</b> set(<b>const</b> function<b>&amp;</b>); <em>// Deprecated</em>
<b>void</b> set(<b>const</b> function<i>N</i>&lt;ResultType, Arg1, Arg2, ..., Arg<i>N</i>&gt;<b>&amp;</b>); <b>void</b> set(<b>const</b> function<i>N</i>&lt;ResultType, Arg1, Arg2, ..., Arg<i>N</i>&gt;<b>&amp;</b>); <em>// Deprecated</em>
<b>template</b>&lt;<b>typename</b> F&gt; <b>void</b> set(F); <b>template</b>&lt;<b>typename</b> F&gt; <b>void</b> set(F); <em>// Deprecated</em>
}; };
<b>template</b>&lt;<b>typename</b> ResultType, <b>template</b>&lt;<b>typename</b> Signature, <b>typename</b> Policy, <b>typename</b> Mixin, <b>typename</b> Allocator&gt;
<b>typename</b> Arg1, <b>void</b> <a href="#swap_function">swap</a>(function&lt;Signature, Policy, Mixin, Allocator&gt;<b>&amp;</b>,
<b>typename</b> Arg2, function&lt;Signature, Policy, Mixin, Allocator&gt;<b>&amp;</b>);
<i>...</i>
<b>typename</b> Arg<i>MAX_ARGS</i>&gt;
<b>void</b> <a href="#swap_function">swap</a>(function&lt;ResultType, Arg1, Arg2, <i>...</i>, Arg<i>MAX_ARGS</i>&gt;<b>&amp;</b>,
function&lt;ResultType, Arg1, Arg2, <i>...</i>, Arg<i>MAX_ARGS</i>&gt;<b>&amp;</b>);
} }
</pre> </pre>
@ -218,11 +209,13 @@
<p> <a name="functionN_copy_set"><code><b>void</b> set(<b>const</b> function<i>N</i><b>&amp;</b> g);</code></a> <p> <a name="functionN_copy_set"><code><b>void</b> set(<b>const</b> function<i>N</i><b>&amp;</b> g);</code></a>
<ul> <ul>
<li><b>Effects</b>: <code><a href="#functionN_copy_assn">*this = g</a></code>.</li> <li><b>Effects</b>: <code><a href="#functionN_copy_assn">*this = g</a></code>.</li>
<li><b>Note</b>: This function is deprecated and will be removed in future versions of Boost.Function. Please use the assignment operator instead.</li>
</ul> </ul>
<p> <a name="functionN_target_set"><code><b>template</b>&lt;<b>typename</b> F&gt; <b>void</b> set(F g);</code></a> <p> <a name="functionN_target_set"><code><b>template</b>&lt;<b>typename</b> F&gt; <b>void</b> set(F g);</code></a>
<ul> <ul>
<li><b>Effects</b>: <code><a href="#functionN_target_assn">*this = g</a></code>.</li> <li><b>Effects</b>: <code><a href="#functionN_target_assn">*this = g</a></code>.</li>
<li><b>Note</b>: This function is deprecated and will be removed in future versions of Boost.Function. Please use the assignment operator instead.</li>
</ul> </ul>
<p> <a name="functionN_swap"><code><b>void</b> swap(function<i>N</i><b>&amp;</b> g);</code></a> <p> <a name="functionN_swap"><code><b>void</b> swap(function<i>N</i><b>&amp;</b> g);</code></a>
@ -248,6 +241,7 @@
<li><code>policy.postcall(this);</code></li> <li><code>policy.postcall(this);</code></li>
</ol> </ol>
<li><b>Returns</b>: the value returned by <i>target</i>.</li> <li><b>Returns</b>: the value returned by <i>target</i>.</li>
<li><b>Note</b>: invocation policies have been deprecated and will be removed in a later release.</li>
</ul> </ul>
<h2><a name="function">Class template <code>function</code></a></h2> <h2><a name="function">Class template <code>function</code></a></h2>
@ -263,8 +257,8 @@
<b>typename</b> Arg2, <b>typename</b> Arg2,
<i>...</i> <i>...</i>
<b>typename</b> Arg<i>N</i>, <b>typename</b> Arg<i>N</i>,
<b>typename</b> Policy, <b>typename</b> Policy, <em>// Deprecated</em>
<b>typename</b> Mixin, <b>typename</b> Mixin, <em>// Deprecated</em>
<b>typename</b> Allocator&gt; <b>typename</b> Allocator&gt;
<b>void</b> <a name="swap_functionN">swap</a>(function<i>N</i>&lt;ResultType, Arg1, Arg2, <i>...</i>, Arg<i>N</i>, Policy, Mixin, Allocator&gt;<b>&amp;</b> f, <b>void</b> <a name="swap_functionN">swap</a>(function<i>N</i>&lt;ResultType, Arg1, Arg2, <i>...</i>, Arg<i>N</i>, Policy, Mixin, Allocator&gt;<b>&amp;</b> f,
function<i>N</i>&lt;ResultType, Arg1, Arg2, <i>...</i>, Arg<i>N</i>, Policy, Mixin, Allocator&gt;<b>&amp;</b> g); function<i>N</i>&lt;ResultType, Arg1, Arg2, <i>...</i>, Arg<i>N</i>, Policy, Mixin, Allocator&gt;<b>&amp;</b> g);
@ -275,13 +269,9 @@
<p> <p>
<pre> <pre>
<b>template</b>&lt;<b>typename</b> ResultType, <b>template</b>&lt;<b>typename</b> Signature, <b>typename</b> Policy, <b>typename</b> Mixin, <b>typename</b> Allocator&gt;
<b>typename</b> Arg1, <b>void</b> <a name="swap_function">swap</a>(function&lt;Signature, Policy, Mixin, Allocator&gt;<b>&amp;</b> f,
<b>typename</b> Arg2, function&lt;Signature, Policy, Mixin, Allocator&gt;<b>&amp;</b> g);
<i>...</i>
<b>typename</b> Arg<i>MAX_ARGS</i>&gt;
<b>void</b> <a name="swap_function">swap</a>(function&lt;ResultType, Arg1, Arg2, <i>...</i>, Arg<i>MAX_ARGS</i>&gt;<b>&amp;</b> f,
function&lt;ResultType, Arg1, Arg2, <i>...</i>, Arg<i>MAX_ARGS</i>&gt;<b>&amp;</b> g);
</pre> </pre>
<ul> <ul>
<li><b>Effects</b>: <code>f.<a href="#functionN_swap">swap</a>(g);</code></li> <li><b>Effects</b>: <code>f.<a href="#functionN_swap">swap</a>(g);</code></li>
@ -293,7 +283,7 @@
<address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address> <address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address>
<!-- Created: Fri Jul 13 10:57:20 EDT 2001 --> <!-- Created: Fri Jul 13 10:57:20 EDT 2001 -->
<!-- hhmts start --> <!-- hhmts start -->
Last modified: Thu Jan 31 21:55:35 EST 2002 Last modified: Fri Jul 19 16:40:00 EDT 2002
<!-- hhmts end --> <!-- hhmts end -->
</body> </body>
</html> </html>

View File

@ -8,14 +8,58 @@
<h1><IMG SRC="../../../c++boost.gif" WIDTH="276" HEIGHT="86">Boost.Function Tutorial</h1> <h1><IMG SRC="../../../c++boost.gif" WIDTH="276" HEIGHT="86">Boost.Function Tutorial</h1>
<h2><a name="usage">Basic usage</a></h2> <p> Boost.Function has two syntactical forms: the preferred form and the compatibility form. The preferred form fits more closely with the C++ language and reduces the number of separate template parameters that need to be considered, often improving readability; however, the preferred form is not supported on all platforms due to compiler bugs. The compatible form will work on all compilers supported by Boost.Function. Consult the table below to determine which syntactic form to use for your compiler.
<p> A function wrapper is defined simply by instantiating the <code>function</code> class template with the desired return type and argument types. Any number of arguments may be supplied, up to some implementation-defined limit (10 is the default maximum). The following declares a function object wrapper <code>f</code> that takes two <code>int</code> parameters and returns a <code>float</code>:
<pre> <center>
boost::<a href="reference.html#function">function</a>&lt;float, int, int&gt; f; <table border=1 cellspacing=1>
</pre> <tr><th bgcolor="#008080">Preferred Syntax</th><th bgcolor="#008080">Compatible Syntax</th></tr>
<tr>
<td>
<ul>
<li>GNU C++ 2.95.x, 3.0.x, 3.1.x</li>
<li>Comeau C++ 4.2.45.2</li>
<li>SGI MIPSpro 7.3.0</li>
<li>Intel C++ 5.0, 6.0</li>
<li>Compaq's cxx 6.2</li>
</ul>
</td>
<td>
<ul>
<li>Microsoft Visual C++ 6.0, 7.0</li>
<li>Borland C++ 5.5.1</li>
<li>Sun WorkShop 6 update 2 C++ 5.3</li>
<li>Metrowerks CodeWarrior 8.1</li>
</ul>
</td>
</tr>
</table>
</center>
<p> If your compiler does not appear in this list, please try the preferred syntax and report your results to the Boost list so that we can keep this table up-to-date.
<a name="preferred"><h2>Basic Usage</h2></a>
<p> A function wrapper is defined simply by instantiating the <code>function</code> class template with the desired return type and argument types, formulated as a C++ function type. Any number of arguments may be supplied, up to some implementation-defined limit (10 is the default maximum). The following declares a function object wrapper <code>f</code> that takes two <code>int</code> parameters and returns a <code>float</code>:
<center>
<table border=1 cellspacing=1>
<tr><th bgcolor="#008080">Preferred Syntax</th><th bgcolor="#008080">Compatible Syntax</th></tr>
<tr>
<td>
<pre>
boost::<a href="reference.html#function">function</a>&lt;float (int x, int y)&gt; f;
</pre>
</td>
<td>
<pre>
boost::<a href="reference.html#functionN">function2</a>&lt;float, int, int&gt; f;
</pre>
</td>
</tr>
</table>
</center>
<p> By default, function object wrappers are empty, so we can create a <p> By default, function object wrappers are empty, so we can create a
function object to assign to <code>f</code>: function object to assign to <code>f</code>:
<pre> <pre>
struct int_div { struct int_div {
float operator()(int x, int y) const { return ((float)x)/y; }; float operator()(int x, int y) const { return ((float)x)/y; };
@ -27,31 +71,47 @@ f = int_div();
<p> Now we can use <code>f</code> to execute the underlying function object <p> Now we can use <code>f</code> to execute the underlying function object
<code>int_div</code>: <code>int_div</code>:
<pre> <pre>
std::cout << f(5, 3) << std::endl; std::cout &lt;&lt; f(5, 3) &gt;&gt; std::endl;
</pre> </pre>
<p> We are free to assign any compatible function object to <code>f</code>. If <code>int_div</code> had been declared to take two <code>long</code> operands, <p> We are free to assign any compatible function object to <code>f</code>. If <code>int_div</code> had been declared to take two <code>long</code> operands,
the implicit conversions would have been applied to the arguments without any user interference. The only limit on the types of arguments is that they be CopyConstructible, so we can even use references and arrays: the implicit conversions would have been applied to the arguments without any user interference. The only limit on the types of arguments is that they be CopyConstructible, so we can even use references and arrays:
<pre> <center>
boost::function&lt;void, int[], int, int&, float&&gt; sum_avg; <table border=1 cellspacing=1>
<tr><th bgcolor="#008080">Preferred Syntax</th><th bgcolor="#008080">Compatible Syntax</th></tr>
<tr>
<td>
<pre>
boost::function&lt;void (int values[], int n, int&amp; sum, float&amp; avg)&gt; sum_avg;
</pre>
</td>
<td>
<pre>
boost::function4&lt;void, int[], int, int&amp;, float&gt; sum_avg;
</pre>
</td>
</tr>
</table>
</center>
<pre>
void do_sum_avg(int values[], int n, int& sum, float&amp; avg) void do_sum_avg(int values[], int n, int& sum, float&amp; avg)
{ {
sum = 0; sum = 0;
for (int i = 0; i < n; i++) for (int i = 0; i &lt; n; i++)
sum += values[i]; sum += values[i];
avg = (float)sum / n; avg = (float)sum / n;
} }
sum_avg = &do_sum_avg; sum_avg = &amp;do_sum_avg;
</pre> </pre>
<p> Invoking a function object wrapper that does not actually contain a function object is a precondition violation, much like trying to call through a null function pointer. We can check for an empty function object wrapper by querying its <code><a href="reference.html#empty">empty</a>()</code> method or, more succinctly, by using it in a boolean context: if it evaluates true, it contains a function object target, i.e., <p> Invoking a function object wrapper that does not actually contain a function object is a precondition violation, much like trying to call through a null function pointer. We can check for an empty function object wrapper by querying its <code><a href="reference.html#empty">empty</a>()</code> method or, more succinctly, by using it in a boolean context: if it evaluates true, it contains a function object target, i.e.,
<pre> <pre>
if (f) if (f)
std::cout << f(5, 3) << std::endl; std::cout &lt;&lt; f(5, 3) &lt;&lt; std::endl;
else else
std::cout << "f has no target, so it is unsafe to call" << std::endl; std::cout &lt;&lt; "f has no target, so it is unsafe to call" &lt;&lt; std::endl;
</pre> </pre>
<p> We can clear out a function target using the <code><a href="reference.html#functionN_clear">clear</a>()</code> member function. <p> We can clear out a function target using the <code><a href="reference.html#functionN_clear">clear</a>()</code> member function.
@ -69,34 +129,82 @@ else
<a name="member_func"> <a name="member_func">
<p> In many systems, callbacks often call to member functions of a particular <p> In many systems, callbacks often call to member functions of a particular
object. This is often referred to as "argument binding", and is beyond the scope of Boost.Function. The use of member functions directly, however, is supported, so the following code is valid: object. This is often referred to as "argument binding", and is beyond the scope of Boost.Function. The use of member functions directly, however, is supported, so the following code is valid:
<pre>
struct X {
int foo(int);
};
boost::function&lt;int, X*, int&gt; f; <center>
f = &amp;X::foo; <table border=1 cellspacing=1>
<tr><th bgcolor="#008080">Preferred Syntax</th><th bgcolor="#008080">Compatible Syntax</th></tr>
<tr>
<td>
<pre>
struct X {
int foo(int);
};
boost::function&lt;int (X*, int)&gt; f;
f = &amp;X::foo;
X x; X x;
f(&amp;x, 5); f(&amp;x, 5);
</pre> </pre>
</td>
<td>
<pre>
struct X {
int foo(int);
};
boost::function2&lt;int, X*, int&gt; f;
f = &amp;X::foo;
X x;
f(&amp;x, 5);
</pre>
</td>
</tr>
</table>
</center>
<p> Several libraries exist that support argument binding. Three such libraries are summarized below: <p> Several libraries exist that support argument binding. Three such libraries are summarized below:
<ul> <ul>
<li> <a href="../../bind/bind.html">Boost.Bind</a>. This library allows binding of arguments for any function object. It is lightweight and very portable.</li> <li> <a href="../../bind/bind.html">Boost.Bind</a>. This library allows binding of arguments for any function object. It is lightweight and very portable.</li>
<li> The C++ Standard library. Using <code>std::bind1st</code> and <code>std::mem_fun</code> together one can bind the object of a pointer-to-member function for use with Boost.Function: <li> The C++ Standard library. Using <code>std::bind1st</code> and <code>std::mem_fun</code> together one can bind the object of a pointer-to-member function for use with Boost.Function:
<center>
<table border=1 cellspacing=1>
<tr><th bgcolor="#008080">Preferred Syntax</th><th bgcolor="#008080">Compatible Syntax</th></tr>
<tr>
<td>
<pre> <pre>
struct X { struct X {
int foo(int); int foo(int);
}; };
boost::function&lt;int, int&gt; f; boost::function&lt;int (int)&gt; f;
X x; X x;
f = std::bind1st(std::mem_fun(&X::foo), &x); f = std::bind1st(std::mem_fun(&amp;X::foo), &amp;x);
f(5); // Call x.foo(5)</pre></li> f(5); // Call x.foo(5)</pre>
</td>
<td>
<pre>
struct X {
int foo(int);
};
<li><a href="http://lambda.cs.utu.fi/">The Lambda library</a>. This library provides a powerful composition mechanism to construct function objects that uses very natural C++ syntax. Lambda requires a compiler that is reasonably conformant to the C++ standard. Note that it is not a Boost library.</li> boost::function1&lt;int, int&gt; f;
X x;
f = std::bind1st(std::mem_fun(&amp;X::foo), &amp;x);
f(5); // Call x.foo(5)</pre>
</td>
</tr>
</table>
</center>
</li>
<li><a href="../../lambda/doc/index.html">The Boost.Lambda library</a>. This library provides a powerful composition mechanism to construct function objects that uses very natural C++ syntax. Lambda requires a compiler that is reasonably conformant to the C++ standard. </li>
</ul> </ul>
<h3>References to Functions</h3> <h3>References to Functions</h3>
@ -107,14 +215,31 @@ function object. This is done using the <a
href="../../bind/ref.html"><code>ref</code></a> and <a href="../../bind/ref.html"><code>ref</code></a> and <a
href="../../bind/ref.html"><code>cref</code></a> functions to wrap a href="../../bind/ref.html"><code>cref</code></a> functions to wrap a
reference to a function object: reference to a function object:
<center>
<table border=1 cellspacing=1>
<tr><th bgcolor="#008080">Preferred Syntax</th><th bgcolor="#008080">Compatible Syntax</th></tr>
<tr>
<td>
<pre> <pre>
stateful_type a_function_object; stateful_type a_function_object;
boost::function&lt;int, int&gt; f; boost::function&lt;int (int)&gt; f;
f = ref(a_function_object); f = ref(a_function_object);
boost::function&lt;int, int&gt; f2(f); boost::function&lt;int (int)&gt; f2(f);
</pre> </pre>
</td>
<td>
<pre>
stateful_type a_function_object;
boost::function1&lt;int, int&gt; f;
f = ref(a_function_object);
boost::function1&lt;int, int&gt; f2(f);
</pre>
</td>
</tr>
</table>
</center>
Here, <code>f</code> will not make a copy of Here, <code>f</code> will not make a copy of
<code>a_function_object</code>, nor will <code>f2</code> when it is <code>a_function_object</code>, nor will <code>f2</code> when it is
@ -123,83 +248,11 @@ targeted to <code>f</code>'s reference to
function objects, Boost.Function will not throw exceptions during function objects, Boost.Function will not throw exceptions during
assignment or construction. assignment or construction.
<h2><a name="family">The <code>function</code> family</a></h2>
<p> The header &lt;<a href="../../../boost/function.hpp">boost/function.hpp</a>&gt; defines the primary entry point to the function object wrappers, the class template <code>boost::function</code>. This class template is essentially a thin wrapper around a set of similar numbered function object wrappers, <code>boost::function0</code>, <code>boost::function1</code>, etc., where the number indicates the number of arguments passed to the function object target. The declaration of <code>f</code> above could also be written as:
<pre>
boost::function2&lt;float, int, int&gt; f;
</pre>
<p> The numbered class templates contain most of the implementation and are each distinct class templates. They may be helpful if used in shared libraries, where the number of arguments supported by Boost.Function may change between revisions. Additionally, some compilers (e.g., Microsoft Visual C++ 6.0) have been known to be incapable of compiling <code>boost::function</code> in some instances but are able to handle the numbered variants.
<h2><a name="advanced">Advanced usage</a></h2>
<p> The <code>boost::function</code> family supports additional customization by means of policies, mixins, and allocators. The specific usage of each of these will be explained in later sections, but they share a common problem: how to replace each default with your own version.
<p> With <code>boost::function</code> it is not so clear, because support for an arbitrary number of parameters means that it is impossible to specify just the last parameter, but not 5 of the parameters in between. Therefore, <code>boost::function</code> doubles as a generative interface for the underlying numbered class templates that uses named template parameters. For instance, to specify both a policy and an allocator for a function object wrapper <code>f</code> taking an <code>int</code> and returning an <code>int</code>, use:
<pre>
function&lt;int, int&gt;::policy&lt;MyPolicy&gt;::allocator&lt;MyAllocator&gt;::type f;
</pre>
<p> The named template parameters <code>policy</code>, <code>mixin</code> and <code>allocator</code> each take one template parameter (the replacement class) and may be nested as above to generate a function object wrapper. The <code>::type</code> at the end accesses the actual type that fits the given properties.
<h3><a name="policies">Policies</a></h3>
<p> Policies define what happens directly before and directly after an invocation of a function object target is made. A policy must have two member functions, <code>precall</code> and <code>postcall</code>, each of which must be able to accept a <code>const</code> function object wrapper pointer. The following policy will print "before" prior to execution and "after" afterwards:
<pre>
struct print_policy {
void precall(const boost::function_base*) { std::cout << "before"; }
void postcall(const boost::function_base*) { std::cout << "after"; }
};
</pre>
<p> A new instance of the policy class will be created prior to calling the function object target and will be preserved until after the call has returned. Therefore, for any invocation the <code>precall</code> and <code>postcall</code> will be executed on the same policy class instance; however, policy class instances will not be kept between target invocations.
<p> Policies are further <a href="../../../more/generic_programming.html#policy">described</a> in the Boost discussion on <a href="../../../more/generic_programming.html">generic programming techniques</a>.
<h3><a name="mixins">Mixins</a></h3>
<p> The function object wrappers allow any class to be "mixed in" as a base class. This allows extra members and/or functionality to be included by the user. This can be used, for instance, to overcome the limitations of policies by storing data between invocations in a base class instead of in a <code>static</code> member of a policy class.
<h3><a name="allocators">Allocators</a></h3>
<p> The function object wrappers allow the user to specify a new allocator to handle the cloning of function object targets (when the wrappers are copied). The allocators used are the same as the C++ standard library allocators. The wrappers assume the allocators are stateless, and will create a new instance each time they are used (because they are rebound very often). This shares the semantics of most standard library implementations, and is explicitly allowed by the C++ standard.
<h3><a name="synchronizing">Example: Synchronized callbacks</a></h3>
<p> Synchronization of callbacks in a multithreaded environment is extremely important. Using mixins and policies, a Boost.Function object may implement its own synchronization policy that ensures that only one thread can be in the callback function at any given point in time.
<p> We will use the prototype Boost.Threads library for its <code>recursive_mutex</code>. Since the mutex is on a per-callback basis, we will add a mutex to the <code>boost::function</code> by mixin it in with this mixin class:
<pre>
class SynchronizedMixin {
mutable boost::recursive_mutex mutex;
};
</pre>
<p> Next, we create a policy that obtains a lock before the target is called (via the <code>precall</code> function) and releases the lock after the target has been called (via the <code>postcall</code> function):
<pre>
class SynchronizedPolicy {
std::auto_ptr&lt;boost::recursive_mutex::lock&gt; lock;
void precall(const SynchronizedMixin* f)
{
lock.reset(new boost::recursive_mutex::lock(f->mutex));
}
void postcall(const SynchronizedMixin* f)
{
lock.reset();
}
};
</pre>
<p>The use of <code>std::auto_ptr</code> ensures that the lock will be destroyed (and therefore released) if an exception is thrown by the target function. Now we can use the policy and mixin together to create a synchronized callback:
<pre>
boost::function2&lt;float, int, int, SynchronizedPolicy, SynchronizedMixin&gt; f;
</pre>
<hr> <hr>
<address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address> <address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address>
<!-- Created: Fri Jul 13 12:47:11 EDT 2001 --> <!-- Created: Fri Jul 13 12:47:11 EDT 2001 -->
<!-- hhmts start --> <!-- hhmts start -->
Last modified: Fri Dec 14 19:58:14 EST 2001 Last modified: Mon Aug 5 11:07:17 EDT 2002
<!-- hhmts end --> <!-- hhmts end -->
</body> </body>
</html> </html>

View File

@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu) // Copyright (C) 2001, 2002 Doug 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.
@ -20,6 +20,10 @@
#define BOOST_FUNCTION_HPP #define BOOST_FUNCTION_HPP
#include <boost/function/function_base.hpp> #include <boost/function/function_base.hpp>
#include <boost/type_traits/function_traits.hpp>
#include <boost/type_traits/same_traits.hpp>
#include <boost/type_traits/transform_traits.hpp>
#include <boost/type_traits/ice.hpp>
#include <boost/function/function0.hpp> #include <boost/function/function0.hpp>
#include <boost/function/function1.hpp> #include <boost/function/function1.hpp>
#include <boost/function/function2.hpp> #include <boost/function/function2.hpp>
@ -32,6 +36,11 @@
#include <boost/function/function9.hpp> #include <boost/function/function9.hpp>
#include <boost/function/function10.hpp> #include <boost/function/function10.hpp>
// Don't compile any of this code if we've asked not to include the deprecated
// syntax and we don't have partial specialization, because none of this code
// can work.
#if !defined (BOOST_FUNCTION_NO_DEPRECATED) || !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace boost { namespace boost {
namespace detail { namespace detail {
namespace function { namespace function {
@ -53,13 +62,19 @@ namespace boost {
typename T8, typename T8,
typename T9, typename T9,
typename T10, typename T10,
typename Policy = empty_function_policy, #ifndef BOOST_FUNCTION_NO_DEPRECATED
typename Mixin = empty_function_mixin, typename Policy,
typename Allocator = std::allocator<function_base> typename Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename Allocator
> >
struct params struct params
{ {
typedef function0<R, Policy, Mixin, Allocator> type; typedef function0<R,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
Policy, Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
Allocator> type;
}; };
}; };
@ -78,13 +93,19 @@ namespace boost {
typename T8, typename T8,
typename T9, typename T9,
typename T10, typename T10,
typename Policy = empty_function_policy, #ifndef BOOST_FUNCTION_NO_DEPRECATED
typename Mixin = empty_function_mixin, typename Policy,
typename Allocator = std::allocator<function_base> typename Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename Allocator
> >
struct params struct params
{ {
typedef function1<R, T1, Policy, Mixin, Allocator> type; typedef function1<R, T1,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
Policy, Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
Allocator> type;
}; };
}; };
@ -103,13 +124,19 @@ namespace boost {
typename T8, typename T8,
typename T9, typename T9,
typename T10, typename T10,
typename Policy = empty_function_policy, #ifndef BOOST_FUNCTION_NO_DEPRECATED
typename Mixin = empty_function_mixin, typename Policy,
typename Allocator = std::allocator<function_base> typename Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename Allocator
> >
struct params struct params
{ {
typedef function2<R, T1, T2, Policy, Mixin, Allocator> type; typedef function2<R, T1, T2,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
Policy, Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
Allocator> type;
}; };
}; };
@ -128,13 +155,19 @@ namespace boost {
typename T8, typename T8,
typename T9, typename T9,
typename T10, typename T10,
typename Policy = empty_function_policy, #ifndef BOOST_FUNCTION_NO_DEPRECATED
typename Mixin = empty_function_mixin, typename Policy,
typename Allocator = std::allocator<function_base> typename Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename Allocator
> >
struct params struct params
{ {
typedef function3<R, T1, T2, T3, Policy, Mixin, Allocator> type; typedef function3<R, T1, T2, T3,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
Policy, Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
Allocator> type;
}; };
}; };
@ -153,13 +186,19 @@ namespace boost {
typename T8, typename T8,
typename T9, typename T9,
typename T10, typename T10,
typename Policy = empty_function_policy, #ifndef BOOST_FUNCTION_NO_DEPRECATED
typename Mixin = empty_function_mixin, typename Policy,
typename Allocator = std::allocator<function_base> typename Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename Allocator
> >
struct params struct params
{ {
typedef function4<R, T1, T2, T3, T4, Policy, Mixin, Allocator> type; typedef function4<R, T1, T2, T3, T4,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
Policy, Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
Allocator> type;
}; };
}; };
@ -178,13 +217,19 @@ namespace boost {
typename T8, typename T8,
typename T9, typename T9,
typename T10, typename T10,
typename Policy = empty_function_policy, #ifndef BOOST_FUNCTION_NO_DEPRECATED
typename Mixin = empty_function_mixin, typename Policy,
typename Allocator = std::allocator<function_base> typename Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename Allocator
> >
struct params struct params
{ {
typedef function5<R, T1, T2, T3, T4, T5, Policy, Mixin, Allocator> typedef function5<R, T1, T2, T3, T4, T5,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
Policy, Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
Allocator>
type; type;
}; };
}; };
@ -204,13 +249,19 @@ namespace boost {
typename T8, typename T8,
typename T9, typename T9,
typename T10, typename T10,
typename Policy = empty_function_policy, #ifndef BOOST_FUNCTION_NO_DEPRECATED
typename Mixin = empty_function_mixin, typename Policy,
typename Allocator = std::allocator<function_base> typename Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename Allocator
> >
struct params struct params
{ {
typedef function6<R, T1, T2, T3, T4, T5, T6, Policy, Mixin, Allocator> typedef function6<R, T1, T2, T3, T4, T5, T6,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
Policy, Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
Allocator>
type; type;
}; };
}; };
@ -230,13 +281,18 @@ namespace boost {
typename T8, typename T8,
typename T9, typename T9,
typename T10, typename T10,
typename Policy = empty_function_policy, #ifndef BOOST_FUNCTION_NO_DEPRECATED
typename Mixin = empty_function_mixin, typename Policy,
typename Allocator = std::allocator<function_base> typename Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename Allocator
> >
struct params struct params
{ {
typedef function7<R, T1, T2, T3, T4, T5, T6, T7, Policy, Mixin, typedef function7<R, T1, T2, T3, T4, T5, T6, T7,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
Policy, Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
Allocator> type; Allocator> type;
}; };
}; };
@ -256,13 +312,18 @@ namespace boost {
typename T8, typename T8,
typename T9, typename T9,
typename T10, typename T10,
typename Policy = empty_function_policy, #ifndef BOOST_FUNCTION_NO_DEPRECATED
typename Mixin = empty_function_mixin, typename Policy,
typename Allocator = std::allocator<function_base> typename Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename Allocator
> >
struct params struct params
{ {
typedef function8<R, T1, T2, T3, T4, T5, T6, T7, T8, Policy, Mixin, typedef function8<R, T1, T2, T3, T4, T5, T6, T7, T8,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
Policy, Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
Allocator> type; Allocator> type;
}; };
}; };
@ -282,14 +343,19 @@ namespace boost {
typename T8, typename T8,
typename T9, typename T9,
typename T10, typename T10,
typename Policy = empty_function_policy, #ifndef BOOST_FUNCTION_NO_DEPRECATED
typename Mixin = empty_function_mixin, typename Policy,
typename Allocator = std::allocator<function_base> typename Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename Allocator
> >
struct params struct params
{ {
typedef function9<R, T1, T2, T3, T4, T5, T6, T7, T8, T9, Policy, typedef function9<R, T1, T2, T3, T4, T5, T6, T7, T8, T9,
Mixin, Allocator> type; #ifndef BOOST_FUNCTION_NO_DEPRECATED
Policy, Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
Allocator> type;
}; };
}; };
@ -308,65 +374,366 @@ namespace boost {
typename T8, typename T8,
typename T9, typename T9,
typename T10, typename T10,
typename Policy = empty_function_policy, #ifndef BOOST_FUNCTION_NO_DEPRECATED
typename Mixin = empty_function_mixin, typename Policy,
typename Allocator = std::allocator<function_base> typename Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename Allocator
> >
struct params struct params
{ {
typedef function10<R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, typedef function10<R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
Policy, Mixin, Allocator> type; #ifndef BOOST_FUNCTION_NO_DEPRECATED
Policy, Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
Allocator> type;
}; };
}; };
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<bool GetIt, typename Traits>
struct get_arg1_type
{
typedef unusable type;
};
template<typename Traits>
struct get_arg1_type<true, Traits>
{
typedef typename Traits::arg1_type type;
};
template<bool GetIt, typename Traits>
struct get_arg2_type
{
typedef unusable type;
};
template<typename Traits>
struct get_arg2_type<true, Traits>
{
typedef typename Traits::arg2_type type;
};
template<bool GetIt, typename Traits>
struct get_arg3_type
{
typedef unusable type;
};
template<typename Traits>
struct get_arg3_type<true, Traits>
{
typedef typename Traits::arg3_type type;
};
template<bool GetIt, typename Traits>
struct get_arg4_type
{
typedef unusable type;
};
template<typename Traits>
struct get_arg4_type<true, Traits>
{
typedef typename Traits::arg4_type type;
};
template<bool GetIt, typename Traits>
struct get_arg5_type
{
typedef unusable type;
};
template<typename Traits>
struct get_arg5_type<true, Traits>
{
typedef typename Traits::arg5_type type;
};
template<bool GetIt, typename Traits>
struct get_arg6_type
{
typedef unusable type;
};
template<typename Traits>
struct get_arg6_type<true, Traits>
{
typedef typename Traits::arg6_type type;
};
template<bool GetIt, typename Traits>
struct get_arg7_type
{
typedef unusable type;
};
template<typename Traits>
struct get_arg7_type<true, Traits>
{
typedef typename Traits::arg7_type type;
};
template<bool GetIt, typename Traits>
struct get_arg8_type
{
typedef unusable type;
};
template<typename Traits>
struct get_arg8_type<true, Traits>
{
typedef typename Traits::arg8_type type;
};
template<bool GetIt, typename Traits>
struct get_arg9_type
{
typedef unusable type;
};
template<typename Traits>
struct get_arg9_type<true, Traits>
{
typedef typename Traits::arg9_type type;
};
template<bool GetIt, typename Traits>
struct get_arg10_type
{
typedef unusable type;
};
template<typename Traits>
struct get_arg10_type<true, Traits>
{
typedef typename Traits::arg10_type type;
};
template<int X, int Y>
struct gte
{
BOOST_STATIC_CONSTANT(bool, value = (X >= Y));
};
template<bool IsFunction,
typename InR,
typename InT1,
typename InT2,
typename InT3,
typename InT4,
typename InT5,
typename InT6,
typename InT7,
typename InT8,
typename InT9,
typename InT10,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
typename InPolicy,
typename InMixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename InAllocator>
struct maybe_decode_function_args
{
typedef function_traits<InR> traits;
typedef typename traits::result_type R;
typedef typename get_arg1_type<(gte<(traits::arity), 1>::value),
traits>::type T1;
typedef typename get_arg2_type<(gte<(traits::arity), 2>::value),
traits>::type T2;
typedef typename get_arg3_type<(gte<(traits::arity), 3>::value),
traits>::type T3;
typedef typename get_arg4_type<(gte<(traits::arity), 4>::value),
traits>::type T4;
typedef typename get_arg5_type<(gte<(traits::arity), 5>::value),
traits>::type T5;
typedef typename get_arg6_type<(gte<(traits::arity), 6>::value),
traits>::type T6;
typedef typename get_arg7_type<(gte<(traits::arity), 7>::value),
traits>::type T7;
typedef typename get_arg8_type<(gte<(traits::arity), 8>::value),
traits>::type T8;
typedef typename get_arg9_type<(gte<(traits::arity), 9>::value),
traits>::type T9;
typedef typename get_arg10_type<(gte<(traits::arity), 10>::value),
traits>::type T10;
#ifndef BOOST_FUNCTION_NO_DEPRECATED
typedef typename ct_if<(is_same<InT1, unusable>::value),
empty_function_policy,
InT1>::type Policy;
typedef typename ct_if<(is_same<InT2, unusable>::value),
empty_function_mixin,
InT2>::type Mixin;
typedef typename ct_if<(is_same<InT3, unusable>::value),
std::allocator<function_base>,
InT3>::type Allocator;
#else
typedef typename ct_if<(is_same<InT1, unusable>::value),
std::allocator<function_base>,
InT1>::type Allocator;
#endif // BOOST_FUNCTION_NO_DEPRECATED
};
#ifndef BOOST_FUNCTION_NO_DEPRECATED
template<typename InR,
typename InT1,
typename InT2,
typename InT3,
typename InT4,
typename InT5,
typename InT6,
typename InT7,
typename InT8,
typename InT9,
typename InT10,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
typename InPolicy,
typename InMixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename InAllocator>
struct maybe_decode_function_args<false, InR, InT1, InT2, InT3, InT4,
InT5, InT6, InT7, InT8, InT9, InT10,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
InPolicy, InMixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
InAllocator>
{
// Not a function, so just map the types directly
typedef InR R;
typedef InT1 T1;
typedef InT2 T2;
typedef InT3 T3;
typedef InT4 T4;
typedef InT5 T5;
typedef InT6 T6;
typedef InT7 T7;
typedef InT8 T8;
typedef InT9 T9;
typedef InT10 T10;
#ifndef BOOST_FUNCTION_NO_DEPRECATED
typedef InPolicy Policy;
typedef InMixin Mixin;
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typedef InAllocator Allocator;
};
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
#endif // ndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template< template<
typename R, typename InR,
typename T1, typename InT1,
typename T2, typename InT2,
typename T3, typename InT3,
typename T4, typename InT4,
typename T5, typename InT5,
typename T6, typename InT6,
typename T7, typename InT7,
typename T8, typename InT8,
typename T9, typename InT9,
typename T10, typename InT10,
typename Policy = empty_function_policy, typename InPolicy = empty_function_policy,
typename Mixin = empty_function_mixin, typename InMixin = empty_function_mixin,
typename Allocator = std::allocator<function_base> typename InAllocator = std::allocator<function_base>
> >
struct get_function_impl struct get_function_impl
{ {
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef maybe_decode_function_args<(is_function<InR>::value),
InR, InT1, InT2, InT3, InT4, InT5,
InT6, InT7, InT8, InT9, InT10,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
InPolicy, InMixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
InAllocator> decoder;
typedef typename decoder::R R;
typedef typename decoder::T1 T1;
typedef typename decoder::T2 T2;
typedef typename decoder::T3 T3;
typedef typename decoder::T4 T4;
typedef typename decoder::T5 T5;
typedef typename decoder::T6 T6;
typedef typename decoder::T7 T7;
typedef typename decoder::T8 T8;
typedef typename decoder::T9 T9;
typedef typename decoder::T10 T10;
#ifndef BOOST_FUNCTION_NO_DEPRECATED
typedef typename decoder::Policy Policy;
typedef typename decoder::Mixin Mixin;
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typedef typename decoder::Allocator Allocator;
#else
typedef InR R;
typedef InT1 T1;
typedef InT2 T2;
typedef InT3 T3;
typedef InT4 T4;
typedef InT5 T5;
typedef InT6 T6;
typedef InT7 T7;
typedef InT8 T8;
typedef InT9 T9;
typedef InT10 T10;
typedef InPolicy Policy;
typedef InMixin Mixin;
typedef InAllocator Allocator;
#endif // def BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef typename real_get_function_impl< typedef typename real_get_function_impl<
(count_used_args<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>::value) (count_used_args<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>::value)
>::template params<R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, >::template params<R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
Policy, Mixin, Allocator>::type #ifndef BOOST_FUNCTION_NO_DEPRECATED
Policy, Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
Allocator>::type
type; type;
}; };
#ifndef BOOST_FUNCTION_NO_DEPRECATED
template< template<
typename R, typename InR,
typename T1, typename InT1,
typename T2, typename InT2,
typename T3, typename InT3,
typename T4, typename InT4,
typename T5, typename InT5,
typename T6, typename InT6,
typename T7, typename InT7,
typename T8, typename InT8,
typename T9, typename InT9,
typename T10, typename InT10,
typename MyPolicy = empty_function_policy, typename InMyPolicy = empty_function_policy,
typename MyMixin = empty_function_mixin, typename InMyMixin = empty_function_mixin,
typename MyAllocator = std::allocator<function_base> typename InMyAllocator = std::allocator<function_base>
> >
struct function_traits_builder class function_traits_builder
{ {
typedef typename get_function_impl<R, T1, T2, T3, T4, T5, T6, T7, typedef get_function_impl<InR, InT1, InT2, InT3, InT4, InT5, InT6, InT7,
T8, T9, T10, MyPolicy, MyMixin, InT8, InT9, InT10, InMyPolicy, InMyMixin,
MyAllocator>::type InMyAllocator>
type; impl;
typedef typename impl::R MyR;
typedef typename impl::T1 MyT1;
typedef typename impl::T2 MyT2;
typedef typename impl::T3 MyT3;
typedef typename impl::T4 MyT4;
typedef typename impl::T5 MyT5;
typedef typename impl::T6 MyT6;
typedef typename impl::T7 MyT7;
typedef typename impl::T8 MyT8;
typedef typename impl::T9 MyT9;
typedef typename impl::T10 MyT10;
typedef typename impl::Policy MyPolicy;
typedef typename impl::Mixin MyMixin;
typedef typename impl::Allocator MyAllocator;
public:
typedef typename impl::type type;
typedef MyPolicy policy_type; typedef MyPolicy policy_type;
typedef MyMixin mixin_type; typedef MyMixin mixin_type;
typedef MyAllocator allocator_type; typedef MyAllocator allocator_type;
@ -374,28 +741,28 @@ namespace boost {
#ifndef BOOST_NO_DEPENDENT_NESTED_DERIVATIONS #ifndef BOOST_NO_DEPENDENT_NESTED_DERIVATIONS
template<typename Policy> template<typename Policy>
struct policy : struct policy :
public function_traits_builder<R, T1, T2, T3, T4, T5, T6, T7, T8, T9, public function_traits_builder<MyR, MyT1, MyT2, MyT3, MyT4, MyT5, MyT6,
T10, Policy, mixin_type, MyT7, MyT8, MyT9, MyT10, Policy,
allocator_type> {}; mixin_type, allocator_type> {};
template<typename Mixin> template<typename Mixin>
struct mixin : struct mixin :
public function_traits_builder<R, T1, T2, T3, T4, T5, T6, T7, T8, T9, public function_traits_builder<MyR, MyT1, MyT2, MyT3, MyT4, MyT5, MyT6,
T10, policy_type, Mixin, MyT7, MyT8, MyT9, MyT10, policy_type,
allocator_type> {}; Mixin, allocator_type> {};
template<typename Allocator> template<typename Allocator>
struct allocator : struct allocator :
public function_traits_builder<R, T1, T2, T3, T4, T5, T6, T7, T8, T9, public function_traits_builder<MyR, MyT1, MyT2, MyT3, MyT4, MyT5, MyT6,
T10, policy_type, mixin_type, MyT7, MyT8, MyT9, MyT10, policy_type,
Allocator> {}; mixin_type, Allocator> {};
#else #else
template<typename Policy> template<typename Policy>
struct policy struct policy
{ {
typedef typename function_traits_builder<R, T1, T2, T3, T4, T5, T6, T7, typedef typename function_traits_builder<MyR, MyT1, MyT2, MyT3, MyT4,
T8, T9, T10, Policy, MyT5, MyT6, MyT7, MyT8, MyT9,
mixin_type, MyT10, Policy, mixin_type,
allocator_type>::type allocator_type>::type
type; type;
}; };
@ -403,8 +770,9 @@ namespace boost {
template<typename Mixin> template<typename Mixin>
struct mixin struct mixin
{ {
typedef typename function_traits_builder<R, T1, T2, T3, T4, T5, T6, T7, typedef typename function_traits_builder<MyR, MyT1, MyT2, MyT3, MyT4,
T8, T9, T10, policy_type, Mixin, MyT5, MyT6, MyT7, MyT8, MyT9,
MyT10, policy_type, Mixin,
allocator_type>::type allocator_type>::type
type; type;
}; };
@ -412,14 +780,15 @@ namespace boost {
template<typename Allocator> template<typename Allocator>
struct allocator struct allocator
{ {
typedef typename function_traits_builder<R, T1, T2, T3, T4, T5, T6, T7, typedef typename function_traits_builder<MyR, MyT1, MyT2, MyT3, MyT4,
T8, T9, T10, policy_type, MyT5, MyT6, MyT7, MyT8, MyT9,
mixin_type, Allocator>::type MyT10, policy_type, mixin_type,
Allocator>::type
type; type;
}; };
#endif #endif // ndef NO_DEPENDENT_NESTED_DERIVATIONS
}; };
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
} // end namespace function } // end namespace function
} // end namespace detail } // end namespace detail
@ -438,9 +807,11 @@ namespace boost {
> >
class function : class function :
public detail::function::get_function_impl<R, T1, T2, T3, T4, T5, T6, T7, public detail::function::get_function_impl<R, T1, T2, T3, T4, T5, T6, T7,
T8, T9, T10>::type, T8, T9, T10>::type
public detail::function::function_traits_builder<R, T1, T2, T3, T4, T5, T6, #ifndef BOOST_FUNCTION_NO_DEPRECATED
T7, T8, T9, T10> , public detail::function::function_traits_builder<R, T1, T2, T3, T4, T5,
T6, T7, T8, T9, T10>
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
{ {
typedef typename detail::function::get_function_impl<R, T1, T2, T3, T4, T5, typedef typename detail::function::get_function_impl<R, T1, T2, T3, T4, T5,
T6, T7, T8, T9, T10 T6, T7, T8, T9, T10
@ -448,8 +819,10 @@ namespace boost {
base_type; base_type;
public: public:
#ifndef BOOST_FUNCTION_NO_DEPRECATED
typedef typename base_type::policy_type policy_type; typedef typename base_type::policy_type policy_type;
typedef typename base_type::mixin_type mixin_type; typedef typename base_type::mixin_type mixin_type;
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typedef typename base_type::allocator_type allocator_type; typedef typename base_type::allocator_type allocator_type;
typedef function self_type; typedef function self_type;
@ -479,21 +852,29 @@ namespace boost {
return *this; return *this;
} }
#ifndef BOOST_FUNCTION_NO_DEPRECATED
template<typename Functor> template<typename Functor>
void set(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) BOOST_FUNCTION_DEPRECATED_PRE
void set(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{ {
BOOST_FUNCTION_DEPRECATED_INNER
self_type(f).swap(*this); self_type(f).swap(*this);
} }
void set(const base_type& f) BOOST_FUNCTION_DEPRECATED_PRE
void set(const base_type& f)
{ {
BOOST_FUNCTION_DEPRECATED_INNER
self_type(f).swap(*this); self_type(f).swap(*this);
} }
BOOST_FUNCTION_DEPRECATED_PRE
void set(const self_type& f) void set(const self_type& f)
{ {
BOOST_FUNCTION_DEPRECATED_INNER
self_type(f).swap(*this); self_type(f).swap(*this);
} }
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
}; };
template<typename R, template<typename R,
@ -512,6 +893,8 @@ namespace boost {
{ {
f1.swap(f2); f1.swap(f2);
} }
} } // end namespace boost
#endif // !no deprecated || !no partial specialization
#endif #endif

View File

@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu) // Copyright (C) 2001, 2002 Doug 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.
@ -24,6 +24,7 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/type_traits.hpp> #include <boost/type_traits.hpp>
#include <boost/ref.hpp> #include <boost/ref.hpp>
#include <boost/pending/ct_if.hpp>
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406
# define BOOST_FUNCTION_TARGET_FIX(x) x # define BOOST_FUNCTION_TARGET_FIX(x) x
@ -31,52 +32,22 @@
# define BOOST_FUNCTION_TARGET_FIX(x) # define BOOST_FUNCTION_TARGET_FIX(x)
#endif // not MSVC #endif // not MSVC
#ifdef BOOST_FUNCTION_SILENT_DEPRECATED
# define BOOST_FUNCTION_DEPRECATED_PRE
# define BOOST_FUNCTION_DEPRECATED_INNER
#else
# if defined (BOOST_MSVC) && (BOOST_MSVC >= 1300)
# define BOOST_FUNCTION_DEPRECATED_PRE __declspec(deprecated)
# define BOOST_FUNCTION_DEPRECATED_INNER
# else
# define BOOST_FUNCTION_DEPRECATED_PRE
# define BOOST_FUNCTION_DEPRECATED_INNER int deprecated;
# endif
#endif
namespace boost { namespace boost {
namespace detail { namespace detail {
namespace function { namespace function {
/*
* The IF implementation is temporary code. When a Boost metaprogramming
* library is introduced, Boost.Function will use it instead.
*/
namespace intimate {
struct SelectThen
{
template<typename Then, typename Else>
struct Result
{
typedef Then type;
};
};
struct SelectElse
{
template<typename Then, typename Else>
struct Result
{
typedef Else type;
};
};
template<bool Condition>
struct Selector
{
typedef SelectThen type;
};
template<>
struct Selector<false>
{
typedef SelectElse type;
};
} // end namespace intimate
template<bool Condition, typename Then, typename Else>
struct IF
{
typedef typename intimate::Selector<Condition>::type select;
typedef typename select::template Result<Then,Else>::type type;
};
/** /**
* A union of a function pointer and a void pointer. This is necessary * A union of a function pointer and a void pointer. This is necessary
* because 5.2.10/6 allows reinterpret_cast<> to safely cast between * because 5.2.10/6 allows reinterpret_cast<> to safely cast between
@ -135,20 +106,20 @@ namespace boost {
template<typename F> template<typename F>
class get_function_tag class get_function_tag
{ {
typedef typename IF<(is_pointer<F>::value), typedef typename ct_if<(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 IF<(is_member_pointer<F>::value), typedef typename ct_if<(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 IF<(is_reference_wrapper<F>::value), typedef typename ct_if<(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 IF<(is_stateless<F>::value), typedef typename ct_if<(is_stateless<F>::value),
stateless_function_obj_tag, stateless_function_obj_tag,
or_ref_tag>::type type; or_ref_tag>::type type;
}; };
@ -156,7 +127,7 @@ namespace boost {
// 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, inline any_pointer trivial_manager(any_pointer f,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
if (op == clone_functor_tag) if (op == clone_functor_tag)
return f; return f;
@ -176,7 +147,8 @@ namespace boost {
// For function pointers, the manager is trivial // For function pointers, the manager is trivial
static inline any_pointer static inline any_pointer
manager(any_pointer function_ptr, functor_manager_operation_type op, manager(any_pointer function_ptr,
functor_manager_operation_type op,
function_ptr_tag) function_ptr_tag)
{ {
if (op == clone_functor_tag) if (op == clone_functor_tag)
@ -307,6 +279,10 @@ namespace boost {
detail::function::functor_manager_operation_type); detail::function::functor_manager_operation_type);
detail::function::any_pointer functor; detail::function::any_pointer functor;
#if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
// Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
operator bool () const { return !this->empty(); }
#else
private: private:
struct dummy { struct dummy {
void nonnull() {}; void nonnull() {};
@ -320,6 +296,7 @@ namespace boost {
safe_bool operator!() const safe_bool operator!() const
{ return (this->empty())? &dummy::nonnull : 0; } { return (this->empty())? &dummy::nonnull : 0; }
#endif
}; };
/* Poison comparison between Boost.Function objects (because it is /* Poison comparison between Boost.Function objects (because it is
@ -333,92 +310,14 @@ namespace boost {
namespace detail { namespace detail {
namespace function { namespace function {
/** inline bool has_empty_target(const function_base* f)
* Determine if the given target is empty. {
*/ return f->empty();
// Fallback - assume target is not empty
inline bool has_empty_target(...)
{
return false;
}
// If the target is a 'function', query the empty() method
inline bool has_empty_target(const function_base* af)
{
return af->empty();
} }
// If the target is a 'function', query the empty() method inline bool has_empty_target(...)
inline bool has_empty_target(const function_base& af)
{
return af.empty();
}
// A function pointer is empty if it is null
template<typename R>
inline bool has_empty_target(R (*f)())
{ {
return f == 0; return false;
}
template<typename R, typename T1>
inline bool has_empty_target(R (*f)(T1))
{
return f == 0;
}
template<typename R, typename T1, typename T2>
inline bool has_empty_target(R (*f)(T1, T2))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3>
inline bool has_empty_target(R (*f)(T1, T2, T3))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6, T7))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6, T7, T8))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8, typename T9>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6, T7, T8, T9))
{
return f == 0;
} }
} // end namespace function } // end namespace function
} // end namespace detail } // end namespace detail
@ -430,14 +329,18 @@ namespace boost {
inline void postcall(const function_base*) {} inline void postcall(const function_base*) {}
}; };
// The default function mixin does nothing. The assignment and copy-construction operators // The default function mixin does nothing. The assignment and
// are all defined because MSVC defines broken versions. // copy-construction operators are all defined because MSVC defines broken
struct empty_function_mixin { // versions.
empty_function_mixin() {}; struct empty_function_mixin
empty_function_mixin(const empty_function_mixin&) {}; {
empty_function_mixin() {}
empty_function_mixin(const empty_function_mixin&) {}
empty_function_mixin& operator=(const empty_function_mixin&) empty_function_mixin& operator=(const empty_function_mixin&)
{return *this; } {
return *this;
}
}; };
} }

View File

@ -41,7 +41,6 @@
// Class names used in this version of the code // Class names used in this version of the code
#define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_BASE BOOST_JOIN(function_base,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_FUNCTION_INVOKER \ #define BOOST_FUNCTION_FUNCTION_INVOKER \
BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \ #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
@ -168,7 +167,7 @@ namespace boost {
> >
struct BOOST_FUNCTION_GET_FUNCTION_INVOKER struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
{ {
typedef typename IF<(is_void<R>::value), typedef typename ct_if<(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 +188,7 @@ namespace boost {
> >
struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
{ {
typedef typename IF<(is_void<R>::value), typedef typename ct_if<(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
@ -210,7 +209,7 @@ namespace boost {
> >
struct BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER struct BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
{ {
typedef typename IF<(is_void<R>::value), typedef typename ct_if<(is_void<R>::value),
BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER< BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER<
FunctionObj, FunctionObj,
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
@ -230,11 +229,16 @@ namespace boost {
template< template<
typename R BOOST_FUNCTION_COMMA typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS, BOOST_FUNCTION_TEMPLATE_PARMS,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
typename Policy = empty_function_policy, typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin, typename Mixin = empty_function_mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR
> >
class BOOST_FUNCTION_FUNCTION : public function_base, public Mixin class BOOST_FUNCTION_FUNCTION : public function_base
#ifndef BOOST_FUNCTION_NO_DEPRECATED
, public Mixin
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
{ {
typedef typename detail::function::function_return_type<R>::type typedef typename detail::function::function_return_type<R>::type
internal_result_type; internal_result_type;
@ -254,36 +258,58 @@ namespace boost {
#else #else
typedef internal_result_type result_type; typedef internal_result_type result_type;
#endif // BOOST_NO_VOID_RETURNS #endif // BOOST_NO_VOID_RETURNS
#ifndef BOOST_FUNCTION_NO_DEPRECATED
typedef Policy policy_type; typedef Policy policy_type;
typedef Mixin mixin_type; typedef Mixin mixin_type;
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
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(), Mixin(), invoker(0) {} BOOST_FUNCTION_FUNCTION() : function_base()
#ifndef BOOST_FUNCTION_NO_DEPRECATED
, Mixin()
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
, invoker(0) {}
#ifndef BOOST_FUNCTION_NO_DEPRECATED
explicit BOOST_FUNCTION_FUNCTION(const Mixin& m) : explicit BOOST_FUNCTION_FUNCTION(const Mixin& m) :
function_base(), Mixin(m), invoker(0) function_base(),
Mixin(m),
invoker(0)
{ {
} }
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
// 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.
template<typename Functor> template<typename Functor>
BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) : BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) :
function_base(), Mixin(), invoker(0) function_base(),
#ifndef BOOST_FUNCTION_NO_DEPRECATED
Mixin(),
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
invoker(0)
{ {
this->assign_to(f); this->assign_to(f);
} }
#ifndef BOOST_FUNCTION_NO_DEPRECATED
template<typename Functor> template<typename Functor>
BOOST_FUNCTION_FUNCTION(Functor f, const Mixin& m) : BOOST_FUNCTION_FUNCTION(Functor f, const Mixin& m) :
function_base(), Mixin(m), invoker(0) function_base(),
Mixin(m),
invoker(0)
{ {
this->assign_to(f); this->assign_to(f);
} }
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) :
function_base(), Mixin(static_cast<const Mixin&>(f)), invoker(0) function_base(),
#ifndef BOOST_FUNCTION_NO_DEPRECATED
Mixin(static_cast<const Mixin&>(f)),
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
invoker(0)
{ {
this->assign_to_own(f); this->assign_to_own(f);
} }
@ -294,14 +320,19 @@ namespace boost {
{ {
assert(!this->empty()); assert(!this->empty());
#ifndef BOOST_FUNCTION_NO_DEPRECATED
policy_type policy; policy_type policy;
policy.precall(this); policy.precall(this);
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
internal_result_type result = invoker(function_base::functor internal_result_type result = invoker(function_base::functor
BOOST_FUNCTION_COMMA BOOST_FUNCTION_COMMA
BOOST_FUNCTION_ARGS); BOOST_FUNCTION_ARGS);
#ifndef BOOST_FUNCTION_NO_DEPRECATED
policy.postcall(this); policy.postcall(this);
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
#ifndef BOOST_NO_VOID_RETURNS #ifndef BOOST_NO_VOID_RETURNS
return static_cast<result_type>(result); return static_cast<result_type>(result);
#else #else
@ -318,15 +349,23 @@ namespace boost {
BOOST_FUNCTION_FUNCTION& BOOST_FUNCTION_FUNCTION&
operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{ {
#ifndef BOOST_FUNCTION_NO_DEPRECATED
self_type(f, static_cast<const Mixin&>(*this)).swap(*this); self_type(f, static_cast<const Mixin&>(*this)).swap(*this);
#else
self_type(f).swap(*this);
#endif // BOOST_FUNCTION_NO_DEPRECATED
return *this; return *this;
} }
#ifndef BOOST_FUNCTION_NO_DEPRECATED
template<typename Functor> template<typename Functor>
BOOST_FUNCTION_DEPRECATED_PRE
void set(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) void set(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{ {
BOOST_FUNCTION_DEPRECATED_INNER
self_type(f, static_cast<const Mixin&>(*this)).swap(*this); self_type(f, static_cast<const Mixin&>(*this)).swap(*this);
} }
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
// Assignment from another BOOST_FUNCTION_FUNCTION // Assignment from another BOOST_FUNCTION_FUNCTION
BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f) BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
@ -338,14 +377,18 @@ namespace boost {
return *this; return *this;
} }
#ifndef BOOST_FUNCTION_NO_DEPRECATED
// Assignment from another BOOST_FUNCTION_FUNCTION // Assignment from another BOOST_FUNCTION_FUNCTION
BOOST_FUNCTION_DEPRECATED_PRE
void set(const BOOST_FUNCTION_FUNCTION& f) void set(const BOOST_FUNCTION_FUNCTION& f)
{ {
BOOST_FUNCTION_DEPRECATED_INNER
if (&f == this) if (&f == this)
return; return;
self_type(f).swap(*this); self_type(f).swap(*this);
} }
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
void swap(BOOST_FUNCTION_FUNCTION& other) void swap(BOOST_FUNCTION_FUNCTION& other)
{ {
@ -355,15 +398,20 @@ namespace boost {
std::swap(function_base::manager, other.manager); std::swap(function_base::manager, other.manager);
std::swap(function_base::functor, other.functor); std::swap(function_base::functor, other.functor);
std::swap(invoker, other.invoker); std::swap(invoker, other.invoker);
#ifndef BOOST_FUNCTION_NO_DEPRECATED
std::swap(static_cast<Mixin&>(*this), static_cast<Mixin&>(other)); std::swap(static_cast<Mixin&>(*this), static_cast<Mixin&>(other));
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
} }
// Clear out a target, if there is one // Clear out a target, if there is one
void clear() void clear()
{ {
if (function_base::manager) if (function_base::manager) {
function_base::functor = function_base::manager(function_base::functor, detail::function::destroy_functor_tag); function_base::functor =
function_base::manager(function_base::functor,
detail::function::destroy_functor_tag);
}
function_base::manager = 0; function_base::manager = 0;
invoker = 0; invoker = 0;
} }
@ -374,7 +422,8 @@ namespace boost {
if (!f.empty()) { if (!f.empty()) {
invoker = f.invoker; invoker = f.invoker;
function_base::manager = f.manager; function_base::manager = f.manager;
function_base::functor = f.manager(f.functor, detail::function::clone_functor_tag); function_base::functor =
f.manager(f.functor, detail::function::clone_functor_tag);
} }
} }
@ -399,9 +448,10 @@ namespace boost {
invoker_type; invoker_type;
invoker = &invoker_type::invoke; invoker = &invoker_type::invoke;
function_base::manager = &detail::function::functor_manager<FunctionPtr, function_base::manager =
Allocator>::manage; &detail::function::functor_manager<FunctionPtr, Allocator>::manage;
function_base::functor = function_base::manager(detail::function::any_pointer( function_base::functor =
function_base::manager(detail::function::any_pointer(
// should be a reinterpret cast, but some compilers // should be a reinterpret cast, but some compilers
// insist on giving cv-qualifiers to free functions // insist on giving cv-qualifiers to free functions
(void (*)())(f) (void (*)())(f)
@ -421,7 +471,7 @@ namespace boost {
template<typename FunctionObj> template<typename FunctionObj>
void assign_to(FunctionObj f, detail::function::function_obj_tag) void assign_to(FunctionObj f, detail::function::function_obj_tag)
{ {
if (!detail::function::has_empty_target(&f)) { if (!detail::function::has_empty_target(addressof(f))) {
typedef typedef
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj, FunctionObj,
@ -431,11 +481,23 @@ namespace boost {
invoker_type; invoker_type;
invoker = &invoker_type::invoke; invoker = &invoker_type::invoke;
function_base::manager = &detail::function::functor_manager<FunctionObj, function_base::manager = &detail::function::functor_manager<
Allocator>::manage; 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
function_base::functor = function_base::functor =
function_base::manager(detail::function::any_pointer(const_cast<FunctionObj*>(&f)), detail::function::any_pointer(static_cast<void*>(new_f));
detail::function::clone_functor_tag);
} }
} }
@ -443,7 +505,7 @@ namespace boost {
void assign_to(const reference_wrapper<FunctionObj>& f, void assign_to(const reference_wrapper<FunctionObj>& f,
detail::function::function_obj_ref_tag) detail::function::function_obj_ref_tag)
{ {
if (!detail::function::has_empty_target(&f.get())) { if (!detail::function::has_empty_target(f.get_pointer())) {
typedef typedef
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj, FunctionObj,
@ -455,9 +517,10 @@ namespace boost {
invoker = &invoker_type::invoke; invoker = &invoker_type::invoke;
function_base::manager = &detail::function::trivial_manager; function_base::manager = &detail::function::trivial_manager;
function_base::functor = function_base::functor =
function_base::manager(detail::function::any_pointer( function_base::manager(
const_cast<FunctionObj*>(&f.get())), detail::function::any_pointer(
detail::function::clone_functor_tag); const_cast<FunctionObj*>(f.get_pointer())),
detail::function::clone_functor_tag);
} }
} }
@ -485,19 +548,26 @@ namespace boost {
}; };
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS , template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
typename Policy, typename Mixin, typename Allocator> #ifndef BOOST_FUNCTION_NO_DEPRECATED
typename Policy, typename Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
typename Allocator>
inline void swap(BOOST_FUNCTION_FUNCTION< inline void swap(BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS , BOOST_FUNCTION_TEMPLATE_ARGS ,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
Policy, Policy,
Mixin, Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
Allocator Allocator
>& f1, >& f1,
BOOST_FUNCTION_FUNCTION< BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS, BOOST_FUNCTION_TEMPLATE_ARGS,
#ifndef BOOST_FUNCTION_NO_DEPRECATED
Policy, Policy,
Mixin, Mixin,
#endif // ndef BOOST_FUNCTION_NO_DEPRECATED
Allocator Allocator
>& f2) >& f2)
{ {
@ -509,8 +579,6 @@ namespace boost {
#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
#undef BOOST_FUNCTION_BASE
#undef BOOST_FUNCTION_INVOKER_BASE
#undef BOOST_FUNCTION_FUNCTION_INVOKER #undef BOOST_FUNCTION_FUNCTION_INVOKER
#undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
#undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
@ -521,4 +589,3 @@ namespace boost {
#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_STATELESS_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER

View File

@ -13,6 +13,7 @@
<p> Generally, any place in which a function pointer would be used to defer a call or make a callback, Boost.Function can be used instead to allow the user greater flexibility in the implementation of the target. Targets can be any 'compatible' function object (or function pointer), meaning that the arguments to the interface designated by Boost.Function can be converted to the arguments of the target function object. <p> Generally, any place in which a function pointer would be used to defer a call or make a callback, Boost.Function can be used instead to allow the user greater flexibility in the implementation of the target. Targets can be any 'compatible' function object (or function pointer), meaning that the arguments to the interface designated by Boost.Function can be converted to the arguments of the target function object.
<ul> <ul>
<li><a href="#compatibility">Compatibility Note</a></li>
<li><a href="doc/tutorial.html">Tutorial</a></li> <li><a href="doc/tutorial.html">Tutorial</a></li>
<li><a href="doc/reference.html">Reference manual</a></li> <li><a href="doc/reference.html">Reference manual</a></li>
<li><a href="#vspointers">Boost.Function vs. Function Pointers</a></li> <li><a href="#vspointers">Boost.Function vs. Function Pointers</a></li>
@ -23,6 +24,48 @@
<li><a href="doc/faq.html">Frequently Asked Questions</a></li> <li><a href="doc/faq.html">Frequently Asked Questions</a></li>
</ul> </ul>
<a name="compatibility"><h2>Compatibility Note</h2></a>
<p> Boost.Function has been partially redesigned to minimize the interface and make it cleaner. Several seldom- or never-used features of the older Boost.Function have been deprecated and will be removed in the near future. Here is a list of features that have been deprecated, the likely impact of the deprecations, and how to adjust your code:
<ul>
<li>The <code>boost::function</code> class template syntax has
changed. The old syntax, e.g., <code>boost::function&lt;int, float,
double, std::string&gt;</code>, has been changed to a more natural
syntax <code>boost::function&lt;int (float, double,
std::string)&gt;</code>, where all return and argument types are
encoded in a single function type parameter. Any other template
parameters (e.g., the <code>Allocator</code>) follow this single
parameter.
<p> The resolution to this change depends on the
abilities of your compiler: if your compiler supports template
partial specialization and can parse function types (most do), modify
your code to use the newer
syntax (preferable) or directly use one of the
<code>function<em>N</em></code> classes whose syntax has not
changed. If your compiler does not support template partial
specialization or function types, you must take the latter option and
use the numbered Boost.Function classes. This option merely requires
changing types such as <code>boost::function&lt;void, int, int&gt;</code>
to <code>boost::function2&lt;void, int, int&gt;</code> (adding the number of
function arguments to the end of the class name).
<p> Support for the old syntax with the
<code>boost::function</code> class template will persist for a short
while, but will eventually be removed so that we can provide better
error messages and link compatibility. </li>
<li>The invocation
policy template parameter (<code>Policy</code>) has been deprecated
and will be removed. There is no direct equivalent to this rarely
used feature.</li> <li>The mixin template parameter
(<code>Mixin</code>) has been deprecated and will be removed. There
is not direct equivalent to this rarely used feature.</li> <li>The
<code>set</code> methods have been deprecated and will be
removed. Use the assignment operator instead.</li>
</ul>
<p> To aid in porting to the new syntax and removing the use of deprecated features, define the preprocessor macro <code>BOOST_FUNCTION_NO_DEPRECATED</code>. This macro makes all deprecated features unavailable. A program compiled with <code>BOOST_FUNCTION_NO_DEPRECATED</code> will likely be prepared when the deprecated features are removed.
<h2><a name="vspointers">Boost.Function vs. Function Pointers</a></h2> <h2><a name="vspointers">Boost.Function vs. Function Pointers</a></h2>
<p>Boost.Function has several advantages over function pointers, namely: <p>Boost.Function has several advantages over function pointers, namely:

View File

@ -0,0 +1,645 @@
// Boost.Function library
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <boost/function.hpp>
#include <functional>
#include <cassert>
#include <string>
using namespace boost;
using std::string;
using std::negate;
int global_int;
struct write_five_obj { void operator()() const { global_int = 5; } };
struct write_three_obj { int operator()() const { global_int = 3; return 7; }};
static void write_five() { global_int = 5; }
static void write_three() { global_int = 3; }
struct generate_five_obj { int operator()() const { return 5; } };
struct generate_three_obj { int operator()() const { return 3; } };
static int generate_five() { return 5; }
static int generate_three() { return 3; }
static string identity_str(const string& s) { return s; }
static string string_cat(const string& s1, const string& s2) { return s1+s2; }
static int sum_ints(int x, int y) { return x+y; }
struct write_const_1_nonconst_2
{
void operator()() { global_int = 2; }
void operator()() const { global_int = 1; }
};
struct add_to_obj
{
add_to_obj(int v) : value(v) {}
int operator()(int x) const { return value + x; }
int value;
};
static void
test_zero_args()
{
typedef function<void> func_void_type;
write_five_obj five;
write_three_obj three;
// Default construction
func_void_type v1;
BOOST_TEST(v1.empty());
// Assignment to an empty function
v1 = five;
BOOST_TEST(!v1.empty());
// Invocation of a function
global_int = 0;
v1();
BOOST_TEST(global_int == 5);
// clear() method
v1.clear();
BOOST_TEST(v1.empty());
// Assignment to an empty function
v1 = three;
BOOST_TEST(!v1.empty());
// Invocation and self-assignment
global_int = 0;
v1 = v1;
v1();
BOOST_TEST(global_int == 3);
// Assignment to a non-empty function
v1 = five;
// Invocation and self-assignment
global_int = 0;
v1 = (v1);
v1();
BOOST_TEST(global_int == 5);
// clear()
v1.clear();
BOOST_TEST(v1.empty());
// Assignment to an empty function from a free function
v1 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
BOOST_TEST(!v1.empty());
// Invocation
global_int = 0;
v1();
BOOST_TEST(global_int == 5);
// Assignment to a non-empty function from a free function
v1 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
BOOST_TEST(!v1.empty());
// Invocation
global_int = 0;
v1();
BOOST_TEST(global_int == 3);
// Assignment
v1 = five;
BOOST_TEST(!v1.empty());
// Invocation
global_int = 0;
v1();
BOOST_TEST(global_int == 5);
// Assignment to a non-empty function from a free function
v1 = &write_three;
BOOST_TEST(!v1.empty());
// Invocation
global_int = 0;
v1();
BOOST_TEST(global_int == 3);
// Construction from another function (that is empty)
v1.clear();
func_void_type v2(v1);
BOOST_TEST(!v2);
// Assignment to an empty function
v2 = three;
BOOST_TEST(!v2.empty());
// Invocation
global_int = 0;
v2();
BOOST_TEST(global_int == 3);
// Assignment to a non-empty function
v2 = (five);
// Invocation
global_int = 0;
v2();
BOOST_TEST(global_int == 5);
v2.clear();
BOOST_TEST(v2.empty());
// Assignment to an empty function from a free function
v2 = (BOOST_FUNCTION_TARGET_FIX(&) write_five);
BOOST_TEST(v2);
// Invocation
global_int = 0;
v2();
BOOST_TEST(global_int == 5);
// Assignment to a non-empty function from a free function
v2 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
BOOST_TEST(!v2.empty());
// Invocation
global_int = 0;
v2();
BOOST_TEST(global_int == 3);
// Swapping
v1 = five;
swap(v1, v2);
v2();
BOOST_TEST(global_int == 5);
v1();
BOOST_TEST(global_int == 3);
swap(v1, v2);
v1.clear();
// Assignment
v2 = five;
BOOST_TEST(!v2.empty());
// Invocation
global_int = 0;
v2();
BOOST_TEST(global_int == 5);
// Assignment to a non-empty function from a free function
v2 = &write_three;
BOOST_TEST(!v2.empty());
// Invocation
global_int = 0;
v2();
BOOST_TEST(global_int == 3);
// Assignment to a function from an empty function
v2 = v1;
BOOST_TEST(v2.empty());
// Assignment to a function from a function with a functor
v1 = three;
v2 = v1;
BOOST_TEST(!v1.empty());
BOOST_TEST(!v2.empty());
// Invocation
global_int = 0;
v1();
BOOST_TEST(global_int == 3);
global_int = 0;
v2();
BOOST_TEST(global_int == 3);
// Assign to a function from a function with a function
v2 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
v1 = v2;
BOOST_TEST(!v1.empty());
BOOST_TEST(!v2.empty());
global_int = 0;
v1();
BOOST_TEST(global_int == 5);
global_int = 0;
v2();
BOOST_TEST(global_int == 5);
// Construct a function given another function containing a function
func_void_type v3(v1);
// Invocation of a function
global_int = 0;
v3();
BOOST_TEST(global_int == 5);
// clear() method
v3.clear();
BOOST_TEST(!v3);
// Assignment to an empty function
v3 = three;
BOOST_TEST(!v3.empty());
// Invocation
global_int = 0;
v3();
BOOST_TEST(global_int == 3);
// Assignment to a non-empty function
v3 = five;
// Invocation
global_int = 0;
v3();
BOOST_TEST(global_int == 5);
// clear()
v3.clear();
BOOST_TEST(v3.empty());
// Assignment to an empty function from a free function
v3 = &write_five;
BOOST_TEST(!v3.empty());
// Invocation
global_int = 0;
v3();
BOOST_TEST(global_int == 5);
// Assignment to a non-empty function from a free function
v3 = &write_three;
BOOST_TEST(!v3.empty());
// Invocation
global_int = 0;
v3();
BOOST_TEST(global_int == 3);
// Assignment
v3 = five;
BOOST_TEST(!v3.empty());
// Invocation
global_int = 0;
v3();
BOOST_TEST(global_int == 5);
// Construction of a function from a function containing a functor
func_void_type v4(v3);
// Invocation of a function
global_int = 0;
v4();
BOOST_TEST(global_int == 5);
// clear() method
v4.clear();
BOOST_TEST(v4.empty());
// Assignment to an empty function
v4 = three;
BOOST_TEST(!v4.empty());
// Invocation
global_int = 0;
v4();
BOOST_TEST(global_int == 3);
// Assignment to a non-empty function
v4 = five;
// Invocation
global_int = 0;
v4();
BOOST_TEST(global_int == 5);
// clear()
v4.clear();
BOOST_TEST(v4.empty());
// Assignment to an empty function from a free function
v4 = &write_five;
BOOST_TEST(!v4.empty());
// Invocation
global_int = 0;
v4();
BOOST_TEST(global_int == 5);
// Assignment to a non-empty function from a free function
v4 = &write_three;
BOOST_TEST(!v4.empty());
// Invocation
global_int = 0;
v4();
BOOST_TEST(global_int == 3);
// Assignment
v4 = five;
BOOST_TEST(!v4.empty());
// Invocation
global_int = 0;
v4();
BOOST_TEST(global_int == 5);
// Construction of a function from a functor
func_void_type v5(five);
// Invocation of a function
global_int = 0;
v5();
BOOST_TEST(global_int == 5);
// clear() method
v5.clear();
BOOST_TEST(v5.empty());
// Assignment to an empty function
v5 = three;
BOOST_TEST(!v5.empty());
// Invocation
global_int = 0;
v5();
BOOST_TEST(global_int == 3);
// Assignment to a non-empty function
v5 = five;
// Invocation
global_int = 0;
v5();
BOOST_TEST(global_int == 5);
// clear()
v5.clear();
BOOST_TEST(v5.empty());
// Assignment to an empty function from a free function
v5 = &write_five;
BOOST_TEST(!v5.empty());
// Invocation
global_int = 0;
v5();
BOOST_TEST(global_int == 5);
// Assignment to a non-empty function from a free function
v5 = &write_three;
BOOST_TEST(!v5.empty());
// Invocation
global_int = 0;
v5();
BOOST_TEST(global_int == 3);
// Assignment
v5 = five;
BOOST_TEST(!v5.empty());
// Invocation
global_int = 0;
v5();
BOOST_TEST(global_int == 5);
// Construction of a function from a function
func_void_type v6(&write_five);
// Invocation of a function
global_int = 0;
v6();
BOOST_TEST(global_int == 5);
// clear() method
v6.clear();
BOOST_TEST(v6.empty());
// Assignment to an empty function
v6 = three;
BOOST_TEST(!v6.empty());
// Invocation
global_int = 0;
v6();
BOOST_TEST(global_int == 3);
// Assignment to a non-empty function
v6 = five;
// Invocation
global_int = 0;
v6();
BOOST_TEST(global_int == 5);
// clear()
v6.clear();
BOOST_TEST(v6.empty());
// Assignment to an empty function from a free function
v6 = &write_five;
BOOST_TEST(!v6.empty());
// Invocation
global_int = 0;
v6();
BOOST_TEST(global_int == 5);
// Assignment to a non-empty function from a free function
v6 = &write_three;
BOOST_TEST(!v6.empty());
// Invocation
global_int = 0;
v6();
BOOST_TEST(global_int == 3);
// Assignment
v6 = five;
BOOST_TEST(!v6.empty());
// Invocation
global_int = 0;
v6();
BOOST_TEST(global_int == 5);
// Const vs. non-const
write_const_1_nonconst_2 one_or_two;
const function<void> v7(one_or_two);
function <void> v8(one_or_two);
global_int = 0;
v7();
BOOST_TEST(global_int == 2);
global_int = 0;
v8();
BOOST_TEST(global_int == 2);
// Test return values
typedef function<int> func_int_type;
generate_five_obj gen_five;
generate_three_obj gen_three;
func_int_type i0(gen_five);
BOOST_TEST(i0() == 5);
i0 = gen_three;
BOOST_TEST(i0() == 3);
i0 = &generate_five;
BOOST_TEST(i0() == 5);
i0 = &generate_three;
BOOST_TEST(i0() == 3);
BOOST_TEST(i0);
i0.clear();
BOOST_TEST(!i0);
// Test return values with compatible types
typedef function<long> func_long_type;
func_long_type i1(gen_five);
BOOST_TEST(i1() == 5);
i1 = gen_three;
BOOST_TEST(i1() == 3);
i1 = &generate_five;
BOOST_TEST(i1() == 5);
i1 = &generate_three;
BOOST_TEST(i1() == 3);
BOOST_TEST(i1);
i1.clear();
BOOST_TEST(!i1);
}
static void
test_one_arg()
{
negate<int> neg;
function<int, int> f1(neg);
BOOST_TEST(f1(5) == -5);
function<string, string> id(&identity_str);
BOOST_TEST(id("str") == "str");
function<std::string, const char*> id2(&identity_str);
BOOST_TEST(id2("foo") == "foo");
add_to_obj add_to(5);
function<int, int> f2(add_to);
BOOST_TEST(f2(3) == 8);
const function<int, int> cf2(add_to);
BOOST_TEST(cf2(3) == 8);
}
static void
test_two_args()
{
function<string, const string&, const string&> cat(&string_cat);
BOOST_TEST(cat("str", "ing") == "string");
function<int, short, short> sum(&sum_ints);
BOOST_TEST(sum(2, 3) == 5);
}
static void
test_emptiness()
{
function<float> f1;
BOOST_TEST(f1.empty());
function<float> f2;
f2 = f1;
BOOST_TEST(f2.empty());
function<double> f3;
f3 = f2;
BOOST_TEST(f3.empty());
}
struct X {
X(int v) : value(v) {}
int twice() const { return 2*value; }
int plus(int v) { return value + v; }
int value;
};
static void
test_member_functions()
{
boost::function<int, X*> f1(&X::twice);
X one(1);
X five(5);
BOOST_TEST(f1(&one) == 2);
BOOST_TEST(f1(&five) == 10);
boost::function<int, X*> f1_2;
f1_2 = &X::twice;
BOOST_TEST(f1_2(&one) == 2);
BOOST_TEST(f1_2(&five) == 10);
boost::function<int, X&, int> f2(&X::plus);
BOOST_TEST(f2(one, 3) == 4);
BOOST_TEST(f2(five, 4) == 9);
}
struct add_with_throw_on_copy {
int operator()(int x, int y) const { return x+y; }
add_with_throw_on_copy() {}
add_with_throw_on_copy(const add_with_throw_on_copy&)
{
throw std::runtime_error("But this CAN'T throw");
}
add_with_throw_on_copy& operator=(const add_with_throw_on_copy&)
{
throw std::runtime_error("But this CAN'T throw");
}
};
static void
test_ref()
{
add_with_throw_on_copy atc;
try {
boost::function<int, int, int> f(ref(atc));
BOOST_TEST(f(1, 3) == 4);
}
catch(std::runtime_error e) {
BOOST_ERROR("Nonthrowing constructor threw an exception");
}
}
int test_main(int, char* [])
{
test_zero_args();
test_one_arg();
test_two_args();
test_emptiness();
test_member_functions();
test_ref();
return 0;
}

View File

@ -93,7 +93,7 @@ test_zero_args()
// Invocation and self-assignment // Invocation and self-assignment
global_int = 0; global_int = 0;
v1.set(v1); v1 = (v1);
v1(); v1();
BOOST_TEST(global_int == 5); BOOST_TEST(global_int == 5);
@ -152,7 +152,7 @@ test_zero_args()
BOOST_TEST(global_int == 3); BOOST_TEST(global_int == 3);
// Assignment to a non-empty function // Assignment to a non-empty function
v2.set(five); v2 = (five);
// Invocation // Invocation
global_int = 0; global_int = 0;
@ -163,7 +163,7 @@ test_zero_args()
BOOST_TEST(v2.empty()); BOOST_TEST(v2.empty());
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
v2.set(&write_five); v2 = (&write_five);
BOOST_TEST(v2); BOOST_TEST(v2);
// Invocation // Invocation

View File

@ -14,6 +14,7 @@
// For more information, see http://www.boost.org // For more information, see http://www.boost.org
#define BOOST_INCLUDE_MAIN #define BOOST_INCLUDE_MAIN
#define BOOST_FUNCTION_NO_DEPRECATED
#include <boost/test/test_tools.hpp> #include <boost/test/test_tools.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <functional> #include <functional>
@ -21,8 +22,7 @@
#include <string> #include <string>
using namespace boost; using namespace boost;
using std::string; using namespace std;
using std::negate;
int global_int; int global_int;
@ -56,7 +56,7 @@ struct add_to_obj
static void static void
test_zero_args() test_zero_args()
{ {
typedef function<void> func_void_type; typedef function<void ()> func_void_type;
write_five_obj five; write_five_obj five;
write_three_obj three; write_three_obj three;
@ -93,7 +93,7 @@ test_zero_args()
// Invocation and self-assignment // Invocation and self-assignment
global_int = 0; global_int = 0;
v1.set(v1); v1 = (v1);
v1(); v1();
BOOST_TEST(global_int == 5); BOOST_TEST(global_int == 5);
@ -152,7 +152,7 @@ test_zero_args()
BOOST_TEST(global_int == 3); BOOST_TEST(global_int == 3);
// Assignment to a non-empty function // Assignment to a non-empty function
v2.set(five); v2 = (five);
// Invocation // Invocation
global_int = 0; global_int = 0;
@ -163,7 +163,7 @@ test_zero_args()
BOOST_TEST(v2.empty()); BOOST_TEST(v2.empty());
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
v2.set(BOOST_FUNCTION_TARGET_FIX(&) write_five); v2 = (BOOST_FUNCTION_TARGET_FIX(&) write_five);
BOOST_TEST(v2); BOOST_TEST(v2);
// Invocation // Invocation
@ -480,8 +480,8 @@ test_zero_args()
// Const vs. non-const // Const vs. non-const
write_const_1_nonconst_2 one_or_two; write_const_1_nonconst_2 one_or_two;
const function<void> v7(one_or_two); const function<void ()> v7(one_or_two);
function <void> v8(one_or_two); function<void ()> v8(one_or_two);
global_int = 0; global_int = 0;
v7(); v7();
@ -492,7 +492,7 @@ test_zero_args()
BOOST_TEST(global_int == 2); BOOST_TEST(global_int == 2);
// Test return values // Test return values
typedef function<int> func_int_type; typedef function<int ()> func_int_type;
generate_five_obj gen_five; generate_five_obj gen_five;
generate_three_obj gen_three; generate_three_obj gen_three;
@ -510,7 +510,7 @@ test_zero_args()
BOOST_TEST(!i0); BOOST_TEST(!i0);
// 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_TEST(i1() == 5);
@ -530,44 +530,44 @@ 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_TEST(f1(5) == -5);
function<string, string> id(&identity_str); function<string (string)> id(&identity_str);
BOOST_TEST(id("str") == "str"); BOOST_TEST(id("str") == "str");
function<std::string, const char*> id2(&identity_str); function<string (const char*)> id2(&identity_str);
BOOST_TEST(id2("foo") == "foo"); BOOST_TEST(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_TEST(f2(3) == 8);
const function<int, int> cf2(add_to); const function<int (int)> cf2(add_to);
BOOST_TEST(cf2(3) == 8); BOOST_TEST(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_TEST(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_TEST(sum(2, 3) == 5);
} }
static void static void
test_emptiness() test_emptiness()
{ {
function<float> f1; function<float ()> f1;
BOOST_TEST(f1.empty()); BOOST_TEST(f1.empty());
function<float> f2; function<float ()> f2;
f2 = f1; f2 = f1;
BOOST_TEST(f2.empty()); BOOST_TEST(f2.empty());
function<double> f3; function<double ()> f3;
f3 = f2; f3 = f2;
BOOST_TEST(f3.empty()); BOOST_TEST(f3.empty());
} }
@ -584,7 +584,7 @@ struct X {
static void static void
test_member_functions() test_member_functions()
{ {
boost::function<int, X*> f1(&X::twice); boost::function<int (X*)> f1(&X::twice);
X one(1); X one(1);
X five(5); X five(5);
@ -592,13 +592,13 @@ test_member_functions()
BOOST_TEST(f1(&one) == 2); BOOST_TEST(f1(&one) == 2);
BOOST_TEST(f1(&five) == 10); BOOST_TEST(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_TEST(f1_2(&one) == 2);
BOOST_TEST(f1_2(&five) == 10); BOOST_TEST(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_TEST(f2(one, 3) == 4);
BOOST_TEST(f2(five, 4) == 9); BOOST_TEST(f2(five, 4) == 9);
} }
@ -610,12 +610,12 @@ struct add_with_throw_on_copy {
add_with_throw_on_copy(const add_with_throw_on_copy&) add_with_throw_on_copy(const add_with_throw_on_copy&)
{ {
throw std::runtime_error("But this CAN'T throw"); throw runtime_error("But this CAN'T throw");
} }
add_with_throw_on_copy& operator=(const add_with_throw_on_copy&) add_with_throw_on_copy& operator=(const add_with_throw_on_copy&)
{ {
throw std::runtime_error("But this CAN'T throw"); throw runtime_error("But this CAN'T throw");
} }
}; };
@ -624,14 +624,78 @@ 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_TEST(f(1, 3) == 4);
} }
catch(std::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
}
int test_main(int, char* []) int test_main(int, char* [])
{ {
test_zero_args(); test_zero_args();
@ -640,6 +704,7 @@ int test_main(int, char* [])
test_emptiness(); test_emptiness();
test_member_functions(); test_member_functions();
test_ref(); test_ref();
test_allocator();
return 0; return 0;
} }