• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &#8212; 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">&lt;</span><span class="kt">int</span><span class="o">&gt;</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">&amp;</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">&lt;</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">&gt;</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">&amp;</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">&lt;</span><span class="kt">int</span><span class="o">&gt;</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">&lt;</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">&gt;</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">&lt;</span><span class="kt">int</span><span class="o">&gt;</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">&lt;</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">&gt;</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">&lt;</span><span class="kt">int</span><span class="o">&gt;</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 &#8220;enhancements&#8221; to the function. One enhancement is to write &#8220;extension&#8221; 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">&lt;</span><span class="n">sum</span><span class="o">&gt;</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&#8217;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            &#169; 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>