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: Implementing Division
</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.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">
26 template
<class T1, class T2
>
28 : mpl::minus
<T1,T2
> {};
31 <!-- @ # The following is OK because we showed how to get at mpl_plus
32 prefix.append('#include <boost/mpl/minus.hpp>')
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
37 <pre class=
"literal-block">
38 typedef typename ...::type type
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>
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
56 <table class=
"footnote" frame=
"void" id=
"edg" rules=
"none">
57 <colgroup><col class=
"label" /><col /></colgroup>
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>
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>
72 <pre class=
"literal-block">
73 typename mpl::transform
<D1,D2,
<strong>mpl::minus
<_1,_2
></strong> >::type
75 <!-- @# Make it harmless but legit C++ so we can syntax check later
76 example.wrap('template <class D1,class D2>', 'fff(D1,D2);')
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>
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;
95 <p>so that they can be accessed without qualification.
</p>
97 <!-- @ prefix.append(str(example)) # move to common prefix
99 <p>Here's our division operator written using placeholder
101 <pre class=
"literal-block">
102 template
<class T, class D1, class D2
>
105 , typename mpl::transform
<D1,D2,
<strong>mpl::minus
<_1,_2
></strong> >::type
107 operator/(quantity
<T,D1
> x, quantity
<T,D2
> y)
110 mpl::transform
<D1,D2,
<strong>mpl::minus
<_1,_2
></strong> >::type dim;
112 return quantity
<T,dim
>( x.value() / y.value() );
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
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)
129 return quantity
<T, typename
<strong>divide_dimensions
<D1,D2
></strong>::type
>(
130 x.value() / y.value());
133 <!-- @compile('all', pop = None) -->
134 <p>Now we can verify our
"force-on-a-laptop
" computation by reversing
136 <pre class=
"literal-block">
137 quantity
<float,mass
> m2 = f/a;
138 float rounding_error = std::abs((m2 - m).value());
140 <!-- @example.wrap('''
145 quantity<float,mass> m(5.0f);
146 quantity<float,acceleration> a(9.8f);
147 quantity<float,force> f = m * a;
149 assert(rounding_error < .001);
152 dimensional_analysis = stack[:-1] # save for later
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>
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>