File: higher-order.html

package info (click to toggle)
boost 1.34.1-14
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 116,412 kB
  • ctags: 259,566
  • sloc: cpp: 642,395; xml: 56,450; python: 17,612; ansic: 14,520; sh: 2,265; yacc: 858; perl: 481; makefile: 478; lex: 94; sql: 74; csh: 6
file content (144 lines) | stat: -rw-r--r-- 8,812 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<!-- Copyright Aleksey Gurtovoy 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.3.6: http://docutils.sourceforge.net/" />
<title>THE BOOST MPL LIBRARY: Higher-Order Metafunctions</title>
<link rel="stylesheet" href="../style.css" type="text/css" />
</head>
<body class="docframe">
<table class="header"><tr class="header"><td class="header-group navigation-bar"><span class="navigation-group"><a href="./implementing-division.html" class="navigation-link">Prev</a>&nbsp;<a href="./handling-placeholders.html" class="navigation-link">Next</a></span><span class="navigation-group-separator">&nbsp;|&nbsp;</span><span class="navigation-group"><a href="./dimensional-analysis.html" class="navigation-link">Back</a>&nbsp;<a href="./handling-placeholders.html" class="navigation-link">Along</a></span><span class="navigation-group-separator">&nbsp;|&nbsp;</span><span class="navigation-group"><a href="./tutorial-metafunctions.html" class="navigation-link">Up</a>&nbsp;<a href="../index.html" class="navigation-link">Home</a></span><span class="navigation-group-separator">&nbsp;|&nbsp;</span><span class="navigation-group"><a href="./tutorial_toc.html" class="navigation-link">Full TOC</a></span></td>
<td class="header-group page-location"><a href="../index.html" class="navigation-link">Front Page</a> / <a href="./tutorial-metafunctions.html" class="navigation-link">Tutorial: Metafunctions and Higher-Order Metaprogramming</a> / <a href="./higher-order.html" class="navigation-link">Higher-Order Metafunctions</a></td>
</tr></table><div class="header-separator"></div>
<div class="section" id="higher-order">
<h1><a class="toc-backref" href="./tutorial-metafunctions.html#id47" name="higher-order">Higher-Order Metafunctions</a></h1>
<p>In the previous section we used two different forms —
metafunction classes and placeholder expressions — 
to pass and return metafunctions just like any other metadata.
Bundling metafunctions into &quot;first class metadata&quot; allows
<tt class="literal"><span class="pre">transform</span></tt> to perform an infinite variety of different
operations: in our case, multiplication and division of dimensions.
Though the idea of using functions to manipulate other functions
may seem simple, its great power and flexibility <a class="citation-reference" href="#hudak89" id="id9" name="id9">[Hudak89]</a> has
earned it a fancy title: <strong>higher-order functional programming</strong>.
A function that operates on another function is known as a 
<strong>higher-order function</strong>.  It follows that <tt class="literal"><span class="pre">transform</span></tt> is a
higher-order 
metafunction: a metafunction that operates on another metafunction.</p>
<table class="citation" frame="void" id="hudak89" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id9" name="hudak89">[Hudak89]</a></td><td>Paul Hudak. &quot;Conception, Evolution, and Application of
Functional Programming Languages,&quot; ACM Computing Surveys 21,
no. 3 Pages: 359 - 411. New York: ACM Press. 1989.
ISSN:0360-0300. http://doi.acm.org/10.1145/72551.72554.</td></tr>
</tbody>
</table>
<p>Now that we've seen the power of higher-order metafunctions at
work, it would be good to be able to create new ones.  In order to
explore the basic mechanisms, let's try a simple example.  Our task
is to write a metafunction called <tt class="literal"><span class="pre">twice</span></tt>, which — given a unary
metafunction <em>f</em> and arbitrary metadata <em>x</em> — computes:</p>
<blockquote>
<em>twice</em>(<em>f</em>, <em>x</em>) := <em>f</em>(<em>f</em>(<em>x</em>))</blockquote>
<p>This might seem like a trivial example, and in fact it is.  You
won't find much use for <tt class="literal"><span class="pre">twice</span></tt> in real code.  We hope you'll
bear with us anyway:  Because it doesn't do much more than accept
and invoke a metafunction, <tt class="literal"><span class="pre">twice</span></tt> captures all the essential
elements of &quot;higher-orderness&quot; without any distracting details.</p>
<p>If <em>f</em> is a metafunction class, the definition of <tt class="literal"><span class="pre">twice</span></tt> is
straightforward:</p>
<pre class="literal-block">
template &lt;class F, class X&gt;
struct twice
{
    typedef typename F::template apply&lt;X&gt;::type once;    // f(x)
    typedef typename F::template apply&lt;once&gt;::type type; // f(f(x))
};
</pre>
<!-- @ prefix.append(
 '''#include <boost/type_traits/add_pointer.hpp>
    #include <boost/static_assert.hpp>
    #include <boost/type_traits/is_same.hpp>''')

twice_test = '''
#include <boost/mpl/assert.hpp>
struct add_pointer_f
{ 
    template <class T> struct apply : boost::add_pointer<T>
    {};
};
BOOST_MPL_ASSERT((boost::is_same<twice<add_pointer_f,int>::type,int**>));
'''
example.append(twice_test)
compile() -->
<!-- @litre_translator.line_offset -= 7 -->
<p>Or, applying metafunction forwarding:</p>
<pre class="literal-block">
template &lt;class F, class X&gt;
struct twice
  : F::template apply&lt;
       typename F::template apply&lt;X&gt;::type
    &gt;
{};
</pre>
<!-- @ example.append(twice_test)
compile() -->
<div class="admonition-c-language-note admonition">
<p class="admonition-title first">C++ Language Note</p>
<p>The C++ standard requires the <tt class="literal"><span class="pre">template</span></tt> keyword when we use a
<strong>dependent name</strong> that refers to a member template.
<tt class="literal"><span class="pre">F::apply</span></tt> may or may not name a template, <em>depending</em> on the
particular <tt class="literal"><span class="pre">F</span></tt> that is passed.  See <a class="reference" href="./resources.html">the book's</a> Appendix B for more
information about <tt class="literal"><span class="pre">template</span></tt>.</p>
</div>
<p>Given the need to sprinkle our code with the <tt class="literal"><span class="pre">template</span></tt> keyword,
it would be nice to reduce the syntactic burden of invoking
metafunction classes.  As usual, the solution is to factor the
pattern into a metafunction:</p>
<pre class="literal-block">
template &lt;class UnaryMetaFunctionClass, class Arg&gt;
struct apply1
  : UnaryMetaFunctionClass::template apply&lt;Arg&gt;
{};
</pre>
<p>Now <tt class="literal"><span class="pre">twice</span></tt> is just:</p>
<pre class="literal-block">
template &lt;class F, class X&gt;
struct twice
  : apply1&lt;F, typename apply1&lt;F,X&gt;::type&gt;
{};
</pre>
<p>To see <tt class="literal"><span class="pre">twice</span></tt> at work, we can apply it to a little metafunction
class built around the <tt class="literal"><span class="pre">add_pointer</span></tt> metafunction:</p>
<pre class="literal-block">
struct add_pointer_f
{
    template &lt;class T&gt;
    struct apply : boost::add_pointer&lt;T&gt; {};
};
</pre>
<!-- @litre_translator.line_offset -= 7 -->
<p>Now we can use <tt class="literal"><span class="pre">twice</span></tt> with <tt class="literal"><span class="pre">add_pointer_f</span></tt> to build
pointers-to-pointers:</p>
<pre class="literal-block">
BOOST_STATIC_ASSERT((
    boost::is_same&lt;
         twice&lt;add_pointer_f, int&gt;::type
       , int**
    &gt;::value
));
</pre>
<!-- @ apply1 = stack[-4]
add_pointer_f = stack[-2]
compile('all', pop = 0) -->
</div>

<div class="footer-separator"></div>
<table class="footer"><tr class="footer"><td class="header-group navigation-bar"><span class="navigation-group"><a href="./implementing-division.html" class="navigation-link">Prev</a>&nbsp;<a href="./handling-placeholders.html" class="navigation-link">Next</a></span><span class="navigation-group-separator">&nbsp;|&nbsp;</span><span class="navigation-group"><a href="./dimensional-analysis.html" class="navigation-link">Back</a>&nbsp;<a href="./handling-placeholders.html" class="navigation-link">Along</a></span><span class="navigation-group-separator">&nbsp;|&nbsp;</span><span class="navigation-group"><a href="./tutorial-metafunctions.html" class="navigation-link">Up</a>&nbsp;<a href="../index.html" class="navigation-link">Home</a></span><span class="navigation-group-separator">&nbsp;|&nbsp;</span><span class="navigation-group"><a href="./tutorial_toc.html" class="navigation-link">Full TOC</a></span></td>
</tr></table></body>
</html>