1 <?xml version=
"1.0" encoding=
"utf-8" ?>
2 <!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html xmlns=
"http://www.w3.org/1999/xhtml" xml:
lang=
"en" lang=
"en">
4 <!-- Copyright Aleksey Gurtovoy 2006. Distributed under the Boost -->
5 <!-- Software License, Version 1.0. (See accompanying -->
6 <!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
8 <meta http-equiv=
"Content-Type" content=
"text/html; charset=utf-8" />
9 <meta name=
"generator" content=
"Docutils 0.3.6: http://docutils.sourceforge.net/" />
10 <title>THE BOOST MPL LIBRARY: Higher-Order Metafunctions
</title>
11 <link rel=
"stylesheet" href=
"../style.css" type=
"text/css" />
13 <body class=
"docframe">
14 <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> <a href=
"./handling-placeholders.html" class=
"navigation-link">Next
</a></span><span class=
"navigation-group-separator"> |
</span><span class=
"navigation-group"><a href=
"./dimensional-analysis.html" class=
"navigation-link">Back
</a> <a href=
"./handling-placeholders.html" class=
"navigation-link">Along
</a></span><span class=
"navigation-group-separator"> |
</span><span class=
"navigation-group"><a href=
"./tutorial-metafunctions.html" class=
"navigation-link">Up
</a> <a href=
"../index.html" class=
"navigation-link">Home
</a></span><span class=
"navigation-group-separator"> |
</span><span class=
"navigation-group"><a href=
"./tutorial_toc.html" class=
"navigation-link">Full TOC
</a></span></td>
15 <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>
16 </tr></table><div class=
"header-separator"></div>
17 <div class=
"section" id=
"higher-order">
18 <h1><a class=
"toc-backref" href=
"./tutorial-metafunctions.html#id47" name=
"higher-order">Higher-Order Metafunctions
</a></h1>
19 <p>In the previous section we used two different forms —
20 metafunction classes and placeholder expressions —
21 to pass and return metafunctions just like any other metadata.
22 Bundling metafunctions into
"first class metadata
" allows
23 <tt class=
"literal"><span class=
"pre">transform
</span></tt> to perform an infinite variety of different
24 operations: in our case, multiplication and division of dimensions.
25 Though the idea of using functions to manipulate other functions
26 may seem simple, its great power and flexibility
<a class=
"citation-reference" href=
"#hudak89" id=
"id9" name=
"id9">[Hudak89]
</a> has
27 earned it a fancy title:
<strong>higher-order functional programming
</strong>.
28 A function that operates on another function is known as a
29 <strong>higher-order function
</strong>. It follows that
<tt class=
"literal"><span class=
"pre">transform
</span></tt> is a
31 metafunction: a metafunction that operates on another metafunction.
</p>
32 <table class=
"citation" frame=
"void" id=
"hudak89" rules=
"none">
33 <colgroup><col class=
"label" /><col /></colgroup>
35 <tr><td class=
"label"><a class=
"fn-backref" href=
"#id9" name=
"hudak89">[Hudak89]
</a></td><td>Paul Hudak.
"Conception, Evolution, and Application of
36 Functional Programming Languages,
" ACM Computing Surveys
21,
37 no.
3 Pages:
359 -
411. New York: ACM Press.
1989.
38 ISSN:
0360-
0300. http://doi.acm.org/
10.1145/
72551.72554.
</td></tr>
41 <p>Now that we've seen the power of higher-order metafunctions at
42 work, it would be good to be able to create new ones. In order to
43 explore the basic mechanisms, let's try a simple example. Our task
44 is to write a metafunction called
<tt class=
"literal"><span class=
"pre">twice
</span></tt>, which — given a unary
45 metafunction
<em>f
</em> and arbitrary metadata
<em>x
</em> — computes:
</p>
47 <em>twice
</em>(
<em>f
</em>,
<em>x
</em>) :=
<em>f
</em>(
<em>f
</em>(
<em>x
</em>))
</blockquote>
48 <p>This might seem like a trivial example, and in fact it is. You
49 won't find much use for
<tt class=
"literal"><span class=
"pre">twice
</span></tt> in real code. We hope you'll
50 bear with us anyway: Because it doesn't do much more than accept
51 and invoke a metafunction,
<tt class=
"literal"><span class=
"pre">twice
</span></tt> captures all the essential
52 elements of
"higher-orderness
" without any distracting details.
</p>
53 <p>If
<em>f
</em> is a metafunction class, the definition of
<tt class=
"literal"><span class=
"pre">twice
</span></tt> is
55 <pre class=
"literal-block">
56 template
<class F, class X
>
59 typedef typename F::template apply
<X
>::type once; // f(x)
60 typedef typename F::template apply
<once
>::type type; // f(f(x))
64 '''#include <boost/type_traits/add_pointer.hpp>
65 #include <boost/static_assert.hpp>
66 #include <boost/type_traits/is_same.hpp>''')
69 #include <boost/mpl/assert.hpp>
72 template <class T> struct apply : boost::add_pointer<T>
75 BOOST_MPL_ASSERT((boost::is_same<twice<add_pointer_f,int>::type,int**>));
77 example.append(twice_test)
79 <!-- @litre_translator.line_offset -= 7 -->
80 <p>Or, applying metafunction forwarding:
</p>
81 <pre class=
"literal-block">
82 template
<class F, class X
>
84 : F::template apply
<
85 typename F::template apply
<X
>::type
89 <!-- @ example.append(twice_test)
91 <div class=
"admonition-c-language-note admonition">
92 <p class=
"admonition-title first">C++ Language Note
</p>
93 <p>The C++ standard requires the
<tt class=
"literal"><span class=
"pre">template
</span></tt> keyword when we use a
94 <strong>dependent name
</strong> that refers to a member template.
95 <tt class=
"literal"><span class=
"pre">F::apply
</span></tt> may or may not name a template,
<em>depending
</em> on the
96 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
97 information about
<tt class=
"literal"><span class=
"pre">template
</span></tt>.
</p>
99 <p>Given the need to sprinkle our code with the
<tt class=
"literal"><span class=
"pre">template
</span></tt> keyword,
100 it would be nice to reduce the syntactic burden of invoking
101 metafunction classes. As usual, the solution is to factor the
102 pattern into a metafunction:
</p>
103 <pre class=
"literal-block">
104 template
<class UnaryMetaFunctionClass, class Arg
>
106 : UnaryMetaFunctionClass::template apply
<Arg
>
109 <p>Now
<tt class=
"literal"><span class=
"pre">twice
</span></tt> is just:
</p>
110 <pre class=
"literal-block">
111 template
<class F, class X
>
113 : apply1
<F, typename apply1
<F,X
>::type
>
116 <p>To see
<tt class=
"literal"><span class=
"pre">twice
</span></tt> at work, we can apply it to a little metafunction
117 class built around the
<tt class=
"literal"><span class=
"pre">add_pointer
</span></tt> metafunction:
</p>
118 <pre class=
"literal-block">
121 template
<class T
>
122 struct apply : boost::add_pointer
<T
> {};
125 <!-- @litre_translator.line_offset -= 7 -->
126 <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
127 pointers-to-pointers:
</p>
128 <pre class=
"literal-block">
129 BOOST_STATIC_ASSERT((
131 twice
<add_pointer_f, int
>::type
136 <!-- @ apply1 = stack[-4]
137 add_pointer_f = stack[-2]
138 compile('all', pop = 0) -->
141 <div class=
"footer-separator"></div>
142 <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> <a href=
"./handling-placeholders.html" class=
"navigation-link">Next
</a></span><span class=
"navigation-group-separator"> |
</span><span class=
"navigation-group"><a href=
"./dimensional-analysis.html" class=
"navigation-link">Back
</a> <a href=
"./handling-placeholders.html" class=
"navigation-link">Along
</a></span><span class=
"navigation-group-separator"> |
</span><span class=
"navigation-group"><a href=
"./tutorial-metafunctions.html" class=
"navigation-link">Up
</a> <a href=
"../index.html" class=
"navigation-link">Home
</a></span><span class=
"navigation-group-separator"> |
</span><span class=
"navigation-group"><a href=
"./tutorial_toc.html" class=
"navigation-link">Full TOC
</a></span></td>