1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3 4 5<html xmlns="http://www.w3.org/1999/xhtml"> 6 <head> 7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 8 9 <title>Getting started — Boost.HigherOrderFunctions 0.6 documentation</title> 10 11 <link rel="stylesheet" href="../../_static/boostbook.css" type="text/css" /> 12 <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" /> 13 14 <script type="text/javascript"> 15 var DOCUMENTATION_OPTIONS = { 16 URL_ROOT: '../../', 17 VERSION: '0.6', 18 COLLAPSE_INDEX: false, 19 FILE_SUFFIX: '.html', 20 HAS_SOURCE: true, 21 SOURCELINK_SUFFIX: '.txt' 22 }; 23 </script> 24 <script type="text/javascript" src="../../_static/jquery.js"></script> 25 <script type="text/javascript" src="../../_static/underscore.js"></script> 26 <script type="text/javascript" src="../../_static/doctools.js"></script> 27 <link rel="index" title="Index" href="../../genindex.html" /> 28 <link rel="search" title="Search" href="../../search.html" /> 29 <link rel="next" title="Examples" href="examples.html" /> 30 <link rel="prev" title="Building" href="building.html" /> 31 </head> 32 <body role="document"> 33<table cellpadding="2" width="100%"><tr> 34<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86"src="../../_static/boost.png"></td> 35</tr></table> 36 37<div class="spirit-nav"> 38<a accesskey="p" href="building.html"><img src="../../_static/prev.png" alt="Prev"></a> 39<a accesskey="u" href="intro.html"><img src="../../_static/up.png" alt="Up"></a> 40<a accesskey="h" href="../index.html"><img src="../../_static/home.png" alt="Home"></a> 41<a accesskey="n" href="examples.html"><img src="../../_static/next.png" alt="Next"></a> 42</div> 43 44 45 <div class="document"> 46 <div class="chapter"> 47 <div class="body" role="main"> 48 49 <!-- Copyright 2018 Paul Fultz II 50 Distributed under the Boost Software License, Version 1.0. 51 (http://www.boost.org/LICENSE_1_0.txt) 52--><div class="section" id="getting-started"> 53<h1>Getting started<a class="headerlink" href="#getting-started" title="Permalink to this headline">¶</a></h1> 54<div class="section" id="higher-order-functions"> 55<h2>Higher-order functions<a class="headerlink" href="#higher-order-functions" title="Permalink to this headline">¶</a></h2> 56<p>A core part of this library is higher-order functions. A higher-order function is a function that either takes a function as its argument or returns a function. To be able to define higher-order functions, we must be able to refer functions as first-class objects. One example of a higher-order function is <code class="docutils literal"><span class="pre">std::accumulate</span></code>. It takes a custom binary operator as a parameter.</p> 57<p>One way to refer to a function is to use a function pointer(or a member function pointer). So if we had our own custom <code class="docutils literal"><span class="pre">sum</span></code> function, we could pass it directly to <code class="docutils literal"><span class="pre">std::accumulate</span></code>:</p> 58<div class="highlight-cpp"><div class="highlight"><pre><span class="kt">int</span> <span class="nf">sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> 59<span class="p">{</span> 60 <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="p">;</span> 61<span class="p">}</span> 62<span class="c1">// Pass sum to accumulate</span> 63<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">></span> <span class="n">v</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span> <span class="p">};</span> 64<span class="kt">int</span> <span class="n">total</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">accumulate</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">v</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="mi">0</span><span class="p">,</span> <span class="o">&</span><span class="n">sum</span><span class="p">);</span> 65</pre></div> 66</div> 67<p>However, a function pointer can only refer to one function in an overload set of functions, and it requires explicit casting to select that overload.</p> 68<p>For example, if we had a templated <code class="docutils literal"><span class="pre">sum</span></code> function that we want to pass to <code class="docutils literal"><span class="pre">std::accumulate</span></code>, we would need an explicit cast:</p> 69<div class="highlight-cpp"><div class="highlight"><pre><span class="k">template</span><span class="o"><</span><span class="k">class</span> <span class="nc">T</span><span class="p">,</span> <span class="k">class</span> <span class="nc">U</span><span class="o">></span> 70<span class="k">auto</span> <span class="n">sum</span><span class="p">(</span><span class="n">T</span> <span class="n">x</span><span class="p">,</span> <span class="n">U</span> <span class="n">y</span><span class="p">)</span> 71<span class="p">{</span> 72 <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="p">;</span> 73<span class="p">}</span> 74 75<span class="k">auto</span> <span class="n">sum_int</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="p">))</span><span class="o">&</span><span class="n">sum</span><span class="p">;</span> 76<span class="c1">// Call integer overload</span> 77<span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">sum_int</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span> 78<span class="c1">// Or pass to an algorithm</span> 79<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">></span> <span class="n">v</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span> <span class="p">};</span> 80<span class="kt">int</span> <span class="n">total</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">accumulate</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">v</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="mi">0</span><span class="p">,</span> <span class="n">sum_int</span><span class="p">);</span> 81</pre></div> 82</div> 83</div> 84<div class="section" id="function-objects"> 85<h2>Function Objects<a class="headerlink" href="#function-objects" title="Permalink to this headline">¶</a></h2> 86<p>A function object allows the ability to encapsulate an entire overload set into one object. This can be done by defining a class that overrides the call operator like this:</p> 87<div class="highlight-cpp"><div class="highlight"><pre><span class="c1">// A sum function object</span> 88<span class="k">struct</span> <span class="n">sum_f</span> 89<span class="p">{</span> 90 <span class="k">template</span><span class="o"><</span><span class="k">class</span> <span class="nc">T</span><span class="p">,</span> <span class="k">class</span> <span class="nc">U</span><span class="o">></span> 91 <span class="k">auto</span> <span class="k">operator</span><span class="p">()(</span><span class="n">T</span> <span class="n">x</span><span class="p">,</span> <span class="n">U</span> <span class="n">y</span><span class="p">)</span> <span class="k">const</span> 92 <span class="p">{</span> 93 <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="p">;</span> 94 <span class="p">}</span> 95<span class="p">};</span> 96</pre></div> 97</div> 98<p>There are few things to note about this. First, the call operator member function is always declared <code class="docutils literal"><span class="pre">const</span></code>, which is generally required to be used with Boost.HigherOrderFunctions.(Note: The <a class="reference internal" href="../../include/boost/hof/mutable.html"><span class="doc">mutable</span></a> adaptor can be used to make a mutable function object have a <code class="docutils literal"><span class="pre">const</span></code> call operator, but this should generally be avoided). Secondly, the <code class="docutils literal"><span class="pre">sum_f</span></code> class must be constructed first before it can be called:</p> 99<div class="highlight-cpp"><div class="highlight"><pre><span class="k">auto</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">sum_f</span><span class="p">();</span> 100<span class="c1">// Call sum function</span> 101<span class="k">auto</span> <span class="n">three</span> <span class="o">=</span> <span class="n">sum</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span> 102<span class="c1">// Or pass to an algorithm</span> 103<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">></span> <span class="n">v</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span> <span class="p">};</span> 104<span class="kt">int</span> <span class="n">total</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">accumulate</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">v</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="mi">0</span><span class="p">,</span> <span class="n">sum</span><span class="p">);</span> 105</pre></div> 106</div> 107<p>Because the function is templated, it can be called on any type that has the plus <code class="docutils literal"><span class="pre">+</span></code> operator, not just integers. Futhermore, the <code class="docutils literal"><span class="pre">sum</span></code> variable can be used to refer to the entire overload set.</p> 108</div> 109<div class="section" id="lifting-functions"> 110<h2>Lifting functions<a class="headerlink" href="#lifting-functions" title="Permalink to this headline">¶</a></h2> 111<p>Another alternative to defining a function object, is to lift the templated function using <a class="reference internal" href="../../include/boost/hof/lift.html"><span class="doc">BOOST_HOF_LIFT</span></a>. This will turn the entire overload set into one object like a function object:</p> 112<div class="highlight-cpp"><div class="highlight"><pre><span class="k">template</span><span class="o"><</span><span class="k">class</span> <span class="nc">T</span><span class="p">,</span> <span class="k">class</span> <span class="nc">U</span><span class="o">></span> 113<span class="k">auto</span> <span class="n">sum</span><span class="p">(</span><span class="n">T</span> <span class="n">x</span><span class="p">,</span> <span class="n">U</span> <span class="n">y</span><span class="p">)</span> 114<span class="p">{</span> 115 <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="p">;</span> 116<span class="p">}</span> 117 118<span class="c1">// Pass sum to an algorithm</span> 119<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">></span> <span class="n">v</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span> <span class="p">};</span> 120<span class="kt">int</span> <span class="n">total</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">accumulate</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">v</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="mi">0</span><span class="p">,</span> <span class="n">BOOST_HOF_LIFT</span><span class="p">(</span><span class="n">sum</span><span class="p">));</span> 121</pre></div> 122</div> 123<p>However, due to limitations in C++14 this will not preserve <code class="docutils literal"><span class="pre">constexpr</span></code>. In those cases, its better to use a function object.</p> 124</div> 125<div class="section" id="declaring-functions"> 126<h2>Declaring functions<a class="headerlink" href="#declaring-functions" title="Permalink to this headline">¶</a></h2> 127<p>Now, this is useful for local functions. However, many times we want to write functions and make them available for others to use. Boost.HigherOrderFunctions provides <a class="reference internal" href="../../include/boost/hof/function.html"><span class="doc">BOOST_HOF_STATIC_FUNCTION</span></a> to declare the function object at the global or namespace scope:</p> 128<div class="highlight-cpp"><div class="highlight"><pre><span class="n">BOOST_HOF_STATIC_FUNCTION</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">=</span> <span class="n">sum_f</span><span class="p">();</span> 129</pre></div> 130</div> 131<p>The <a class="reference internal" href="../../include/boost/hof/function.html"><span class="doc">BOOST_HOF_STATIC_FUNCTION</span></a> declares a global variable following the best practices as outlined in <a class="reference external" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html">N4381</a>. This includes using <code class="docutils literal"><span class="pre">const</span></code> to avoid global state, compile-time initialization of the function object to avoid the <a class="reference external" href="https://isocpp.org/wiki/faq/ctors#static-init-order">static initialization order fiasco</a>, and an external address of the function object that is the same across translation units to avoid possible One-Definition-Rule(ODR) violations. In C++17, this can be achieved using an <code class="docutils literal"><span class="pre">inline</span></code> variable:</p> 132<div class="highlight-cpp"><div class="highlight"><pre><span class="kr">inline</span> <span class="k">const</span> <span class="k">constexpr</span> <span class="k">auto</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">sum_f</span><span class="p">{};</span> 133</pre></div> 134</div> 135<p>The <a class="reference internal" href="../../include/boost/hof/function.html"><span class="doc">BOOST_HOF_STATIC_FUNCTION</span></a> macro provides a portable way to do this that supports pre-C++17 compilers and MSVC.</p> 136</div> 137<div class="section" id="adaptors"> 138<h2>Adaptors<a class="headerlink" href="#adaptors" title="Permalink to this headline">¶</a></h2> 139<p>Now we have defined the function as a function object, we can add new “enhancements” to the function. One enhancement is to write “extension” methods. The proposal <a class="reference external" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4165.pdf">N4165</a> for Unified Call Syntax(UFCS) would have allowed a function call of <code class="docutils literal"><span class="pre">x.f(y)</span></code> to become <code class="docutils literal"><span class="pre">f(x,</span> <span class="pre">y)</span></code>. Without UFCS in C++, we can instead use pipable function which would transform <code class="docutils literal"><span class="pre">x</span> <span class="pre">|</span> <span class="pre">f(y)</span></code> into <code class="docutils literal"><span class="pre">f(x,</span> <span class="pre">y)</span></code>. To make <code class="docutils literal"><span class="pre">sum_f</span></code> function pipable using the <a class="reference internal" href="../../include/boost/hof/pipable.html"><span class="doc">pipable</span></a> adaptor, we can simply write:</p> 140<div class="highlight-cpp"><div class="highlight"><pre><span class="n">BOOST_HOF_STATIC_FUNCTION</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">=</span> <span class="n">pipable</span><span class="p">(</span><span class="n">sum_f</span><span class="p">());</span> 141</pre></div> 142</div> 143<p>Then the parameters can be piped into it, like this:</p> 144<div class="highlight-cpp"><div class="highlight"><pre><span class="k">auto</span> <span class="n">three</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">|</span> <span class="n">sum</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span> 145</pre></div> 146</div> 147<p>Pipable function can be chained mutliple times just like the <code class="docutils literal"><span class="pre">.</span></code> operator:</p> 148<div class="highlight-cpp"><div class="highlight"><pre><span class="k">auto</span> <span class="n">four</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">|</span> <span class="n">sum</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">|</span> <span class="n">sum</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> 149</pre></div> 150</div> 151<p>Alternatively, instead of using the <code class="docutils literal"><span class="pre">|</span></code> operator, pipable functions can be chained together using the <a class="reference internal" href="../../include/boost/hof/flow.html"><span class="doc">flow</span></a> adaptor:</p> 152<div class="highlight-cpp"><div class="highlight"><pre><span class="k">auto</span> <span class="n">four</span> <span class="o">=</span> <span class="n">flow</span><span class="p">(</span><span class="n">sum</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span> <span class="n">sum</span><span class="p">(</span><span class="mi">1</span><span class="p">))(</span><span class="mi">1</span><span class="p">);</span> 153</pre></div> 154</div> 155<p>Another enhancement that can be done to functions is defining named infix operators using the <a class="reference internal" href="../../include/boost/hof/infix.html"><span class="doc">infix</span></a> adaptor:</p> 156<div class="highlight-cpp"><div class="highlight"><pre><span class="n">BOOST_HOF_STATIC_FUNCTION</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">=</span> <span class="n">infix</span><span class="p">(</span><span class="n">sum_f</span><span class="p">());</span> 157</pre></div> 158</div> 159<p>And it could be called like this:</p> 160<div class="highlight-cpp"><div class="highlight"><pre><span class="k">auto</span> <span class="n">three</span> <span class="o">=</span> <span class="mi">1</span> <span class="o"><</span><span class="n">sum</span><span class="o">></span> <span class="mi">2</span><span class="p">;</span> 161</pre></div> 162</div> 163<p>In addition, adaptors are provided that support simple functional operations such as <a class="reference external" href="https://en.wikipedia.org/wiki/Partial_application">partial application</a> and <a class="reference external" href="https://en.wikipedia.org/wiki/Function_composition">function composition</a>:</p> 164<div class="highlight-cpp"><div class="highlight"><pre><span class="k">auto</span> <span class="n">add_1</span> <span class="o">=</span> <span class="n">partial</span><span class="p">(</span><span class="n">sum</span><span class="p">)(</span><span class="mi">1</span><span class="p">);</span> 165<span class="k">auto</span> <span class="n">add_2</span> <span class="o">=</span> <span class="n">compose</span><span class="p">(</span><span class="n">add_1</span><span class="p">,</span> <span class="n">add_1</span><span class="p">);</span> 166<span class="k">auto</span> <span class="n">three</span> <span class="o">=</span> <span class="n">add_2</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> 167</pre></div> 168</div> 169</div> 170<div class="section" id="lambdas"> 171<h2>Lambdas<a class="headerlink" href="#lambdas" title="Permalink to this headline">¶</a></h2> 172<p>Writing function objects can be a little verbose. C++ provides lambdas which have a much terser syntax for defining functions. Of course, lambdas can work with all the adaptors in the library, however, if we want to declare a function using lambdas, <a class="reference internal" href="../../include/boost/hof/function.html"><span class="doc">BOOST_HOF_STATIC_FUNCTION</span></a> won’t work. Instead, <a class="reference internal" href="../../include/boost/hof/lambda.html#boost-hof-static-lambda-function"><span class="std std-ref">BOOST_HOF_STATIC_LAMBDA_FUNCTION</span></a> can be used to the declare the lambda as a function instead, this will initialize the function at compile-time and avoid possible ODR violations:</p> 173<div class="highlight-cpp"><div class="highlight"><pre><span class="n">BOOST_HOF_STATIC_LAMBDA_FUNCTION</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">=</span> <span class="p">[](</span><span class="k">auto</span> <span class="n">x</span><span class="p">,</span> <span class="k">auto</span> <span class="n">y</span><span class="p">)</span> 174<span class="p">{</span> 175 <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="p">;</span> 176<span class="p">};</span> 177</pre></div> 178</div> 179<p>Additionally, adaptors can be used, so the pipable version of <code class="docutils literal"><span class="pre">sum</span></code> can be written like this:</p> 180<div class="highlight-cpp"><div class="highlight"><pre><span class="c1">// Pipable sum</span> 181<span class="n">BOOST_HOF_STATIC_LAMBDA_FUNCTION</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span> <span class="o">=</span> <span class="n">pipable</span><span class="p">([](</span><span class="k">auto</span> <span class="n">x</span><span class="p">,</span> <span class="k">auto</span> <span class="n">y</span><span class="p">)</span> 182<span class="p">{</span> 183 <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="p">;</span> 184<span class="p">});</span> 185</pre></div> 186</div> 187</div> 188</div> 189 190 191 </div> 192 </div> 193 <div class="clearer"></div> 194 </div> 195 <div class="footer" role="contentinfo"> 196 <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> 197 <td align="left"></td> 198 <td align="right"><div class="copyright-footer"> 199 © Copyright 2016, Paul Fultz II. 200 201 Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.5.6. 202 <p>Distributed under the Boost Software License, Version 1.0. 203 (See accompanying file <code class="filename">LICENSE_1_0.txt</code> or copy at 204 <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) 205 </p> 206 </div></td> 207 </tr></table> 208 </div> 209 </body> 210</html>