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 145 146 147 148 149 150 151 152 153 154 155 156
|
<?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: Representing Dimensions</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="./dimensional-analysis.html" class="navigation-link">Prev</a> <a href="./representing-quantities.html" class="navigation-link">Next</a></span><span class="navigation-group-separator"> | </span><span class="navigation-group">Back <a href="./representing-quantities.html" class="navigation-link">Along</a></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>
<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="./representing-dimensions.html" class="navigation-link">Representing Dimensions</a></td>
</tr></table><div class="header-separator"></div>
<div class="section" id="representing-dimensions">
<h1><a class="toc-backref" href="./dimensional-analysis.html#id42" name="representing-dimensions">Representing Dimensions</a></h1>
<p>An international standard called <em>Système
International d'Unites</em> (SI), breaks every quantity down into a
combination of the dimensions <em>mass</em>, <em>length</em> (or <em>position</em>),
<em>time</em>, <em>charge</em>, <em>temperature</em>, <em>intensity</em>, and <em>angle</em>. To be
reasonably general, our system would have to be able to
represent seven or more fundamental dimensions. It also needs
the ability to represent composite dimensions that, like <em>force</em>,
are built through multiplication or division of the fundamental
ones.</p>
<p>In general, a composite dimension is the product of powers of
fundamental dimensions. <a class="footnote-reference" href="#divisor" id="id6" name="id6">[1]</a> If we were going to represent
these powers for manipulation at runtime, we could use an array of
seven <tt class="literal"><span class="pre">int</span></tt>s, with each position in the array holding the power
of a different fundamental dimension:</p>
<pre class="literal-block">
typedef int dimension[7]; // m l t ...
dimension const mass = {1, 0, 0, 0, 0, 0, 0};
dimension const length = {0, 1, 0, 0, 0, 0, 0};
dimension const time = {0, 0, 1, 0, 0, 0, 0};
...
</pre>
<table class="footnote" frame="void" id="divisor" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id6" name="divisor">[1]</a></td><td>Divisors just contribute negative exponents, since
1/<em>x</em> = <em>x</em><sup>-1</sup>.</td></tr>
</tbody>
</table>
<p>In that representation, force would be:</p>
<pre class="literal-block">
dimension const force = {1, 1, -2, 0, 0, 0, 0};
</pre>
<!-- @compile(2) -->
<!-- @litre_translator.line_offset -= 7 -->
<p>that is, <em>mlt</em><sup>-2</sup>. However, if we want to get dimensions into the
type system, these arrays won't do the trick: they're all
the same type! Instead, we need types that <em>themselves</em> represent
sequences of numbers, so that two masses have the same type and a
mass is a different type from a length.</p>
<p>Fortunately, the MPL provides us with a collection of <strong>type
sequences</strong>. For example, we can build a sequence of the built-in
signed integral types this way:</p>
<pre class="literal-block">
#include <boost/mpl/vector.hpp>
typedef boost::mpl::vector<
signed char, short, int, long> signed_types;
</pre>
<p>How can we use a type sequence to represent numbers? Just as
numerical metafunctions pass and return wrapper <em>types</em> having a
nested <tt class="literal"><span class="pre">::value</span></tt>, so numerical sequences are really sequences of
wrapper types (another example of polymorphism). To make this sort
of thing easier, MPL supplies the <tt class="literal"><span class="pre">int_<N></span></tt> class template, which
presents its integral argument as a nested <tt class="literal"><span class="pre">::value</span></tt>:</p>
<pre class="literal-block">
#include <boost/mpl/int.hpp>
namespace mpl = boost::mpl; // namespace alias
static int const five = mpl::int_<5>::value;
</pre>
<div class="sidebar">
<p class="sidebar-title first">Namespace Aliases</p>
<div class="line-block">
<div class="line"><tt class="literal"><span class="pre">namespace</span></tt> <em>alias</em> <tt class="literal"><span class="pre">=</span></tt> <em>namespace-name</em><tt class="literal"><span class="pre">;</span></tt></div>
</div>
<p>declares <em>alias</em> to be a synonym for <em>namespace-name</em>. Many
examples in this book will use <tt class="literal"><span class="pre">mpl::</span></tt> to indicate
<tt class="literal"><span class="pre">boost::mpl::</span></tt>, but will omit the alias that makes it legal
C++.</p>
</div>
<!-- @ignore() # nonsense isn't worth testing
prefix +=['''
#include <boost/mpl/int.hpp>
#include <boost/mpl/vector.hpp>
'''] -->
<p>In fact, the library contains a whole suite of integral constant
wrappers such as <tt class="literal"><span class="pre">long_</span></tt> and <tt class="literal"><span class="pre">bool_</span></tt>, each one wrapping a
different type of integral constant within a class template.</p>
<p>Now we can build our fundamental dimensions:</p>
<pre class="literal-block">
typedef mpl::vector<
mpl::int_<1>, mpl::int_<0>, mpl::int_<0>, mpl::int_<0>
, mpl::int_<0>, mpl::int_<0>, mpl::int_<0>
> mass;
typedef mpl::vector<
mpl::int_<0>, mpl::int_<1>, mpl::int_<0>, mpl::int_<0>
, mpl::int_<0>, mpl::int_<0>, mpl::int_<0>
> length;
...
</pre>
<!-- @ # We explained about the implicit namespace alias above
prefix.append("""
namespace boost{namespace mpl {}}
namespace mpl = boost::mpl;
""")
compile('all') -->
<p>Whew! That's going to get tiring pretty quickly. Worse, it's hard
to read and verify: The essential information, the powers of each
fundamental dimension, is buried in repetitive syntactic "noise."
Accordingly, MPL supplies <strong>integral sequence wrappers</strong> that allow
us to write:</p>
<pre class="literal-block">
#include <boost/mpl/vector_c.hpp>
typedef mpl::vector_c<int,1,0,0,0,0,0,0> mass;
typedef mpl::vector_c<int,0,1,0,0,0,0,0> length; // or position
typedef mpl::vector_c<int,0,0,1,0,0,0,0> time;
typedef mpl::vector_c<int,0,0,0,1,0,0,0> charge;
typedef mpl::vector_c<int,0,0,0,0,1,0,0> temperature;
typedef mpl::vector_c<int,0,0,0,0,0,1,0> intensity;
typedef mpl::vector_c<int,0,0,0,0,0,0,1> angle;
</pre>
<p>Even though they have different types, you can think of these
<tt class="literal"><span class="pre">mpl::vector_c</span></tt> specializations as being equivalent to the more
verbose versions above that use <tt class="literal"><span class="pre">mpl::vector</span></tt>.</p>
<p>If we want, we can also define a few composite dimensions:</p>
<pre class="literal-block">
// base dimension: m l t ...
typedef mpl::vector_c<int,0,1,-1,0,0,0,0> velocity; // l/t
typedef mpl::vector_c<int,0,1,-2,0,0,0,0> acceleration; // l/(t<sup>2</sup>)
typedef mpl::vector_c<int,1,1,-1,0,0,0,0> momentum; // ml/t
typedef mpl::vector_c<int,1,1,-2,0,0,0,0> force; // ml/(t<sup>2</sup>)
</pre>
<p>And, incidentally, the dimensions of scalars (like pi) can be
described as:</p>
<pre class="literal-block">
typedef mpl::vector_c<int,0,0,0,0,0,0,0> scalar;
</pre>
<!-- @stack[0].replace('hpp>', 'hpp>\nnamespace {')
stack[0].append('}')
compile('all', pop = None) -->
</div>
<div class="footer-separator"></div>
<table class="footer"><tr class="footer"><td class="header-group navigation-bar"><span class="navigation-group"><a href="./dimensional-analysis.html" class="navigation-link">Prev</a> <a href="./representing-quantities.html" class="navigation-link">Next</a></span><span class="navigation-group-separator"> | </span><span class="navigation-group">Back <a href="./representing-quantities.html" class="navigation-link">Along</a></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>
</tr></table></body>
</html>
|