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) --> |
---|
7 | <head> |
---|
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: Implementing Division</title> |
---|
11 | <link rel="stylesheet" href="../style.css" type="text/css" /> |
---|
12 | </head> |
---|
13 | <body class="docframe"> |
---|
14 | <table class="header"><tr class="header"><td class="header-group navigation-bar"><span class="navigation-group"><a href="./implementing.html" class="navigation-link">Prev</a> <a href="./higher-order.html" class="navigation-link">Next</a></span><span class="navigation-group-separator"> | </span><span class="navigation-group"><a href="./implementing.html" class="navigation-link">Back</a> Along</span><span class="navigation-group-separator"> | </span><span class="navigation-group"><a href="./dimensional-analysis.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="./dimensional-analysis.html" class="navigation-link">Dimensional Analysis</a> / <a href="./implementing-division.html" class="navigation-link">Implementing Division</a></td> |
---|
16 | </tr></table><div class="header-separator"></div> |
---|
17 | <div class="section" id="implementing-division"> |
---|
18 | <h1><a class="toc-backref" href="./dimensional-analysis.html#id46" name="implementing-division">Implementing Division</a></h1> |
---|
19 | <p>Division is similar to multiplication, but instead of adding |
---|
20 | exponents, we must subtract them. Rather than writing out a near |
---|
21 | duplicate of <tt class="literal"><span class="pre">plus_f</span></tt>, we can use the following trick to make |
---|
22 | <tt class="literal"><span class="pre">minus_f</span></tt> much simpler:</p> |
---|
23 | <pre class="literal-block"> |
---|
24 | struct minus_f |
---|
25 | { |
---|
26 | template <class T1, class T2> |
---|
27 | struct apply |
---|
28 | : mpl::minus<T1,T2> {}; |
---|
29 | }; |
---|
30 | </pre> |
---|
31 | <!-- @ # The following is OK because we showed how to get at mpl_plus |
---|
32 | prefix.append('#include <boost/mpl/minus.hpp>') |
---|
33 | compile(1) --> |
---|
34 | <p>Here <tt class="literal"><span class="pre">minus_f::apply</span></tt> uses inheritance to expose the nested |
---|
35 | <tt class="literal"><span class="pre">type</span></tt> of its base class, <tt class="literal"><span class="pre">mpl::minus</span></tt>, so we don't have to |
---|
36 | write:</p> |
---|
37 | <pre class="literal-block"> |
---|
38 | typedef typename ...::type type |
---|
39 | </pre> |
---|
40 | <!-- @ignore() --> |
---|
41 | <p>We don't have to write |
---|
42 | <tt class="literal"><span class="pre">typename</span></tt> here (in fact, it would be illegal), because the |
---|
43 | compiler knows that dependent names in <tt class="literal"><span class="pre">apply</span></tt>'s initializer |
---|
44 | list must be base classes. <a class="footnote-reference" href="#plus-too" id="id7" name="id7">[2]</a> This powerful |
---|
45 | simplification is known as <strong>metafunction forwarding</strong>; we'll apply |
---|
46 | it often as the book goes on. <a class="footnote-reference" href="#edg" id="id8" name="id8">[3]</a></p> |
---|
47 | <table class="footnote" frame="void" id="plus-too" rules="none"> |
---|
48 | <colgroup><col class="label" /><col /></colgroup> |
---|
49 | <tbody valign="top"> |
---|
50 | <tr><td class="label"><a class="fn-backref" href="#id7" name="plus-too">[2]</a></td><td>In case you're wondering, the same approach could |
---|
51 | have been applied to <tt class="literal"><span class="pre">plus_f</span></tt>, but since it's a little subtle, |
---|
52 | we introduced the straightforward but verbose formulation |
---|
53 | first.</td></tr> |
---|
54 | </tbody> |
---|
55 | </table> |
---|
56 | <table class="footnote" frame="void" id="edg" rules="none"> |
---|
57 | <colgroup><col class="label" /><col /></colgroup> |
---|
58 | <tbody valign="top"> |
---|
59 | <tr><td class="label"><a class="fn-backref" href="#id8" name="edg">[3]</a></td><td>Users of EDG-based compilers should consult <a class="reference" href="./resources.html">the book's</a> Appendix C |
---|
60 | for a caveat about metafunction forwarding. You can tell whether |
---|
61 | you have an EDG compiler by checking the preprocessor symbol |
---|
62 | <tt class="literal"><span class="pre">__EDG_VERSION__</span></tt>, which is defined by all EDG-based compilers.</td></tr> |
---|
63 | </tbody> |
---|
64 | </table> |
---|
65 | <p>Syntactic tricks notwithstanding, writing trivial classes to wrap |
---|
66 | existing metafunctions is going to get boring pretty quickly. Even |
---|
67 | though the definition of <tt class="literal"><span class="pre">minus_f</span></tt> was far less verbose than that |
---|
68 | of <tt class="literal"><span class="pre">plus_f</span></tt>, it's still an awful lot to type. Fortunately, MPL gives |
---|
69 | us a <em>much</em> simpler way to pass metafunctions around. Instead of |
---|
70 | building a whole metafunction class, we can invoke <tt class="literal"><span class="pre">transform</span></tt> |
---|
71 | this way:</p> |
---|
72 | <pre class="literal-block"> |
---|
73 | typename mpl::transform<D1,D2, <strong>mpl::minus<_1,_2></strong> >::type |
---|
74 | </pre> |
---|
75 | <!-- @# Make it harmless but legit C++ so we can syntax check later |
---|
76 | example.wrap('template <class D1,class D2>', 'fff(D1,D2);') |
---|
77 | |
---|
78 | # We explain placeholders below, so we can henceforth use them |
---|
79 | # without qualification --> |
---|
80 | <p>Those funny looking arguments (<tt class="literal"><span class="pre">_1</span></tt> and <tt class="literal"><span class="pre">_2</span></tt>) are known as |
---|
81 | <strong>placeholders</strong>, and they signify that when the <tt class="literal"><span class="pre">transform</span></tt>'s |
---|
82 | <tt class="literal"><span class="pre">BinaryOperation</span></tt> is invoked, its first and second arguments will |
---|
83 | be passed on to <tt class="literal"><span class="pre">minus</span></tt> in the positions indicated by <tt class="literal"><span class="pre">_1</span></tt> and |
---|
84 | <tt class="literal"><span class="pre">_2</span></tt>, respectively. The whole type <tt class="literal"><span class="pre">mpl::minus<_1,_2></span></tt> is |
---|
85 | known as a <strong>placeholder expression</strong>.</p> |
---|
86 | <div class="note"> |
---|
87 | <p class="admonition-title first">Note</p> |
---|
88 | <p>MPL's placeholders are in the <tt class="literal"><span class="pre">mpl::placeholders</span></tt> |
---|
89 | namespace and defined in <tt class="literal"><span class="pre">boost/mpl/placeholders.hpp</span></tt>. In |
---|
90 | this book we will usually assume that you have written:</p> |
---|
91 | <pre class="literal-block"> |
---|
92 | #include<boost/mpl/placeholders.hpp> |
---|
93 | using namespace mpl::placeholders; |
---|
94 | </pre> |
---|
95 | <p>so that they can be accessed without qualification.</p> |
---|
96 | </div> |
---|
97 | <!-- @ prefix.append(str(example)) # move to common prefix |
---|
98 | ignore() --> |
---|
99 | <p>Here's our division operator written using placeholder |
---|
100 | expressions:</p> |
---|
101 | <pre class="literal-block"> |
---|
102 | template <class T, class D1, class D2> |
---|
103 | quantity< |
---|
104 | T |
---|
105 | , typename mpl::transform<D1,D2,<strong>mpl::minus<_1,_2></strong> >::type |
---|
106 | > |
---|
107 | operator/(quantity<T,D1> x, quantity<T,D2> y) |
---|
108 | { |
---|
109 | typedef typename |
---|
110 | mpl::transform<D1,D2,<strong>mpl::minus<_1,_2></strong> >::type dim; |
---|
111 | |
---|
112 | return quantity<T,dim>( x.value() / y.value() ); |
---|
113 | } |
---|
114 | </pre> |
---|
115 | <!-- @compile('all', pop = 1) --> |
---|
116 | <p>This code is considerably simpler. We can simplify it even further |
---|
117 | by factoring the code that calculates the new dimensions into its |
---|
118 | own metafunction:</p> |
---|
119 | <pre class="literal-block"> |
---|
120 | template <class D1, class D2> |
---|
121 | struct <strong>divide_dimensions</strong> |
---|
122 | : mpl::transform<D1,D2,mpl::minus<_1,_2> > // forwarding again |
---|
123 | {}; |
---|
124 | |
---|
125 | template <class T, class D1, class D2> |
---|
126 | quantity<T, typename <strong>divide_dimensions<D1,D2></strong>::type> |
---|
127 | operator/(quantity<T,D1> x, quantity<T,D2> y) |
---|
128 | { |
---|
129 | return quantity<T, typename <strong>divide_dimensions<D1,D2></strong>::type>( |
---|
130 | x.value() / y.value()); |
---|
131 | } |
---|
132 | </pre> |
---|
133 | <!-- @compile('all', pop = None) --> |
---|
134 | <p>Now we can verify our "force-on-a-laptop" computation by reversing |
---|
135 | it, as follows:</p> |
---|
136 | <pre class="literal-block"> |
---|
137 | quantity<float,mass> m2 = f/a; |
---|
138 | float rounding_error = std::abs((m2 - m).value()); |
---|
139 | </pre> |
---|
140 | <!-- @example.wrap(''' |
---|
141 | #include <cassert> |
---|
142 | #include <cmath> |
---|
143 | int main() |
---|
144 | { |
---|
145 | quantity<float,mass> m(5.0f); |
---|
146 | quantity<float,acceleration> a(9.8f); |
---|
147 | quantity<float,force> f = m * a; |
---|
148 | ''',''' |
---|
149 | assert(rounding_error < .001); |
---|
150 | }''') |
---|
151 | |
---|
152 | dimensional_analysis = stack[:-1] # save for later |
---|
153 | |
---|
154 | run('all') --> |
---|
155 | <p>If we got everything right, <tt class="literal"><span class="pre">rounding_error</span></tt> should be very close |
---|
156 | to zero. These are boring calculations, but they're just the sort |
---|
157 | of thing that could ruin a whole program (or worse) if you got them |
---|
158 | wrong. If we had written <tt class="literal"><span class="pre">a/f</span></tt> instead of <tt class="literal"><span class="pre">f/a</span></tt>, there would have |
---|
159 | been a compilation error, preventing a mistake from propagating |
---|
160 | throughout our program.</p> |
---|
161 | </div> |
---|
162 | |
---|
163 | <div class="footer-separator"></div> |
---|
164 | <table class="footer"><tr class="footer"><td class="header-group navigation-bar"><span class="navigation-group"><a href="./implementing.html" class="navigation-link">Prev</a> <a href="./higher-order.html" class="navigation-link">Next</a></span><span class="navigation-group-separator"> | </span><span class="navigation-group"><a href="./implementing.html" class="navigation-link">Back</a> Along</span><span class="navigation-group-separator"> | </span><span class="navigation-group"><a href="./dimensional-analysis.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> |
---|
165 | </tr></table></body> |
---|
166 | </html> |
---|