1071 lines
68 KiB
HTML
1071 lines
68 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
|
<title>Annex: Alternatives</title>
|
|
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
|
|
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
|
|
<link rel="home" href="../index.html" title="Chapter 1. Boost.LocalFunction 1.0.0">
|
|
<link rel="up" href="../index.html" title="Chapter 1. Boost.LocalFunction 1.0.0">
|
|
<link rel="prev" href="examples.html" title="Examples">
|
|
<link rel="next" href="no_variadic_macros.html" title="Annex: No Variadic Macros">
|
|
</head>
|
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
|
<table cellpadding="2" width="100%"><tr>
|
|
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
|
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
|
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
|
|
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
|
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
|
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
|
</tr></table>
|
|
<hr>
|
|
<div class="spirit-nav">
|
|
<a accesskey="p" href="examples.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="no_variadic_macros.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
|
<a name="boost_localfunction.alternatives"></a><a class="link" href="alternatives.html" title="Annex: Alternatives">Annex: Alternatives</a>
|
|
</h2></div></div></div>
|
|
<p>
|
|
This section compares the features offered by this library with similar features
|
|
offered by C++ and by other libraries.
|
|
</p>
|
|
<h4>
|
|
<a name="boost_localfunction.alternatives.h0"></a>
|
|
<span class="phrase"><a name="boost_localfunction.alternatives.features"></a></span><a class="link" href="alternatives.html#boost_localfunction.alternatives.features">Features</a>
|
|
</h4>
|
|
<p>
|
|
The following table compares local function features.
|
|
</p>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup>
|
|
<col>
|
|
<col>
|
|
<col>
|
|
<col>
|
|
<col>
|
|
<col>
|
|
</colgroup>
|
|
<thead><tr>
|
|
<th>
|
|
<p>
|
|
Local Function Feature
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
Boost.LocalFunction
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
C++11 Lambda Function (Not C++03)
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
Local Functor
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
Global Functor (Not Local)
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
Boost.Phoenix
|
|
</p>
|
|
</th>
|
|
</tr></thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<span class="emphasis"><em>Can be defined locally</em></span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
No. Therefore this not really an alternative implementation of local
|
|
functions but it is listed here just for comparison.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes.
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<span class="emphasis"><em>Can be defined using C++ statement syntax</em></span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes. Plus eventual compiler errors and debugging retain their usual
|
|
meaning and format.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes. Plus eventual compiler errors and debugging retain their usual
|
|
meaning and format.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes. Plus eventual compiler errors and debugging retain their usual
|
|
meaning and format.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes. Plus eventual compiler errors and debugging retain their usual
|
|
meaning and format.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
No (it uses C++ <a href="http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Expression-template" target="_top">expression
|
|
template</a> syntax).
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<span class="emphasis"><em>Can be defined within expressions</em></span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
No. It can be defined only within declarations.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes (plus the local function can be unnamed).
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
No. It can be defined only within declarations.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
No. It can be defined only within declarations.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes (plus the local function can be unnamed).
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<span class="emphasis"><em>Can be passed as template parameter (e.g., to STL algorithms)</em></span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes. The <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/standards" target="_top">C++03</a>
|
|
standard does not allow to pass local types as template parameters
|
|
(see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm" target="_top">[N2657]</a>)
|
|
but this library implements a "trick" to get around this
|
|
limitation (see the <a class="link" href="implementation.html" title="Annex: Implementation">Implementation</a>
|
|
section).
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
No on <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/standards" target="_top">C++03</a>
|
|
compilers (but yes on <a href="http://www.open-std.org/JTC1/SC22/WG21/" target="_top">C++11</a>
|
|
compilers and some compilers like MSVC 8.0, see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm" target="_top">[N2657]</a>).
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes.
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<span class="emphasis"><em>Access variables in scope</em></span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes. The variable names are repeated in the function declaration
|
|
so they can be bound by value, by constant value, by reference, and
|
|
by constant reference (the object <code class="computeroutput"><span class="keyword">this</span></code>
|
|
can also be bound using <code class="computeroutput"><span class="identifier">this_</span></code>).
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes. The variable names are repeated in the function declaration
|
|
(plus there is a short-hand syntax to bind all variables in scope
|
|
at once) so they can be bound by constant value and by reference
|
|
(the object <code class="computeroutput"><span class="keyword">this</span></code> can
|
|
also be bound). However, variables cannot be bound by constant references
|
|
(see below).
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
No. Programmers must manually program functor data members and explicitly
|
|
specify their types to access variables in scope.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
No. Programmers must manually program functor data members and explicitly
|
|
specify their types to access variables in scope.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes. Variables in scope are accessible as usual within expressions
|
|
(plus <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">let</span></code> can be used to bind variables
|
|
by constant reference).
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<span class="emphasis"><em><a href="http://en.wikipedia.org/wiki/Type_polymorphism#Parametric_polymorphism" target="_top">Polymorphic</a>
|
|
in the function parameter type</em></span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
No (local functions cannot be function templates).
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
No (<a href="http://www.open-std.org/JTC1/SC22/WG21/" target="_top">C++11</a>
|
|
lambdas cannot be function templates).
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
No (local classes cannot have member function templates).
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes.
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Yes.
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table></div>
|
|
<p>
|
|
<span class="bold"><strong>C++11 Lambda Function</strong></span>
|
|
</p>
|
|
<p>
|
|
<a href="http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions" target="_top">C++11
|
|
lambda functions</a> have most of the features of this library plus some
|
|
additional feature (see also the example in the <a class="link" href="../index.html#boost_localfunction.introduction" title="Introduction">Introduction</a>
|
|
section):
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
<a href="http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions" target="_top">C++11
|
|
lambda functions</a> can be defined within expressions while this library
|
|
local functions can only be defined at declaration scope.
|
|
</li>
|
|
<li class="listitem">
|
|
<a href="http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions" target="_top">C++11
|
|
lambda functions</a> are only supported by the <a href="http://www.open-std.org/JTC1/SC22/WG21/" target="_top">C++11</a>
|
|
standard so they are not supported by all C++ compilers. This library local
|
|
functions can be programmed also on <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/standards" target="_top">C++03</a>
|
|
compilers (and they have performances comparable to <a href="http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions" target="_top">C++11
|
|
lambda functions</a> on <a href="http://www.open-std.org/JTC1/SC22/WG21/" target="_top">C++11</a>
|
|
compilers).
|
|
</li>
|
|
<li class="listitem">
|
|
<a href="http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions" target="_top">C++11
|
|
lambda functions</a> do not allow to bind variables in scope by constant
|
|
reference. Because a variable cannot be bound by constant reference, <a href="http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions" target="_top">C++11
|
|
lambda functions</a> can bind a variable by constant only if the variable
|
|
is <code class="computeroutput"><span class="identifier">CopyConstructible</span></code> and
|
|
the binding requires a (potentially expensive) extra copy operation. Constant
|
|
reference binding is instead supported by this library.
|
|
</li>
|
|
<li class="listitem">
|
|
<a href="http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions" target="_top">C++11
|
|
lambda functions</a> do not allow to bind data members selectively
|
|
without binding also the object <code class="computeroutput"><span class="keyword">this</span></code>
|
|
while this library local functions can bind either selected data members
|
|
or the entire object <code class="computeroutput"><span class="keyword">this</span></code>
|
|
(using <code class="computeroutput"><span class="identifier">this_</span></code>).
|
|
</li>
|
|
<li class="listitem">
|
|
<a href="http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions" target="_top">C++11
|
|
lambda functions</a> provide a short-hand syntax to bind all variables
|
|
in scope at once (<code class="computeroutput"><span class="special">&</span></code> or
|
|
<code class="computeroutput"><span class="special">=</span></code>) while this library local
|
|
function always require to bind variables naming them one-by-one.
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
For example, for non-copyable objects (see also <a href="../../../example/noncopyable_cxx11_lambda_error.cpp" target="_top"><code class="literal">noncopyable_cxx11_lambda_error.cpp</code></a>
|
|
and <a href="../../../example/noncopyable_local_function.cpp" target="_top"><code class="literal">noncopyable_local_function.cpp</code></a>):
|
|
</p>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup>
|
|
<col>
|
|
<col>
|
|
</colgroup>
|
|
<thead><tr>
|
|
<th>
|
|
<p>
|
|
C++11 Lambda Function
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
Boost.LocalFunction
|
|
</p>
|
|
</th>
|
|
</tr></thead>
|
|
<tbody><tr>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">struct</span> <span class="identifier">n</span><span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span> <span class="special">{</span>
|
|
<span class="keyword">int</span> <span class="identifier">i</span><span class="special">;</span>
|
|
<span class="identifier">n</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">_i</span><span class="special">):</span> <span class="identifier">i</span><span class="special">(</span><span class="identifier">_i</span><span class="special">)</span> <span class="special">{}</span>
|
|
<span class="special">};</span>
|
|
|
|
|
|
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="keyword">void</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">n</span> <span class="identifier">x</span><span class="special">(-</span><span class="number">1</span><span class="special">);</span>
|
|
|
|
<span class="keyword">auto</span> <span class="identifier">f</span> <span class="special">=</span> <span class="special">[</span><span class="identifier">x</span><span class="special">](</span><span class="keyword">void</span><span class="special">)</span> <span class="special">{</span> <span class="comment">// Error: x is non-copyable, but if</span>
|
|
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">i</span> <span class="special">==</span> <span class="special">-</span><span class="number">1</span><span class="special">);</span> <span class="comment">// bind `&x` then `x` is not constant.</span>
|
|
<span class="special">};</span>
|
|
<span class="identifier">f</span><span class="special">();</span>
|
|
|
|
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">struct</span> <span class="identifier">n</span><span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span> <span class="special">{</span>
|
|
<span class="keyword">int</span> <span class="identifier">i</span><span class="special">;</span>
|
|
<span class="identifier">n</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">_i</span><span class="special">):</span> <span class="identifier">i</span><span class="special">(</span><span class="identifier">_i</span><span class="special">)</span> <span class="special">{}</span>
|
|
<span class="special">};</span>
|
|
<span class="identifier">BOOST_TYPEOF_REGISTER_TYPE</span><span class="special">(</span><span class="identifier">n</span><span class="special">)</span> <span class="comment">// Register for `bind& x` below.</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="keyword">void</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">n</span> <span class="identifier">x</span><span class="special">(-</span><span class="number">1</span><span class="special">);</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">bind</span><span class="special">&</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span> <span class="comment">// OK: No copy</span>
|
|
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">i</span> <span class="special">==</span> <span class="special">-</span><span class="number">1</span><span class="special">);</span> <span class="comment">// and constant.</span>
|
|
<span class="special">}</span> <span class="identifier">BOOST_LOCAL_FUNCTION_NAME</span><span class="special">(</span><span class="identifier">f</span><span class="special">)</span>
|
|
<span class="identifier">f</span><span class="special">();</span>
|
|
|
|
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
</tr></tbody>
|
|
</table></div>
|
|
<p>
|
|
Or, for objects with expensive copy operations (see also <a href="../../../example/expensive_copy_cxx11_lambda.cpp" target="_top"><code class="literal">expensive_copy_cxx11_lambda.cpp</code></a>
|
|
and <a href="../../../example/expensive_copy_local_function.cpp" target="_top"><code class="literal">expensive_copy_local_function.cpp</code></a>):
|
|
</p>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup>
|
|
<col>
|
|
<col>
|
|
</colgroup>
|
|
<thead><tr>
|
|
<th>
|
|
<p>
|
|
C++11 Lambda Function
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
Boost.LocalFunction
|
|
</p>
|
|
</th>
|
|
</tr></thead>
|
|
<tbody><tr>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">struct</span> <span class="identifier">n</span> <span class="special">{</span>
|
|
<span class="keyword">int</span> <span class="identifier">i</span><span class="special">;</span>
|
|
<span class="identifier">n</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">_i</span><span class="special">):</span> <span class="identifier">i</span><span class="special">(</span><span class="identifier">_i</span><span class="special">)</span> <span class="special">{}</span>
|
|
<span class="identifier">n</span><span class="special">(</span><span class="identifier">n</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span><span class="special">):</span> <span class="identifier">i</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">i</span><span class="special">)</span> <span class="special">{</span> <span class="comment">// Some time consuming copy operation.</span>
|
|
<span class="keyword">for</span> <span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="number">10000</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="char">'.'</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
<span class="special">};</span>
|
|
|
|
|
|
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="keyword">void</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">n</span> <span class="identifier">x</span><span class="special">(-</span><span class="number">1</span><span class="special">);</span>
|
|
|
|
<span class="keyword">auto</span> <span class="identifier">f</span> <span class="special">=</span> <span class="special">[</span><span class="identifier">x</span><span class="special">]()</span> <span class="special">{</span> <span class="comment">// Problem: Expensive copy, but if bind</span>
|
|
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">i</span> <span class="special">==</span> <span class="special">-</span><span class="number">1</span><span class="special">);</span> <span class="comment">// by `&x` then `x` is not constant.</span>
|
|
<span class="special">};</span>
|
|
<span class="identifier">f</span><span class="special">();</span>
|
|
|
|
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">struct</span> <span class="identifier">n</span> <span class="special">{</span>
|
|
<span class="keyword">int</span> <span class="identifier">i</span><span class="special">;</span>
|
|
<span class="identifier">n</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">_i</span><span class="special">):</span> <span class="identifier">i</span><span class="special">(</span><span class="identifier">_i</span><span class="special">)</span> <span class="special">{}</span>
|
|
<span class="identifier">n</span><span class="special">(</span><span class="identifier">n</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span><span class="special">):</span> <span class="identifier">i</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">i</span><span class="special">)</span> <span class="special">{</span> <span class="comment">// Some time consuming copy operation.</span>
|
|
<span class="keyword">for</span> <span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="number">10000</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="char">'.'</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
<span class="special">};</span>
|
|
<span class="identifier">BOOST_TYPEOF_REGISTER_TYPE</span><span class="special">(</span><span class="identifier">n</span><span class="special">)</span> <span class="comment">// Register for `bind& x` below.</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="keyword">void</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">n</span> <span class="identifier">x</span><span class="special">(-</span><span class="number">1</span><span class="special">);</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">bind</span><span class="special">&</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span> <span class="comment">// OK: No copy expensive</span>
|
|
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">i</span> <span class="special">==</span> <span class="special">-</span><span class="number">1</span><span class="special">);</span> <span class="comment">// copy but constant.</span>
|
|
<span class="special">}</span> <span class="identifier">BOOST_LOCAL_FUNCTION_NAME</span><span class="special">(</span><span class="identifier">f</span><span class="special">)</span>
|
|
<span class="identifier">f</span><span class="special">();</span>
|
|
|
|
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
</tr></tbody>
|
|
</table></div>
|
|
<p>
|
|
When constant binding functionality is needed for <a href="http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions" target="_top">C++11
|
|
lambda functions</a>, the best alternative might be to bind an extra local
|
|
variable declared constant and initialized to the original variable (for example,
|
|
see <span class="emphasis"><em>constant blocks</em></span> implemented with <a href="http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions" target="_top">C++11
|
|
lambda functions</a> in the <a class="link" href="examples.html" title="Examples">Examples</a>
|
|
section).
|
|
</p>
|
|
<p>
|
|
<span class="bold"><strong>Local Functor</strong></span>
|
|
</p>
|
|
<p>
|
|
The following example compares local functions with C++ local functors (see
|
|
also <a href="../../../example/add_local_functor.cpp" target="_top"><code class="literal">add_local_functor.cpp</code></a>
|
|
and <a href="../../../test/add.cpp" target="_top"><code class="literal">add.cpp</code></a>):
|
|
</p>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup>
|
|
<col>
|
|
<col>
|
|
</colgroup>
|
|
<thead><tr>
|
|
<th>
|
|
<p>
|
|
Local Functor
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
Boost.LocalFunction
|
|
</p>
|
|
</th>
|
|
</tr></thead>
|
|
<tbody><tr>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="keyword">void</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">int</span> <span class="identifier">sum</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">factor</span> <span class="special">=</span> <span class="number">10</span><span class="special">;</span>
|
|
|
|
<span class="keyword">struct</span> <span class="identifier">local_add</span> <span class="special">{</span> <span class="comment">// Unfortunately, boilerplate code to program the class.</span>
|
|
<span class="identifier">local_add</span><span class="special">(</span><span class="keyword">int</span><span class="special">&</span> <span class="identifier">_sum</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">_factor</span><span class="special">):</span> <span class="identifier">sum</span><span class="special">(</span><span class="identifier">_sum</span><span class="special">),</span> <span class="identifier">factor</span><span class="special">(</span><span class="identifier">_factor</span><span class="special">)</span> <span class="special">{}</span>
|
|
|
|
<span class="keyword">inline</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span><span class="keyword">int</span> <span class="identifier">num</span><span class="special">)</span> <span class="special">{</span> <span class="comment">// Body uses C++ statement syntax.</span>
|
|
<span class="identifier">sum</span> <span class="special">+=</span> <span class="identifier">factor</span> <span class="special">*</span> <span class="identifier">num</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span> <span class="comment">// Unfortunately, cannot bind so repeat variable types.</span>
|
|
<span class="keyword">int</span><span class="special">&</span> <span class="identifier">sum</span><span class="special">;</span> <span class="comment">// Access `sum` by reference.</span>
|
|
<span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">factor</span><span class="special">;</span> <span class="comment">// Make `factor` constant.</span>
|
|
<span class="special">}</span> <span class="identifier">add</span><span class="special">(</span><span class="identifier">sum</span><span class="special">,</span> <span class="identifier">factor</span><span class="special">);</span>
|
|
|
|
<span class="identifier">add</span><span class="special">(</span><span class="number">1</span><span class="special">);</span>
|
|
<span class="keyword">int</span> <span class="identifier">nums</span><span class="special">[]</span> <span class="special">=</span> <span class="special">{</span><span class="number">2</span><span class="special">,</span> <span class="number">3</span><span class="special">};</span>
|
|
<span class="comment">// Unfortunately, cannot pass as template parameter to `std::for_each`.</span>
|
|
<span class="keyword">for</span><span class="special">(</span><span class="identifier">size_t</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="number">2</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="identifier">add</span><span class="special">(</span><span class="identifier">nums</span><span class="special">[</span><span class="identifier">i</span><span class="special">]);</span>
|
|
|
|
<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">sum</span> <span class="special">==</span> <span class="number">60</span><span class="special">);</span>
|
|
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">report_errors</span><span class="special">();</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="keyword">void</span><span class="special">)</span> <span class="special">{</span> <span class="comment">// Some local scope.</span>
|
|
<span class="keyword">int</span> <span class="identifier">sum</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">factor</span> <span class="special">=</span> <span class="number">10</span><span class="special">;</span> <span class="comment">// Variables in scope to bind.</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">bind</span> <span class="identifier">factor</span><span class="special">,</span> <span class="identifier">bind</span><span class="special">&</span> <span class="identifier">sum</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">num</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">sum</span> <span class="special">+=</span> <span class="identifier">factor</span> <span class="special">*</span> <span class="identifier">num</span><span class="special">;</span>
|
|
<span class="special">}</span> <span class="identifier">BOOST_LOCAL_FUNCTION_NAME</span><span class="special">(</span><span class="identifier">add</span><span class="special">)</span>
|
|
|
|
<span class="identifier">add</span><span class="special">(</span><span class="number">1</span><span class="special">);</span> <span class="comment">// Call the local function.</span>
|
|
<span class="keyword">int</span> <span class="identifier">nums</span><span class="special">[]</span> <span class="special">=</span> <span class="special">{</span><span class="number">2</span><span class="special">,</span> <span class="number">3</span><span class="special">};</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span><span class="special">(</span><span class="identifier">nums</span><span class="special">,</span> <span class="identifier">nums</span> <span class="special">+</span> <span class="number">2</span><span class="special">,</span> <span class="identifier">add</span><span class="special">);</span> <span class="comment">// Pass it to an algorithm.</span>
|
|
|
|
<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">sum</span> <span class="special">==</span> <span class="number">60</span><span class="special">);</span> <span class="comment">// Assert final summation value.</span>
|
|
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">report_errors</span><span class="special">();</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
</tr></tbody>
|
|
</table></div>
|
|
<p>
|
|
<span class="bold"><strong>Global Functor</strong></span>
|
|
</p>
|
|
<p>
|
|
The following example compares local functions with C++ global functors (see
|
|
also <a href="../../../example/add_global_functor.cpp" target="_top"><code class="literal">add_global_functor.cpp</code></a>
|
|
and <a href="../../../test/add.cpp" target="_top"><code class="literal">add.cpp</code></a>):
|
|
</p>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup>
|
|
<col>
|
|
<col>
|
|
</colgroup>
|
|
<thead><tr>
|
|
<th>
|
|
<p>
|
|
Global Functor
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
Boost.LocalFunction
|
|
</p>
|
|
</th>
|
|
</tr></thead>
|
|
<tbody><tr>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="comment">// Unfortunately, cannot be defined locally (so not a real alternative).</span>
|
|
<span class="keyword">struct</span> <span class="identifier">global_add</span> <span class="special">{</span> <span class="comment">// Unfortunately, boilerplate code to program the class.</span>
|
|
<span class="identifier">global_add</span><span class="special">(</span><span class="keyword">int</span><span class="special">&</span> <span class="identifier">_sum</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">_factor</span><span class="special">):</span> <span class="identifier">sum</span><span class="special">(</span><span class="identifier">_sum</span><span class="special">),</span> <span class="identifier">factor</span><span class="special">(</span><span class="identifier">_factor</span><span class="special">)</span> <span class="special">{}</span>
|
|
|
|
<span class="keyword">inline</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span><span class="keyword">int</span> <span class="identifier">num</span><span class="special">)</span> <span class="special">{</span> <span class="comment">// Body uses C++ statement syntax.</span>
|
|
<span class="identifier">sum</span> <span class="special">+=</span> <span class="identifier">factor</span> <span class="special">*</span> <span class="identifier">num</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span> <span class="comment">// Unfortunately, cannot bind so repeat variable types.</span>
|
|
<span class="keyword">int</span><span class="special">&</span> <span class="identifier">sum</span><span class="special">;</span> <span class="comment">// Access `sum` by reference.</span>
|
|
<span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">factor</span><span class="special">;</span> <span class="comment">// Make `factor` constant.</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="keyword">void</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">int</span> <span class="identifier">sum</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">factor</span> <span class="special">=</span> <span class="number">10</span><span class="special">;</span>
|
|
|
|
<span class="identifier">global_add</span> <span class="identifier">add</span><span class="special">(</span><span class="identifier">sum</span><span class="special">,</span> <span class="identifier">factor</span><span class="special">);</span>
|
|
|
|
<span class="identifier">add</span><span class="special">(</span><span class="number">1</span><span class="special">);</span>
|
|
<span class="keyword">int</span> <span class="identifier">nums</span><span class="special">[]</span> <span class="special">=</span> <span class="special">{</span><span class="number">2</span><span class="special">,</span> <span class="number">3</span><span class="special">};</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span><span class="special">(</span><span class="identifier">nums</span><span class="special">,</span> <span class="identifier">nums</span> <span class="special">+</span> <span class="number">2</span><span class="special">,</span> <span class="identifier">add</span><span class="special">);</span> <span class="comment">// Passed as template parameter.</span>
|
|
|
|
<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">sum</span> <span class="special">==</span> <span class="number">60</span><span class="special">);</span>
|
|
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">report_errors</span><span class="special">();</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="keyword">void</span><span class="special">)</span> <span class="special">{</span> <span class="comment">// Some local scope.</span>
|
|
<span class="keyword">int</span> <span class="identifier">sum</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">factor</span> <span class="special">=</span> <span class="number">10</span><span class="special">;</span> <span class="comment">// Variables in scope to bind.</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">bind</span> <span class="identifier">factor</span><span class="special">,</span> <span class="identifier">bind</span><span class="special">&</span> <span class="identifier">sum</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">num</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">sum</span> <span class="special">+=</span> <span class="identifier">factor</span> <span class="special">*</span> <span class="identifier">num</span><span class="special">;</span>
|
|
<span class="special">}</span> <span class="identifier">BOOST_LOCAL_FUNCTION_NAME</span><span class="special">(</span><span class="identifier">add</span><span class="special">)</span>
|
|
|
|
<span class="identifier">add</span><span class="special">(</span><span class="number">1</span><span class="special">);</span> <span class="comment">// Call the local function.</span>
|
|
<span class="keyword">int</span> <span class="identifier">nums</span><span class="special">[]</span> <span class="special">=</span> <span class="special">{</span><span class="number">2</span><span class="special">,</span> <span class="number">3</span><span class="special">};</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span><span class="special">(</span><span class="identifier">nums</span><span class="special">,</span> <span class="identifier">nums</span> <span class="special">+</span> <span class="number">2</span><span class="special">,</span> <span class="identifier">add</span><span class="special">);</span> <span class="comment">// Pass it to an algorithm.</span>
|
|
|
|
<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">sum</span> <span class="special">==</span> <span class="number">60</span><span class="special">);</span> <span class="comment">// Assert final summation value.</span>
|
|
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">report_errors</span><span class="special">();</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
</tr></tbody>
|
|
</table></div>
|
|
<p>
|
|
However, note that global functors do not allow to define the function locally
|
|
so they are not a real alternative implementation of local functions.
|
|
</p>
|
|
<p>
|
|
<span class="bold"><strong>Boost.Phoenix</strong></span>
|
|
</p>
|
|
<p>
|
|
The following example compares local functions with <a href="http://www.boost.org/libs/phoenix" target="_top">Boost.Phoenix</a>
|
|
(see also <a href="../../../example/add_phoenix.cpp" target="_top"><code class="literal">add_phoenix.cpp</code></a>
|
|
and <a href="../../../test/add.cpp" target="_top"><code class="literal">add.cpp</code></a>):
|
|
</p>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup>
|
|
<col>
|
|
<col>
|
|
</colgroup>
|
|
<thead><tr>
|
|
<th>
|
|
<p>
|
|
Boost.Phoenix
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
Boost.LocalFunction
|
|
</p>
|
|
</th>
|
|
</tr></thead>
|
|
<tbody><tr>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="keyword">void</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">let</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">local_names</span><span class="special">::</span><span class="identifier">_f</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">cref</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">ref</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">arg_names</span><span class="special">::</span><span class="identifier">_1</span><span class="special">;</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">sum</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">factor</span> <span class="special">=</span> <span class="number">10</span><span class="special">;</span>
|
|
<span class="keyword">int</span> <span class="identifier">nums</span><span class="special">[]</span> <span class="special">=</span> <span class="special">{</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span><span class="special">};</span>
|
|
|
|
<span class="comment">// Passed to template, `factor` by constant, and defined in expression.</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span><span class="special">(</span><span class="identifier">nums</span><span class="special">,</span> <span class="identifier">nums</span> <span class="special">+</span> <span class="number">3</span><span class="special">,</span> <span class="identifier">let</span><span class="special">(</span><span class="identifier">_f</span> <span class="special">=</span> <span class="identifier">cref</span><span class="special">(</span><span class="identifier">factor</span><span class="special">))[</span>
|
|
<span class="comment">// Unfortunately, body cannot use C++ statement syntax.</span>
|
|
<span class="identifier">ref</span><span class="special">(</span><span class="identifier">sum</span><span class="special">)</span> <span class="special">+=</span> <span class="identifier">_f</span> <span class="special">*</span> <span class="identifier">_1</span><span class="special">,</span> <span class="identifier">_1</span> <span class="comment">// Access `sum` by reference.</span>
|
|
<span class="special">]);</span>
|
|
|
|
<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">sum</span> <span class="special">==</span> <span class="number">60</span><span class="special">);</span>
|
|
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">report_errors</span><span class="special">();</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="keyword">void</span><span class="special">)</span> <span class="special">{</span> <span class="comment">// Some local scope.</span>
|
|
<span class="keyword">int</span> <span class="identifier">sum</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">factor</span> <span class="special">=</span> <span class="number">10</span><span class="special">;</span> <span class="comment">// Variables in scope to bind.</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">bind</span> <span class="identifier">factor</span><span class="special">,</span> <span class="identifier">bind</span><span class="special">&</span> <span class="identifier">sum</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">num</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">sum</span> <span class="special">+=</span> <span class="identifier">factor</span> <span class="special">*</span> <span class="identifier">num</span><span class="special">;</span>
|
|
<span class="special">}</span> <span class="identifier">BOOST_LOCAL_FUNCTION_NAME</span><span class="special">(</span><span class="identifier">add</span><span class="special">)</span>
|
|
|
|
<span class="identifier">add</span><span class="special">(</span><span class="number">1</span><span class="special">);</span> <span class="comment">// Call the local function.</span>
|
|
<span class="keyword">int</span> <span class="identifier">nums</span><span class="special">[]</span> <span class="special">=</span> <span class="special">{</span><span class="number">2</span><span class="special">,</span> <span class="number">3</span><span class="special">};</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span><span class="special">(</span><span class="identifier">nums</span><span class="special">,</span> <span class="identifier">nums</span> <span class="special">+</span> <span class="number">2</span><span class="special">,</span> <span class="identifier">add</span><span class="special">);</span> <span class="comment">// Pass it to an algorithm.</span>
|
|
|
|
<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">sum</span> <span class="special">==</span> <span class="number">60</span><span class="special">);</span> <span class="comment">// Assert final summation value.</span>
|
|
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">report_errors</span><span class="special">();</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
</tr></tbody>
|
|
</table></div>
|
|
<p>
|
|
The comparison in this section does not include the <a href="http://www.boost.org/libs/lambda" target="_top">Boost.Lambda</a>
|
|
library because that library is obsolete and it was replaced by <a href="http://www.boost.org/libs/phoenix" target="_top">Boost.Phoenix</a>.
|
|
The <a href="http://www.boost.org/libs/phoenix" target="_top">Boost.Phoenix</a> library
|
|
version 3.0 is used for this comparison.
|
|
</p>
|
|
<h4>
|
|
<a name="boost_localfunction.alternatives.h1"></a>
|
|
<span class="phrase"><a name="boost_localfunction.alternatives.performances"></a></span><a class="link" href="alternatives.html#boost_localfunction.alternatives.performances">Performances</a>
|
|
</h4>
|
|
<p>
|
|
The following tables compare run-times, compile-times, and binary sizes for
|
|
the different alternatives to local functions presented in this section.
|
|
</p>
|
|
<p>
|
|
Overall, this library has compile-times and generates binary sizes similar
|
|
to the ones of the other approaches. This library run-times on <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/standards" target="_top">C++03</a>
|
|
compilers were measured to be larger than other approaches when compiler optimization
|
|
is enabled (using <code class="computeroutput"><span class="identifier">bjam</span> <span class="identifier">release</span>
|
|
<span class="special">...</span></code>). However, on compilers that allow
|
|
to pass local types as template parameters (e.g., MSVC 8.0 or GCC 4.5.3 with
|
|
<a href="http://www.open-std.org/JTC1/SC22/WG21/" target="_top">C++11</a> features
|
|
enabled <code class="literal">-std=c++0x</code>, see also <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm" target="_top">[N2657]</a>
|
|
and <a href="http://www.boost.org/libs/chrono" target="_top">Boost.Config</a>'s <code class="computeroutput"><span class="identifier">BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS</span></code>)
|
|
this library automatically generates optimized code that runs as fast as the
|
|
fastest of the other approaches (see the "Boost.LocalFunction" approach
|
|
below). When this library local function is specified <code class="computeroutput"><span class="keyword">inline</span></code>
|
|
(see the "Boost.LocalFunction Inline" approach below and the <a class="link" href="advanced_topics.html" title="Advanced Topics">Advanced Topics</a> section)
|
|
its run-times are always comparable to both the "Local Functor" and
|
|
"Global Functor" approaches. However, in these cases the local function
|
|
cannot be portably passed as template parameter (see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm" target="_top">[N2657]</a>
|
|
and <a href="http://www.boost.org/libs/chrono" target="_top">Boost.Config</a>'s <code class="computeroutput"><span class="identifier">BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS</span></code>)
|
|
so <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span></code> is replaced by a for-loop (on MSVC
|
|
the for-loop, and not the local function in fact the same applies to local
|
|
functors, was measured to have worst performances than using <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span></code>).
|
|
Finally, this library run-times are always among the fastest when no compiler
|
|
optimization is enabled (using <code class="computeroutput"><span class="identifier">bjam</span>
|
|
<span class="identifier">debug</span> <span class="special">...</span></code>).
|
|
</p>
|
|
<div class="note"><table border="0" summary="Note">
|
|
<tr>
|
|
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td>
|
|
<th align="left">Note</th>
|
|
</tr>
|
|
<tr><td align="left" valign="top"><p>
|
|
The run-time performances of this library local functions are explained because
|
|
on <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/standards" target="_top">C++03</a>
|
|
compliant compilers (e.g., GCC 4.5.3 without <code class="literal">-std=c++0x</code>)
|
|
this library needs to use a function pointer in order to portably pass the
|
|
local function class as a template parameter (see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm" target="_top">[N2657]</a>
|
|
and the <a class="link" href="implementation.html" title="Annex: Implementation">Implementation</a>
|
|
section). For all tested compilers, this function pointer prevents the compiler
|
|
optimization algorithms from inlining the local function calls. Instead,
|
|
the functors used by other approaches (e.g., <a href="http://www.boost.org/libs/phoenix" target="_top">Boost.Phoenix</a>)
|
|
have been observed to allow all tested compilers to inline all the function
|
|
calls for optimization. This run-time performance cost is not present on
|
|
compilers that allow to pass local types as template parameters (e.g., MSVC
|
|
8.0 or GCC 4.5.3 with <a href="http://www.open-std.org/JTC1/SC22/WG21/" target="_top">C++11</a>
|
|
features enabled <code class="literal">-std=c++0x</code>, see <a href="http://www.boost.org/libs/chrono" target="_top">Boost.Config</a>'s
|
|
<code class="computeroutput"><span class="identifier">BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS</span></code>)
|
|
because this library does not have to use the extra function pointer to implement
|
|
the local function call (it directly passes the local class type as template
|
|
parameter).
|
|
</p></td></tr>
|
|
</table></div>
|
|
<p>
|
|
This run-time performance cost on <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/standards" target="_top">C++03</a>
|
|
compilers might or might not be an issue depending on the performance requirements
|
|
of specific applications. For example, an application might already be using
|
|
a number of indirect function calls (function pointers, virtual functions,
|
|
etc) for which the overhead added by using the one extra function pointer required
|
|
by the local function call might not be noticeable within the overall program
|
|
run-time.
|
|
</p>
|
|
<p>
|
|
Finally, note that only a very simple local function body with just a single
|
|
instruction was used for the anaylsis presented here (see the source files
|
|
below). The authors have not studied how this library and the other approaches
|
|
will perform with respect to each other when a more complex set of instructions
|
|
is programmed for the local function body (e.g., <span class="emphasis"><em>if</em></span> a
|
|
more complex set of instructions in the local function body were to inhibit
|
|
some compiler from inlining function objects also other approaches like <a href="http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions" target="_top">C++11
|
|
lambda functions</a> and <a href="http://www.boost.org/libs/phoenix" target="_top">Boost.Phoenix</a>
|
|
<span class="emphasis"><em>could</em></span> start to show higher run-times even when optimization
|
|
is enabled).
|
|
</p>
|
|
<p>
|
|
The following commands were executed from the library example directory to
|
|
measure compile-time, binary size, and run-time respectively:
|
|
</p>
|
|
<pre class="programlisting">> touch <FILE_NAME>.cpp # force recompilation
|
|
> python chrono.py bjam {release|debug} <FILE_NAME> # compile-time
|
|
> size <FILE_NAME> # binary size
|
|
> ./<FILE_NAME> # run-time
|
|
</pre>
|
|
<p>
|
|
The local function was called <code class="literal">1e8</code> times to add together
|
|
all the elements of a vector and the run-time was measured using <a href="http://www.boost.org/libs/chrono" target="_top">Boost.Chrono</a>
|
|
averaging over <code class="literal">10</code> executions of the vector summation (see
|
|
the source files below).
|
|
</p>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup>
|
|
<col>
|
|
<col>
|
|
<col>
|
|
</colgroup>
|
|
<thead><tr>
|
|
<th>
|
|
<p>
|
|
Legend
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
Approach
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
Source File
|
|
</p>
|
|
</th>
|
|
</tr></thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<span class="inlinemediaobject"><img src="../../../example/profile_legend_local_function.png" alt="profile_legend_local_function"></span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
<a href="http://www.boost.org/libs/local_function" target="_top">Boost.LocalFunction</a>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
<a href="../../../example/profile_local_function.cpp" target="_top"><code class="literal">profile_local_function.cpp</code></a>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<span class="inlinemediaobject"><img src="../../../example/profile_legend_local_function_inline.png" alt="profile_legend_local_function_inline"></span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
<a href="http://www.boost.org/libs/local_function" target="_top">Boost.LocalFunction</a>
|
|
inline
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
<a href="../../../example/profile_local_function_inline.cpp" target="_top"><code class="literal">profile_local_function_inline.cpp</code></a>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<span class="inlinemediaobject"><img src="../../../example/profile_legend_cxx11_lambda.png" alt="profile_legend_cxx11_lambda"></span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
<a href="http://www.open-std.org/JTC1/SC22/WG21/" target="_top">C++11</a>
|
|
Lambda Function <a href="#ftn.boost_localfunction.alternatives.f0" class="footnote" name="boost_localfunction.alternatives.f0"><sup class="footnote">[a]</sup></a>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
<a href="../../../example/profile_cxx11_lambda.cpp" target="_top"><code class="literal">profile_cxx11_lambda.cpp</code></a>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<span class="inlinemediaobject"><img src="../../../example/profile_legend_local_functor.png" alt="profile_legend_local_functor"></span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Local Functor
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
<a href="../../../example/profile_local_functor.cpp" target="_top"><code class="literal">profile_local_functor.cpp</code></a>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<span class="inlinemediaobject"><img src="../../../example/profile_legend_global_functor.png" alt="profile_legend_global_functor"></span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Global Functor
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
<a href="../../../example/profile_global_functor.cpp" target="_top"><code class="literal">profile_global_functor.cpp</code></a>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<span class="inlinemediaobject"><img src="../../../example/profile_legend_phoenix.png" alt="profile_legend_phoenix"></span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
<a href="http://www.boost.org/libs/phoenix" target="_top">Boost.Phoenix</a>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
<a href="../../../example/profile_phoenix.cpp" target="_top"><code class="literal">profile_phoenix.cpp</code></a>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
<tbody class="footnotes"><tr><td colspan="3"><div id="ftn.boost_localfunction.alternatives.f0" class="footnote"><p><a href="#boost_localfunction.alternatives.f0" class="para"><sup class="para">[a] </sup></a>
|
|
Measurements available only for <a href="http://www.open-std.org/JTC1/SC22/WG21/" target="_top">C++11</a>
|
|
compilers.
|
|
</p></div></td></tr></tbody>
|
|
</table></div>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup><col></colgroup>
|
|
<thead><tr><th>
|
|
<p>
|
|
GCC 4.5.3 With C++11 Lambda Functions and "Local Classes as
|
|
Template Parameters" (<code class="literal">bjam cxxflags=-std=c++0x ...</code>)
|
|
</p>
|
|
</th></tr></thead>
|
|
<tbody>
|
|
<tr><td>
|
|
<p>
|
|
<span class="bold"><strong>Compiled with <code class="literal">bjam release ...</code>
|
|
for maximum optimization (<code class="literal">-O3 -finline-functions</code>)</strong></span>
|
|
<span class="inlinemediaobject"><img src="../../../example/profile_gcc_cxx11_release.png" width="1170" alt="profile_gcc_cxx11_release"></span>
|
|
</p>
|
|
</td></tr>
|
|
<tr><td>
|
|
<p>
|
|
<span class="bold"><strong>Compiled with <code class="literal">bjam debug ...</code>
|
|
for no optimization (<code class="literal">-O0 -fno-inline</code>)</strong></span>
|
|
<span class="inlinemediaobject"><img src="../../../example/profile_gcc_cxx11_debug.png" width="1170" alt="profile_gcc_cxx11_debug"></span>
|
|
</p>
|
|
</td></tr>
|
|
</tbody>
|
|
</table></div>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup><col></colgroup>
|
|
<thead><tr><th>
|
|
<p>
|
|
MSVC 8.0 With "Local Classes as Template Parameters" (Without
|
|
C++11 Lambda Functions)
|
|
</p>
|
|
</th></tr></thead>
|
|
<tbody>
|
|
<tr><td>
|
|
<p>
|
|
<span class="bold"><strong>Compiled with <code class="literal">bjam release ...</code>
|
|
for maximum optimization (<code class="literal">/O2 /Ob2</code>)</strong></span>
|
|
<span class="inlinemediaobject"><img src="../../../example/profile_msvc_release.png" width="1170" alt="profile_msvc_release"></span>
|
|
</p>
|
|
</td></tr>
|
|
<tr><td>
|
|
<p>
|
|
<span class="bold"><strong>Compiled with <code class="literal">bjam debug ...</code>
|
|
for no optimization (<code class="literal">/Od /Ob0</code>)</strong></span> <span class="inlinemediaobject"><img src="../../../example/profile_msvc_debug.png" width="1170" alt="profile_msvc_debug"></span>
|
|
</p>
|
|
</td></tr>
|
|
</tbody>
|
|
</table></div>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup><col></colgroup>
|
|
<thead><tr><th>
|
|
<p>
|
|
GCC 4.3.4 With <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/standards" target="_top">C++03</a>
|
|
Only (Without <a href="http://www.open-std.org/JTC1/SC22/WG21/" target="_top">C++11</a>
|
|
Lambda Functions and Without "Local Classes as Template Parameters")
|
|
</p>
|
|
</th></tr></thead>
|
|
<tbody>
|
|
<tr><td>
|
|
<p>
|
|
<span class="bold"><strong>Compiled with <code class="literal">bjam release ...</code>
|
|
for maximum optimization (<code class="literal">-O3 -finline-functions</code>)</strong></span>
|
|
<span class="inlinemediaobject"><img src="../../../example/profile_gcc_release.png" width="1170" alt="profile_gcc_release"></span>
|
|
</p>
|
|
</td></tr>
|
|
<tr><td>
|
|
<p>
|
|
<span class="bold"><strong>Compiled with <code class="literal">bjam debug ...</code>
|
|
for no optimization (<code class="literal">-O0 -fno-inline</code>)</strong></span>
|
|
<span class="inlinemediaobject"><img src="../../../example/profile_gcc_debug.png" width="1170" alt="profile_gcc_debug"></span>
|
|
</p>
|
|
</td></tr>
|
|
</tbody>
|
|
</table></div>
|
|
</div>
|
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
|
<td align="left"></td>
|
|
<td align="right"><div class="copyright-footer">Copyright © 2009-2012 Lorenzo
|
|
Caminiti<p>
|
|
Distributed under the Boost Software License, Version 1.0 (see accompanying
|
|
file LICENSE_1_0.txt or a copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
|
</p>
|
|
</div></td>
|
|
</tr></table>
|
|
<hr>
|
|
<div class="spirit-nav">
|
|
<a accesskey="p" href="examples.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="no_variadic_macros.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
|
</div>
|
|
</body>
|
|
</html>
|