Compare commits

..

41 Commits

Author SHA1 Message Date
0dcec9ffb9 function_base.hpp:
- Fixed strange patch weirdness on Sun WorkShop C++


[SVN r13855]
2002-05-14 14:34:21 +00:00
4d635501ab function_base.hpp:
function_template.hpp:
  - Revert to older implementation of has_empty_function (Metrowerks doesn't
    handle is_base_and_derived correctly)


[SVN r13854]
2002-05-14 14:18:36 +00:00
d1f21800ac Lambda is now a Boost library
[SVN r13831]
2002-05-13 12:33:19 +00:00
092cb0d706 This commit was manufactured by cvs2svn to create branch 'RC_1_28_0'.
[SVN r13795]
2002-05-10 04:34:27 +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
02f5d9d0e0 reference.html:
- Document non-voidness of result_type when on a broken compiler


[SVN r12616]
2002-02-01 02:55:22 +00:00
1774c0646d function_template.hpp:
- Handle compilers without void returns in a sensible manner


[SVN r12615]
2002-02-01 02:51:48 +00:00
4b430a5414 function_template.hpp:
- Make functionN<void, ...> really have a void return value


[SVN r12613]
2002-01-31 22:56:16 +00:00
7b0f465f33 Reverting member function pointer optimization
[SVN r12580]
2002-01-30 15:04:08 +00:00
6882358627 function_base.hpp:
function_template.hpp:
  - Add support for storing member function pointers directly within the
    Boost.Function object, without allocating any extra memory


[SVN r12568]
2002-01-30 04:33:45 +00:00
39f6d34db8 reference.html:
- Document exception behavior of assignments/construction from stateless
    objects
  - Document what the term "stateless" means in this context


[SVN r12567]
2002-01-30 03:54:18 +00:00
812ef599bd function_template.hpp:
- Fix unused parameter warning


[SVN r12565]
2002-01-30 03:39:44 +00:00
8c198b1c90 function_template.hpp:
- Ensure initialization of stateless function objects


[SVN r12561]
2002-01-30 03:18:15 +00:00
5a07d4b262 regression.cfg:
- Add stateless_test


[SVN r12560]
2002-01-30 03:17:40 +00:00
11187bcf3a function_base.hpp:
- Switch over to using is_reference_wrapper instead of homegrown is_ref
  - Identify stateless function objects

function_template.hpp:
  - Optimize away construction/allocator for stateless function objects.


[SVN r12559]
2002-01-30 01:59:49 +00:00
aaa7f61b9e stateless_test.cpp:
- Test function's ability to optimize away allocations for stateless function
    objects


[SVN r12557]
2002-01-30 01:58:28 +00:00
a250f9c140 Lots of documentation fixes - thanks Dave
[SVN r12505]
2002-01-25 15:00:37 +00:00
4f33ea7665 function_base.hpp:
- Fixed for Intel on Windows _and_ MSVC 7.0


[SVN r12472]
2002-01-24 04:06:05 +00:00
51c376c4ee function_base.hpp:
- Fixed for Intel C++, I hope?


[SVN r12469]
2002-01-23 21:17:40 +00:00
8e123d2a97 sum_avg.cpp:
- Portability fix for GCC


[SVN r12464]
2002-01-23 18:24:58 +00:00
58656b40b1 Try to fix for MSVC 7.0
[SVN r12456]
2002-01-23 14:01:28 +00:00
2fa9ee040b Fixes for Intel, added version cutoff for obsolete MWERKS workaround
[SVN r12434]
2002-01-22 13:11:05 +00:00
8635632937 untabified
[SVN r12336]
2002-01-17 15:57:26 +00:00
96f7184528 Untabified
[SVN r12335]
2002-01-17 15:57:13 +00:00
647693dfc9 function_base.hpp:
- Make manager and functor members of function_base public instead of
    protected, because attempt to make HP aCC compile Boost.Function

function_template.hpp:
  - HP aCC seems to believe that the functor and manager members inherited from
    function_base are inaccessible. So qualify them with the function_base
    base class.


[SVN r12298]
2002-01-13 16:12:26 +00:00
d48fa26030 Renamed BOOST_MSVC_ONLY to BOOST_FUNCTION_TARGET_FIX
[SVN r12145]
2001-12-24 17:11:11 +00:00
d3daf6db42 Renamed BOOST_MSVC_ONLY to BOOST_FUNCTION_TARGET_FIX
Metrowerks needs the BOOST_FUNCTION_TARGET_FIX workaround


[SVN r12144]
2001-12-24 17:10:47 +00:00
fb26630e37 index.html:
- Fix "Copying Efficiency" section to not imply that memory is ALWAYS
    allocated on copy.


[SVN r12062]
2001-12-15 01:11:32 +00:00
794b728603 tutorial.html:
- State that ref(...) function objects won't throw during construction,
    either.


[SVN r12061]
2001-12-15 00:58:47 +00:00
ce68cb8999 function_template.hpp:
- Use a C-style cast to deal with constness easily


[SVN r12060]
2001-12-15 00:43:56 +00:00
47599fb625 Added inline modifier to trivial_manager -
without this, some compilers (VC6) generate linker errors,
   in any case it is an ODR violation to define this function
   in every translation unit.


[SVN r11984]
2001-12-09 12:49:09 +00:00
1a7478bbd1 Updated docs to reflect changes in code:
- assignments/constructors that took const F& now take F
  - no need to use &free_function for assignment from free functions, unless
    using MSVC6.5


[SVN r11946]
2001-12-05 23:16:39 +00:00
db5399d447 Remove spurious semicolon
[SVN r11944]
2001-12-05 22:39:33 +00:00
083767f67a Taking function objects by value instead of as references-to-const. This does not work on MSVC6.5, so the BOOST_MSVC_ONLY macro was added to make them references-to-const for only that compiler.
- Borland C++ no longer requires hacks to make function pointers work
- On any compiler other than MSVC, free functions can be assigned to Boost.Function objects without the explicit '&'


[SVN r11943]
2001-12-05 22:35:32 +00:00
8cbd121969 function_base.hpp:
- Add trivial_manager that does nothing but copy object pointers
  - Add is_ref to determine if a type is a reference_wrapper
  - Add function_obj_ref_tag for reference_wrappers
  - Teach get_function_tag about reference_wrappers

function_template.hpp:
  - Add assign_to overload for reference_wrappers (these don't throw)


[SVN r11875]
2001-12-03 16:28:33 +00:00
2e67e2126b reference.html:
- Document semantics of reference_wrapper usage

tutorial.html:
  - Add short discussion and example of ref() and cref()


[SVN r11874]
2001-12-03 16:26:19 +00:00
1512df77b1 function_n_test:
function_test:
  - Add testcases using ref() wrapper


[SVN r11873]
2001-12-03 16:25:00 +00:00
12 changed files with 469 additions and 276 deletions

View File

@ -32,7 +32,7 @@
<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>typedef</b> ResultType result_type;
<b>typedef</b> ResultType result_type; <em>// <a href="#novoid">[1]</a></em>
<b>typedef</b> Policy policy_type;
<b>typedef</b> Mixin mixin_type;
<b>typedef</b> Allocator allocator_type;
@ -45,13 +45,15 @@
<i>// Construction</i>
<a href="#functionN_default"><b>explicit</b> function<i>N</i>(<b>const</b> Mixin<b>&amp;</b> = Mixin())</a>;
<a href="#functionN_copy">function<i>N</i>(<b>const</b> function<i>N</i><b>&amp;</b>)</a>;
<a href="#functionN_target"><b>template</b>&lt;<b>typename</b> F&gt; function<i>N</i>(<b>const</b> F<b>&amp;</b>, <b>const</b> Mixin<b>&amp;</b> = Mixin())</a>;
<a href="#functionN_target"><b>template</b>&lt;<b>typename</b> F&gt; function<i>N</i>(F, <b>const</b> Mixin<b>&amp;</b> = Mixin())</a>;
<a href="#functionN_target_ref"><b>template</b>&lt;<b>typename</b> F&gt; function<i>N</i>(reference_wrapper&lt;F&gt;)</a>;
<i>// Assignment</i>
<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>=(<b>const</b> F<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_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_target_set"><b>template</b>&lt;<b>typename</b> F&gt; <b>void</b> set(<b>const</b> F<b>&amp;</b>)</a>;
<a href="#functionN_target_set"><b>template</b>&lt;<b>typename</b> F&gt; <b>void</b> set(F)</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>;
@ -67,8 +69,8 @@
<b>typename</b> Policy,
<b>typename</b> Mixin,
<b>typename</b> Allocator&gt;
<b>void</b> <a href="#swap_functionN">swap</a>(<b>const</b> function<em>N</em>&lt;Arg1, Arg2, <i>...</i>, Arg<i>N</i>, Policy, Mixin, Allocator&gt;<b>&amp;</b>,
<b>const</b> function<em>N</em>&lt;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>);
// For any <i>N</i> in [0, <i>MAX_ARGS</i>]
<b>template</b>&lt;<b>typename</b> ResultType,
@ -80,21 +82,21 @@
<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;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>
function();
function(<b>const</b> function<b>&amp;</b>);
function<i>N</i>(<b>const</b> function<i>N</i><b>&amp;</b>);
<b>template</b>&lt;<b>typename</b> F&gt; function<i>N</i>(<b>const</b> F<b>&amp;</b>);
function(<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<i>N</i>(F);
<i>// Assignment</i>
function<b>&amp;</b> <b>operator</b>=(<b>const</b> function<b>&amp;</b>);
function<i>N</i><b>&amp;</b> <b>operator</b>=(<b>const</b> function<i>N</i><b>&amp;</b>);
<b>template</b>&lt;<b>typename</b> F&gt; function<b>&amp;</b> <b>operator</b>=(<b>const</b> F<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>void</b> set(<b>const</b> function<b>&amp;</b>);
<b>void</b> set(<b>const</b> function<i>N</i><b>&amp;</b>);
<b>template</b>&lt;<b>typename</b> F&gt; <b>void</b> set(<b>const</b> F<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>);
<b>template</b>&lt;<b>typename</b> F&gt; <b>void</b> set(F);
};
<b>template</b>&lt;<b>typename</b> ResultType,
@ -102,8 +104,8 @@
<b>typename</b> Arg2,
<i>...</i>
<b>typename</b> Arg<i>MAX_ARGS</i>&gt;
<b>void</b> <a href="#swap_function">swap</a>(<b>const</b> function&lt;Arg1, Arg2, <i>...</i>, Arg<i>MAX_ARGS</i>&gt;<b>&amp;</b>,
<b>const</b> function&lt;Arg1, Arg2, <i>...</i>, Arg<i>MAX_ARGS</i>&gt;<b>&amp;</b>);
<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>
@ -126,22 +128,13 @@
</pre>
<p> A special provision is made for pointers to member functions. Though they are not function objects, Boost.Function will adapt them internally to function objects. This requires that a pointer to member function of the form <code>R (X::*mf)(Arg1, Arg2, ..., Arg<em>N</em>) <em>cv-quals</em></code> be adapted to a function object with the following function call operator overloads:
<pre>
R <b>operator</b>()(<em>cv-quals</em> X&amp; x, Arg1 arg1, Arg2 arg2, ..., Arg<em>N</em> arg<em>N</em>) <b>const</b>
{
<b>return</b> x.*mf(arg1, arg2, ..., arg<em>N</em>);
}
R <b>operator</b>()(<em>cv-quals</em> X* x, Arg1 arg1, Arg2 arg2, ..., Arg<em>N</em> arg<em>N</em>) <b>const</b>
{
<b>return</b> x->*mf(arg1, arg2, ..., arg<em>N</em>);
}
<b>template</b>&lt;<b>typename P</b>&gt;
R <b>operator</b>()(<em>cv-quals</em> P&amp; x, Arg1 arg1, Arg2 arg2, ..., Arg<em>N</em> arg<em>N</em>) <b>const</b>
{
<b>return</b> (*x).*mf(arg1, arg2, ..., arg<em>N</em>);
}
</pre>
<li><a name="stateless"></a>A function object <code>f</code> of type <code>F</code> is <em>stateless</em> if it is a function pointer or if <a href="../../type_traits/index.htm#properties"><code>boost::is_stateless&lt;T&gt;</code></a> is true. The construction of or copy to a Boost.Function object from a stateless function object will not cause exceptions to be thrown and will not allocate any storage.</li>
</ul>
<h2><a name="function_base">Class <code>function_base</code></a></h2>
@ -174,34 +167,52 @@
<ul>
<li><b>Effects</b>: Constructs the <code>Mixin</code> subobject with the given mixin.</li>
<li><b>Postconditions</b>: <code>f.<a href="#empty">empty</a>()</code>.</li>
<li><b>Throws</b>: will not throw.</li>
<li><b>Throws</b>: will not throw unless construction of the <code>Mixin</code> subobject throws.</li>
</ul>
<p> <a name="functionN_copy"><code>function<i>N</i>(<b>const</b> function<i>N</i><b>&amp;</b> g);</code></a>
<ul>
<li><b>Postconditions</b>: <code>f</code> contains a copy of the <code>g</code>'s target, if it has one, or is empty if <code>g.<a href="#empty">empty</a>()</code>. The mixin for the <code>f</code> is copy-constructed from the mixin of <code>g</code>.</li>
<li><b>Throws</b>: will not throw unless copying the target of <code>g</code> or construction of the <code>Mixin</code> subobject throws.</li>
</ul>
<p> <a name="functionN_target"><code><b>template</b>&lt;<b>typename</b> F&gt; function<i>N</i>(<b>const</b> F<b>&amp;</b> g, <b>const</b> Mixin<b>&amp;</b> = Mixin());</code></a>
<p> <a name="functionN_target"><code><b>template</b>&lt;<b>typename</b> F&gt; function<i>N</i>(F g, <b>const</b> Mixin<b>&amp;</b> = Mixin());</code></a>
<ul>
<li><b>Requires</b>: <code>g</code> is a <a href="#compatible">compatible</a> function object.</li>
<li><b>Effects</b>: Constructs the <code>Mixin</code> subobject from the given mixin.</li>
<li><b>Postconditions</b>: <code>f</code> targets a copy of <code>g</code> if <code>g</code> is nonempty, or <code>f.<a href="#empty">empty</a>()</code> if <code>g</code> is empty.</li>
<li><b>Rationale</b>: <code>g</code> is a reference-to-<code><b>const</b></code> because it is a portable, efficient, and concise way to accept any function object or function pointer. In the case of a function pointer, the type of <code>g</code> is reference-to-<code><b>const</b></code> pointer-to-function.</li>
<li><b>Throws</b>: will not throw when <code>g</code> is a <a href="#stateless">stateless</a> function object unless construction of the <code>Mixin</code> subobject throws.</li>
</ul>
<p> <a name="functionN_target_ref"><code><b>template</b>&lt;<b>typename</b> F&gt; function<i>N</i>(<a href="../../bind/ref.html">reference_wrapper</a>&lt;F&gt; g);</code></a>
<ul>
<li><b>Requires</b>: <code>g.get()</code> is a <a href="#compatible">compatible</a> function object.</li>
<li><b>Effects</b>: Constructs the <code>Mixin</code> subobject from the given mixin.</li>
<li><b>Postconditions</b>: <code>this</code> object targets <code>g</code> (<em>not</em> a copy of <code>g.get()</code>) if <code>g.get()</code> is nonempty, or <code>this-&gt;empty()</code> if <code>g.get()</code> is empty.</li>
<li><b>Throws</b>: will not throw unless the construction of the <code>Mixin</code> subobject throws.</li>
</ul>
<p> <a name="functionN_copy_assn"><code>function<i>N</i><b>&amp;</b> <b>operator</b>=(<b>const</b> function<i>N</i><b>&amp;</b> g);</code></a>
<ul>
<li><b>Postconditions</b>: <code>f</code> targets a copy of <code>g</code>'s target, if it has one, or is empty if <code>g.<a href="#empty">empty</a>()</code>. The mixin for <code>f</code> is assigned the value of the mixin for <code>g</code>.</li>
<li><b>Returns</b>: <code>*this</code>.</li>
<li><b>Throws</b>: will not throw when the target of <code>g</code> is a <a href="#stateless">stateless</a> function object or a reference to the function object, unless the copy of the <code>Mixin</code> subobject throws.</li>
</ul>
<p> <a name="functionN_target_assn"><code><b>template</b>&lt;<b>typename</b> F&gt; function<i>N</i><b>&amp;</b> <b>operator</b>=(<b>const</b> F<b>&amp;</b> g);</code></a>
<p> <a name="functionN_target_assn"><code><b>template</b>&lt;<b>typename</b> F&gt; function<i>N</i><b>&amp;</b> <b>operator</b>=(F g);</code></a>
<ul>
<li><b>Requires</b>: <code>g</code> is a <a href="#compatible">compatible</a> function object.</li>
<li><b>Postconditions</b>: <code>f</code> targets a copy of <code>g</code> if <code>g</code> is nonempty, or <code>f.<a href="#empty">empty</a>()</code> if <code>g</code> is empty.</li>
<li><b>Returns</b>: <code>*this</code>.</li>
<li><b>Rationale</b>: <code>g</code> is a reference-to-<code><b>const</b></code> because it is a portable, efficient, and concise way to accept any function object or function pointer. In the case of a function pointer, the type of <code>g</code> is reference-to-<code><b>const</b></code> pointer-to-function.</li>
<li><b>Throws</b>: will not throw when <code>g</code> is a <a href="#stateless">stateless</a> function object.</li>
</ul>
<p> <a name="functionN_target_ref_assn"><code><b>template</b>&lt;<b>typename</b> F&gt; function<i>N</i><b>&amp;</b> <b>operator</b>=(<a href="../../bind/ref.html">reference_wrapper</a>&lt;F&gt; g);</code></a>
<ul>
<li><b>Requires</b>: <code>g.get()</code> is a <a href="#compatible">compatible</a> function object.</li>
<li><b>Postconditions</b>: <code>f</code> targets <code>g.get()</code> (not a copy of <code>g.get()</code>) if <code>g.get()</code> is nonempty, or <code>f.<a href="#empty">empty</a>()</code> if <code>g.get()</code> is empty.</li>
<li><b>Returns</b>: <code>*this</code>.</li>
<li><b>Throws</b>: will throw only if the destruction or deallocation of the target of <code>this</code> throws.</li>
</ul>
<p> <a name="functionN_copy_set"><code><b>void</b> set(<b>const</b> function<i>N</i><b>&amp;</b> g);</code></a>
@ -209,7 +220,7 @@
<li><b>Effects</b>: <code><a href="#functionN_copy_assn">*this = g</a></code>.</li>
</ul>
<p> <a name="functionN_target_set"><code><b>template</b>&lt;<b>typename</b> F&gt; <b>void</b> set(<b>const</b> F<b>&amp;</b> 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>
<li><b>Effects</b>: <code><a href="#functionN_target_assn">*this = g</a></code>.</li>
</ul>
@ -255,8 +266,8 @@
<b>typename</b> Policy,
<b>typename</b> Mixin,
<b>typename</b> Allocator&gt;
<b>void</b> <a name="swap_functionN">swap</a>(<b>const</b> function<i>N</i>&lt;Arg1, Arg2, <i>...</i>, Arg<i>N</i>, Policy, Mixin, Allocator&gt;<b>&amp;</b> f,
<b>const</b> function<i>N</i>&lt;Arg1, Arg2, <i>...</i>, Arg<i>N</i>, Policy, Mixin, Allocator&gt;<b>&amp;</b> g);
<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);
</pre>
<ul>
<li><b>Effects</b>: <code>f.<a href="#functionN_swap">swap</a>(g);</code></li>
@ -269,18 +280,20 @@
<b>typename</b> Arg2,
<i>...</i>
<b>typename</b> Arg<i>MAX_ARGS</i>&gt;
<b>void</b> <a name="swap_function">swap</a>(<b>const</b> function&lt;Arg1, Arg2, <i>...</i>, Arg<i>MAX_ARGS</i>&gt;<b>&amp;</b> f,
<b>const</b> function&lt;Arg1, Arg2, <i>...</i>, Arg<i>MAX_ARGS</i>&gt;<b>&amp;</b> g);
<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>
<ul>
<li><b>Effects</b>: <code>f.<a href="#functionN_swap">swap</a>(g);</code></li>
</ul>
<hr>
<p><a name="novoid">[1]</a> On compilers not supporting void returns, when the <code>ReturnType</code> is <b>void</b>, the <code>result_type</code> of a Boost.Function object is implementation-defined.
<hr>
<address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address>
<!-- Created: Fri Jul 13 10:57:20 EDT 2001 -->
<!-- hhmts start -->
Last modified: Sun Oct 28 00:40:55 EDT 2001
Last modified: Thu Jan 31 21:55:35 EST 2002
<!-- hhmts end -->
</body>
</html>

View File

@ -60,9 +60,11 @@ else
<p> Free function pointers can be considered singleton function objects with const function call operators, and can therefore be directly used with the function object wrappers:
<pre>
float mul_ints(int x, int y) { return ((float)x) * y; }
f = &mul_ints;
f = &amp;mul_ints;
</pre>
<p> Note that the <code>&amp;</code> isn't really necessary unless you happen to be using Microsoft Visual C++ version 6.
<h3>Member functions</h3>
<a name="member_func">
<p> In many systems, callbacks often call to member functions of a particular
@ -73,10 +75,10 @@ object. This is often referred to as "argument binding", and is beyond the scope
};
boost::function&lt;int, X*, int&gt; f;
f = &X::foo;
f = &amp;X::foo;
X x;
f(&x, 5);
f(&amp;x, 5);
</pre>
<p> Several libraries exist that support argument binding. Three such libraries are summarized below:
<ul>
@ -94,9 +96,33 @@ object. This is often referred to as "argument binding", and is beyond the scope
f(5); // Call x.foo(5)</pre></li>
<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>
<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>
<h3>References to Functions</h3>
<p> In some cases it is expensive (or semantically incorrect) to have
Boost.Function clone a function object. In such cases, it is possible
to request that Boost.Function keep only a reference to the actual
function object. This is done using the <a
href="../../bind/ref.html"><code>ref</code></a> and <a
href="../../bind/ref.html"><code>cref</code></a> functions to wrap a
reference to a function object:
<pre>
stateful_type a_function_object;
boost::function&lt;int, int&gt; f;
f = ref(a_function_object);
boost::function&lt;int, int&gt; f2(f);
</pre>
Here, <code>f</code> will not make a copy of
<code>a_function_object</code>, nor will <code>f2</code> when it is
targeted to <code>f</code>'s reference to
<code>a_function_object</code>. Additionally, when using references to
function objects, Boost.Function will not throw exceptions during
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>
@ -173,7 +199,7 @@ boost::function2&lt;float, int, int, SynchronizedPolicy, SynchronizedMixin&gt; f
<address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address>
<!-- Created: Fri Jul 13 12:47:11 EDT 2001 -->
<!-- hhmts start -->
Last modified: Sun Oct 28 00:49:02 EDT 2001
Last modified: Mon May 13 08:31:23 EDT 2002
<!-- hhmts end -->
</body>
</html>

View File

@ -27,7 +27,9 @@ void do_sum_avg(int values[], int n, int& sum, float& avg)
int
main()
{
boost::function<void, int[], int, int&, float&> sum_avg;
// The second parameter should be int[], but some compilers (e.g., GCC)
// complain about this
boost::function<void, int*, int, int&, float&> sum_avg;
sum_avg = &do_sum_avg;

View File

@ -53,9 +53,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
typename Policy,
typename Mixin,
typename Allocator
>
struct params
{
@ -78,9 +78,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
typename Policy,
typename Mixin,
typename Allocator
>
struct params
{
@ -103,9 +103,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
typename Policy,
typename Mixin,
typename Allocator
>
struct params
{
@ -128,9 +128,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
typename Policy,
typename Mixin,
typename Allocator
>
struct params
{
@ -153,9 +153,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
typename Policy,
typename Mixin,
typename Allocator
>
struct params
{
@ -178,9 +178,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
typename Policy,
typename Mixin,
typename Allocator
>
struct params
{
@ -204,9 +204,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
typename Policy,
typename Mixin,
typename Allocator
>
struct params
{
@ -230,9 +230,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
typename Policy,
typename Mixin,
typename Allocator
>
struct params
{
@ -256,9 +256,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
typename Policy,
typename Mixin,
typename Allocator
>
struct params
{
@ -282,9 +282,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
typename Policy,
typename Mixin,
typename Allocator
>
struct params
{
@ -308,9 +308,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
typename Policy,
typename Mixin,
typename Allocator
>
struct params
{
@ -456,56 +456,35 @@ namespace boost {
function() : base_type() {}
template<typename Functor>
function(const Functor& f) : base_type(f) {}
function(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) : base_type(f) {}
#ifdef __BORLANDC__
template<typename Functor> function(Functor* f) : base_type(f) {}
#endif // __BORLANDC__
function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
template<typename Functor>
function& operator=(const Functor& f)
self_type& operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{
self_type(f).swap(*this);
return *this;
}
#ifdef __BORLANDC__
template<typename Functor>
self_type& operator=(Functor* f)
{
self_type(f).swap(*this);
return *this;
}
#endif // __BORLANDC__
self_type& operator=(const base_type& f)
{
self_type(f).swap(*this);
return *this;
}
self_type& operator=(const self_type& f)
self_type& operator=(const self_type& f)
{
self_type(f).swap(*this);
return *this;
}
return *this;
}
template<typename Functor>
void set(const Functor& f)
void set(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{
self_type(f).swap(*this);
}
#ifdef __BORLANDC__
template<typename Functor>
void set(Functor* f)
{
self_type(f).swap(*this);
}
#endif // __BORLANDC__
void set(const base_type& f)
{
self_type(f).swap(*this);

View File

@ -23,12 +23,21 @@
#include <typeinfo>
#include <boost/config.hpp>
#include <boost/type_traits.hpp>
#include <boost/ref.hpp>
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406
# define BOOST_FUNCTION_TARGET_FIX(x) x
#else
# define BOOST_FUNCTION_TARGET_FIX(x)
#endif // not MSVC
namespace boost {
namespace detail {
namespace function {
template<bool> struct truth {};
/*
* The IF implementation is temporary code. When a Boost metaprogramming
* The ct_if implementation is temporary code. When a Boost metaprogramming
* library is introduced, Boost.Function will use it instead.
*/
namespace intimate {
@ -64,7 +73,7 @@ namespace boost {
} // end namespace intimate
template<bool Condition, typename Then, typename Else>
struct IF
struct ct_if
{
typedef typename intimate::Selector<Condition>::type select;
typedef typename select::template Result<Then,Else>::type type;
@ -122,20 +131,41 @@ namespace boost {
struct function_ptr_tag {};
struct function_obj_tag {};
struct member_ptr_tag {};
struct function_obj_ref_tag {};
struct stateless_function_obj_tag {};
template<typename F>
class get_function_tag
{
typedef typename IF<(is_pointer<F>::value),
typedef typename ct_if<(is_pointer<F>::value),
function_ptr_tag,
function_obj_tag>::type ptr_or_obj_tag;
typedef typename ct_if<(is_member_pointer<F>::value),
member_ptr_tag,
ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
typedef typename ct_if<(is_reference_wrapper<F>::value),
function_obj_ref_tag,
ptr_or_obj_or_mem_tag>::type or_ref_tag;
public:
typedef typename IF<(is_member_pointer<F>::value),
member_ptr_tag,
ptr_or_obj_tag>::type type;
typedef typename ct_if<(is_stateless<F>::value),
stateless_function_obj_tag,
or_ref_tag>::type type;
};
// The trivial manager does nothing but return the same pointer (if we
// are cloning) or return the null pointer (if we are deleting).
inline any_pointer trivial_manager(any_pointer f,
functor_manager_operation_type op)
{
if (op == clone_functor_tag)
return f;
else
return any_pointer(reinterpret_cast<void*>(0));
}
/**
* The functor_manager class contains a static function "manage" which
* can clone or destroy the given function/function object pointer.
@ -148,7 +178,8 @@ namespace boost {
// For function pointers, the manager is trivial
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)
{
if (op == clone_functor_tag)
@ -273,12 +304,16 @@ namespace boost {
// Is this function empty?
bool empty() const { return !manager; }
protected:
public: // should be protected, but GCC 2.95.3 will fail to allow access
detail::function::any_pointer (*manager)(
detail::function::any_pointer,
detail::function::functor_manager_operation_type);
detail::function::any_pointer functor;
#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:
struct dummy {
void nonnull() {};
@ -292,6 +327,7 @@ namespace boost {
safe_bool operator!() const
{ return (this->empty())? &dummy::nonnull : 0; }
#endif
};
/* Poison comparison between Boost.Function objects (because it is
@ -305,92 +341,14 @@ namespace boost {
namespace detail {
namespace function {
/**
* Determine if the given target is 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();
inline bool has_empty_target(const function_base* f)
{
return f->empty();
}
// If the target is a 'function', query the empty() method
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)())
inline bool has_empty_target(...)
{
return f == 0;
}
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;
return false;
}
} // end namespace function
} // end namespace detail
@ -402,14 +360,18 @@ namespace boost {
inline void postcall(const function_base*) {}
};
// The default function mixin does nothing. The assignment and copy-construction operators
// are all defined because MSVC defines broken versions.
struct empty_function_mixin {
empty_function_mixin() {};
empty_function_mixin(const empty_function_mixin&) {};
// The default function mixin does nothing. The assignment and
// copy-construction operators are all defined because MSVC defines broken
// versions.
struct empty_function_mixin
{
empty_function_mixin() {}
empty_function_mixin(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
#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 \
BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
@ -50,10 +49,16 @@
BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(stateless_void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(get_stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
namespace boost {
namespace detail {
@ -101,7 +106,7 @@ namespace boost {
BOOST_FUNCTION_PARMS)
{
FunctionObj* f = static_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
return (*f)(BOOST_FUNCTION_ARGS);
}
};
@ -118,12 +123,43 @@ namespace boost {
BOOST_FUNCTION_PARMS)
{
FunctionObj* f = static_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
(*f)(BOOST_FUNCTION_ARGS);
return unusable();
}
};
template<
typename FunctionObj,
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
{
static R invoke(any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS)
{
FunctionObj f = FunctionObj();
return f(BOOST_FUNCTION_ARGS);
}
};
template<
typename FunctionObj,
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
{
static unusable invoke(any_pointer BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
FunctionObj f = FunctionObj();
f(BOOST_FUNCTION_ARGS);
return unusable();
}
};
template<
typename FunctionPtr,
typename R BOOST_FUNCTION_COMMA
@ -131,7 +167,7 @@ namespace boost {
>
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<
FunctionPtr,
R BOOST_FUNCTION_COMMA
@ -152,7 +188,7 @@ namespace boost {
>
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<
FunctionObj,
R BOOST_FUNCTION_COMMA
@ -165,6 +201,28 @@ namespace boost {
>
>::type type;
};
template<
typename FunctionObj,
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
{
typedef typename ct_if<(is_void<R>::value),
BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>,
BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
>::type type;
};
} // end namespace function
} // end namespace detail
@ -177,6 +235,9 @@ namespace boost {
>
class BOOST_FUNCTION_FUNCTION : public function_base, public Mixin
{
typedef typename detail::function::function_return_type<R>::type
internal_result_type;
public:
BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
@ -186,8 +247,12 @@ namespace boost {
typedef T0 first_argument_type;
typedef T1 second_argument_type;
#endif
typedef typename detail::function::function_return_type<R>::type
result_type;
#ifndef BOOST_NO_VOID_RETURNS
typedef R result_type;
#else
typedef internal_result_type result_type;
#endif // BOOST_NO_VOID_RETURNS
typedef Policy policy_type;
typedef Mixin mixin_type;
typedef Allocator allocator_type;
@ -203,23 +268,14 @@ namespace boost {
// MSVC chokes if the following two constructors are collapsed into
// one with a default parameter.
template<typename Functor>
BOOST_FUNCTION_FUNCTION(const Functor& f) :
BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) :
function_base(), Mixin(), invoker(0)
{
this->assign_to(f);
}
#ifdef __BORLANDC__
template<typename Functor>
BOOST_FUNCTION_FUNCTION(Functor* f) :
function_base(), Mixin(), invoker(0)
{
this->assign_to(f);
}
#endif // __BORLANDC__
template<typename Functor>
BOOST_FUNCTION_FUNCTION(const Functor& f, const Mixin& m) :
BOOST_FUNCTION_FUNCTION(Functor f, const Mixin& m) :
function_base(), Mixin(m), invoker(0)
{
this->assign_to(f);
@ -240,11 +296,16 @@ namespace boost {
policy_type policy;
policy.precall(this);
result_type result = invoker(functor BOOST_FUNCTION_COMMA
BOOST_FUNCTION_ARGS);
internal_result_type result = invoker(function_base::functor
BOOST_FUNCTION_COMMA
BOOST_FUNCTION_ARGS);
policy.postcall(this);
#ifndef BOOST_NO_VOID_RETURNS
return static_cast<result_type>(result);
#else
return result;
#endif // BOOST_NO_VOID_RETURNS
}
// The distinction between when to use BOOST_FUNCTION_FUNCTION and
@ -253,35 +314,19 @@ namespace boost {
// handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
// construct.
template<typename Functor>
BOOST_FUNCTION_FUNCTION& operator=(const Functor& f)
BOOST_FUNCTION_FUNCTION&
operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{
self_type(f, static_cast<const Mixin&>(*this)).swap(*this);
return *this;
}
#ifdef __BORLANDC__
template<typename Functor>
BOOST_FUNCTION_FUNCTION& operator=(Functor* f)
{
self_type(f, static_cast<const Mixin&>(*this)).swap(*this);
return *this;
}
#endif // __BORLANDC__
template<typename Functor>
void set(const Functor& f)
void set(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{
self_type(f, static_cast<const Mixin&>(*this)).swap(*this);
}
#ifdef __BORLANDC__
template<typename Functor>
void set(Functor* f)
{
self_type(f, static_cast<const Mixin&>(*this)).swap(*this);
}
#endif // __BORLANDC__
// Assignment from another BOOST_FUNCTION_FUNCTION
BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
{
@ -306,8 +351,8 @@ namespace boost {
if (&other == this)
return;
std::swap(manager, other.manager);
std::swap(functor, other.functor);
std::swap(function_base::manager, other.manager);
std::swap(function_base::functor, other.functor);
std::swap(invoker, other.invoker);
std::swap(static_cast<Mixin&>(*this), static_cast<Mixin&>(other));
}
@ -315,10 +360,13 @@ namespace boost {
// Clear out a target, if there is one
void clear()
{
if (manager)
functor = manager(functor, detail::function::destroy_functor_tag);
manager = 0;
if (function_base::manager) {
function_base::functor =
function_base::manager(function_base::functor,
detail::function::destroy_functor_tag);
}
function_base::manager = 0;
invoker = 0;
}
@ -327,13 +375,14 @@ namespace boost {
{
if (!f.empty()) {
invoker = f.invoker;
manager = f.manager;
functor = f.manager(f.functor, detail::function::clone_functor_tag);
function_base::manager = f.manager;
function_base::functor =
f.manager(f.functor, detail::function::clone_functor_tag);
}
}
template<typename Functor>
void assign_to(const Functor& f)
void assign_to(Functor f)
{
typedef typename detail::function::get_function_tag<Functor>::type tag;
this->assign_to(f, tag());
@ -353,10 +402,13 @@ namespace boost {
invoker_type;
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<FunctionPtr,
Allocator>::manage;
functor = manager(detail::function::any_pointer(
reinterpret_cast<void (*)()>(f)
function_base::manager =
&detail::function::functor_manager<FunctionPtr, Allocator>::manage;
function_base::functor =
function_base::manager(detail::function::any_pointer(
// should be a reinterpret cast, but some compilers
// insist on giving cv-qualifiers to free functions
(void (*)())(f)
),
detail::function::clone_functor_tag);
}
@ -371,9 +423,9 @@ namespace boost {
#endif // BOOST_FUNCTION_NUM_ARGS > 0
template<typename FunctionObj>
void assign_to(const 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
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
@ -383,17 +435,68 @@ namespace boost {
invoker_type;
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<FunctionObj,
Allocator>::manage;
functor =
manager(detail::function::any_pointer(const_cast<FunctionObj*>(&f)),
detail::function::clone_functor_tag);
function_base::manager = &detail::function::functor_manager<
FunctionObj, Allocator>::manage;
#ifndef BOOST_NO_STD_ALLOCATOR
typedef typename Allocator::template rebind<FunctionObj>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
allocator.construct(copy, f);
// Get back to the original pointer type
FunctionObj* new_f = static_cast<FunctionObj*>(copy);
#else
FunctionObj* new_f = new FunctionObj(f);
#endif // BOOST_NO_STD_ALLOCATOR
function_base::functor =
detail::function::any_pointer(static_cast<void*>(new_f));
}
}
typedef result_type (*invoker_type)(detail::function::any_pointer
BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS);
template<typename FunctionObj>
void assign_to(const reference_wrapper<FunctionObj>& f,
detail::function::function_obj_ref_tag)
{
if (!detail::function::has_empty_target(f.get_pointer())) {
typedef
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
invoker = &invoker_type::invoke;
function_base::manager = &detail::function::trivial_manager;
function_base::functor =
function_base::manager(
detail::function::any_pointer(
const_cast<FunctionObj*>(f.get_pointer())),
detail::function::clone_functor_tag);
}
}
template<typename FunctionObj>
void assign_to(FunctionObj, detail::function::stateless_function_obj_tag)
{
typedef
typename detail::function::
BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
invoker = &invoker_type::invoke;
function_base::manager = &detail::function::trivial_manager;
function_base::functor = detail::function::any_pointer(this);
}
typedef internal_result_type (*invoker_type)(detail::function::any_pointer
BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS);
invoker_type invoker;
};
@ -423,13 +526,13 @@ namespace boost {
#undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
#undef BOOST_FUNCTION_COMMA
#undef BOOST_FUNCTION_FUNCTION
#undef BOOST_FUNCTION_BASE
#undef BOOST_FUNCTION_INVOKER_BASE
#undef BOOST_FUNCTION_FUNCTION_INVOKER
#undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
#undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER

View File

@ -50,7 +50,7 @@ And, of course, function pointers have several advantages over Boost.Function:
<p> Function object wrappers will be the size of two function pointers plus one function pointer or data pointer (whichever is larger). On common 32-bit platforms, this amounts to 12 bytes per wrapper. Additionally, the function object target will be allocated on the heap.
<h3>Copying efficiency</h3>
<p> Copying function object wrappers requires allocating member for a copy of the function object target. The default allocator may be replaced with a faster custom allocator if the cost of this cloning becomes prohibitive.
<p> Copying function object wrappers may require allocating memory for a copy of the function object target. The default allocator may be replaced with a faster custom allocator or one may choose to allow the function object wrappers to only store function object targets by reference (using <a href="../bind/ref.html"><code>ref</code></a>) if the cost of this cloning becomes prohibitive.
<h3>Invocation efficiency</h3>
<p> With a properly inlining compiler, an invocation of a function object requires one call through a function pointer. If the call is to a free function pointer, an additional call must be made to that function pointer (unless the compiler has very powerful interprocedural analysis).

View File

@ -102,7 +102,7 @@ test_zero_args()
BOOST_TEST(v1.empty());
// Assignment to an empty function from a free function
v1 = &write_five;
v1 = write_five;
BOOST_TEST(!v1.empty());
// Invocation
@ -129,7 +129,7 @@ test_zero_args()
BOOST_TEST(global_int == 5);
// Assignment to a non-empty function from a free function
v1 = &write_three;
v1 = write_three;
BOOST_TEST(!v1.empty());
// Invocation
@ -604,6 +604,35 @@ test_member_functions()
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::function2<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();
@ -611,5 +640,6 @@ int test_main(int, char* [])
test_two_args();
test_emptiness();
test_member_functions();
test_ref();
return 0;
}

View File

@ -102,7 +102,7 @@ test_zero_args()
BOOST_TEST(v1.empty());
// Assignment to an empty function from a free function
v1 = &write_five;
v1 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
BOOST_TEST(!v1.empty());
// Invocation
@ -111,7 +111,7 @@ test_zero_args()
BOOST_TEST(global_int == 5);
// Assignment to a non-empty function from a free function
v1 = &write_three;
v1 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
BOOST_TEST(!v1.empty());
// Invocation
@ -163,7 +163,7 @@ test_zero_args()
BOOST_TEST(v2.empty());
// Assignment to an empty function from a free function
v2.set(&write_five);
v2.set(BOOST_FUNCTION_TARGET_FIX(&) write_five);
BOOST_TEST(v2);
// Invocation
@ -172,7 +172,7 @@ test_zero_args()
BOOST_TEST(global_int == 5);
// Assignment to a non-empty function from a free function
v2 = &write_three;
v2 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
BOOST_TEST(!v2.empty());
// Invocation
@ -227,7 +227,7 @@ test_zero_args()
BOOST_TEST(global_int == 3);
// Assign to a function from a function with a function
v2 = &write_five;
v2 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
v1 = v2;
BOOST_TEST(!v1.empty());
BOOST_TEST(!v2.empty());
@ -603,6 +603,35 @@ test_member_functions()
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();
@ -610,5 +639,7 @@ int test_main(int, char* [])
test_two_args();
test_emptiness();
test_member_functions();
test_ref();
return 0;
}

View File

@ -20,7 +20,7 @@
#include <boost/function.hpp>
struct id_mixin
{
{
id_mixin(const id_mixin& rhs) : id(rhs.id) {}
id_mixin& operator=(const id_mixin& rhs){id = rhs.id; return *this;}
id_mixin(int i = 0){ id = i;}
@ -49,12 +49,12 @@ int test_main(int, char*[])
f.id = 21;
BOOST_TEST(f.id == 21);
boost::swap(f,g);
BOOST_TEST(f.id == 7);
BOOST_TEST(g.id == 21);
g = f;
g = f;
BOOST_TEST(g.id == 7);
return 0;
}

View File

@ -11,4 +11,4 @@ compile-fail libs/function/test/function_test_fail1.cpp
compile-fail libs/function/test/function_test_fail2.cpp
run libs/function/test/mixin_test.cpp
run libs/function/test/policy_test.cpp
run libs/function/test/stateless_test.cpp

47
test/stateless_test.cpp Normal file
View File

@ -0,0 +1,47 @@
// 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 <stdexcept>
struct stateless_integer_add {
int operator()(int x, int y) const { return x+y; }
void* operator new(std::size_t, stateless_integer_add*)
{
throw std::runtime_error("Cannot allocate a stateless_integer_add");
}
void operator delete(void*, stateless_integer_add*)
{
}
};
namespace boost {
template<>
struct is_stateless<stateless_integer_add> {
BOOST_STATIC_CONSTANT(bool, value = true);
};
}
int test_main(int, char*[])
{
boost::function<int, int, int> f;
f = stateless_integer_add();
return 0;
}