12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070 |
- <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.79.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>
|