Files
safe_numerics/doc/html/safe.html
2017-02-03 14:24:05 -08:00

271 lines
22 KiB
HTML

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>safe&lt;T, PP, EP&gt;</title>
<link rel="stylesheet" href="boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="index.html" title="Safe Numerics">
<link rel="up" href="types.html" title="Types">
<link rel="prev" href="types.html" title="Types">
<link rel="next" href="safe_range.html" title="safe_signed_range&lt;MIN, MAX, PP, EP&gt; and safe_unsigned_range&lt;MIN, MAX, PP, EP&gt;">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img href="index.html" height="164px" src="pre-boost.jpg" alt="Library Documentation Index"></td>
<td><h2>Safe Numerics</h2></td>
</tr></table>
<div class="spirit-nav">
<a accesskey="p" href="types.html"><img src="images/prev.png" alt="Prev"></a><a accesskey="u" href="types.html"><img src="images/up.png" alt="Up"></a><a accesskey="h" href="index.html"><img src="images/home.png" alt="Home"></a><a accesskey="n" href="safe_range.html"><img src="images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="safe_numerics.safe"></a>safe&lt;T, PP, EP&gt;</h3></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="safe.html#idm50879211680">Description</a></span></dt>
<dt><span class="section"><a href="safe.html#idm50879209712">Notation</a></span></dt>
<dt><span class="section"><a href="safe.html#idm50879202368">Associated Types</a></span></dt>
<dt><span class="section"><a href="safe.html#idm50879195328">Template Parameters</a></span></dt>
<dt><span class="section"><a href="safe.html#idm50879177584">Model of</a></span></dt>
<dt><span class="section"><a href="safe.html#idm50879174992">Valid Expressions</a></span></dt>
<dt><span class="section"><a href="safe.html#idm50879172704">Header</a></span></dt>
<dt><span class="section"><a href="safe.html#idm50879170592">Examples of use</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="idm50879211680"></a>Description</h4></div></div></div>
<p>A <code class="computeroutput">safe&lt;T, PP , EP&gt;</code> can be used anywhere a type T
can be used. Any expression which uses this type is guaranteed to return
an arithmetically correct value or trap in some way.</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="idm50879209712"></a>Notation</h4></div></div></div>
<div class="informaltable"><table class="table">
<colgroup>
<col align="left">
<col align="left">
</colgroup>
<thead><tr>
<th align="left">Symbol</th>
<th align="left">Description</th>
</tr></thead>
<tbody><tr>
<td align="left"><code class="computeroutput">T</code></td>
<td align="left">Underlying type from which a safe type is being
derived</td>
</tr></tbody>
</table></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="idm50879202368"></a>Associated Types</h4></div></div></div>
<div class="informaltable"><table class="table">
<colgroup>
<col align="left">
<col align="left">
</colgroup>
<tbody>
<tr>
<td align="left"><code class="computeroutput">PP</code></td>
<td align="left">A type which specifies the result type of an expression
using safe types.</td>
</tr>
<tr>
<td align="left"><code class="computeroutput">EP</code></td>
<td align="left">A type containing members which are called when a correct
result cannot be returned</td>
</tr>
</tbody>
</table></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="idm50879195328"></a>Template Parameters</h4></div></div></div>
<div class="informaltable"><table class="table">
<colgroup>
<col>
<col align="left">
<col align="left">
</colgroup>
<thead><tr>
<th align="left">Parameter</th>
<th align="left">Type Requirements</th>
<th align="left">Description</th>
</tr></thead>
<tbody>
<tr>
<td><code class="computeroutput">T</code></td>
<td align="left"><a href="http://en.cppreference.com/w/cpp/types/is_integral" target="_top">Integer&lt;T&gt;</a></td>
<td align="left"><p>The underlying type. Currently only integer types
supported</p></td>
</tr>
<tr>
<td><code class="computeroutput">PP</code></td>
<td align="left"><a class="link" href="numeric.html" title="Numeric&lt;T&gt;">PromotionPolicy&lt;PP&gt;</a></td>
<td align="left"><p>Default value is <a class="link" href="promotion_policy.html#safe_numerics.promotion_policy.models.native">boost::numeric::native</a></p></td>
</tr>
<tr>
<td><code class="computeroutput">EP</code></td>
<td align="left"><a class="link" href="numeric.html" title="Numeric&lt;T&gt;">Exception
Policy&lt;EP&gt;</a></td>
<td align="left"><p>Default value is <a class="link" href="exception_policy.html#safe_numerics.exception_policy.models.thow_exception">boost::numeric::throw_exception</a></p></td>
</tr>
</tbody>
</table></div>
<p>See examples below.</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="idm50879177584"></a>Model of</h4></div></div></div>
<p><a class="link" href="numeric.html" title="Numeric&lt;T&gt;">Integer</a></p>
<p><a class="link" href="safe_numeric_concept.html" title="SafeNumeric&lt;T&gt;">SafeNumeric</a></p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="idm50879174992"></a>Valid Expressions</h4></div></div></div>
<p>Implements all expressions and only those expressions defined by the
<a class="link" href="safe_numeric_concept.html" title="SafeNumeric&lt;T&gt;">SafeNumeric</a> type
requirements. This, the result type of such an expression will be another
safe type. The actual type of the result of such an expression will depend
upon the specific promotion policy template parameter.</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="idm50879172704"></a>Header</h4></div></div></div>
<p><code class="filename"><a href="../../include/safe_integer.hpp" target="_top">#include
&lt;boost/safe_numerics/safe_integer.hpp&gt;</a></code></p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="idm50879170592"></a>Examples of use</h4></div></div></div>
<p>The most common usage would be safe&lt;T&gt; which uses the default
promotion and exception policies. This type is meant to be a "drop-in"
replacement of the intrinsic integer types. That is, expressions involving
these types will be evaluated into result types which reflect the standard
rules for evaluation of C++ expressions. Should it occur that such
evaluation cannot return a correct result, an exception will be
thrown.</p>
<p>There are two aspects of the operation of this type which can be
customized with a policy. The first is the result type of an arithmetic
operation. C++ defines the rules which define this result type in terms of
the constituent types of the operation. Here we refer to these rules a
"type promotion" rules. These rules will sometimes result in a type which
cannot hold the actual arithmetic result of the operation. This is the
main motivation for making this library in the first place. One way to
deal with this problem is to substitute our own type promotion rules for
the C++ ones.</p>
<div class="section">
<div class="titlepage"><div><div><h5 class="title">
<a name="safe_numerics.drop_in_replacement"></a>As a Drop-in replacement for standard integer types.</h5></div></div></div>
<p>The following program will throw an exception and emit a error
message at runtime if any of several events result in an incorrect
arithmetic type. Behavior of this program could vary according to the
machine architecture in question.</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">exception</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">numeric</span><span class="special">/</span><span class="identifier">safe</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="special">)</span><span class="special">{</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">;</span>
<span class="identifier">safe</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">j</span><span class="special">;</span>
<span class="keyword">try</span> <span class="special">{</span>
<span class="identifier">safe</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">i</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cin</span> <span class="special">&gt;&gt;</span> <span class="identifier">i</span><span class="special">;</span> <span class="comment">// could overflow !</span>
<span class="identifier">j</span> <span class="special">=</span> <span class="identifier">i</span> <span class="special">*</span> <span class="identifier">i</span><span class="special">;</span> <span class="comment">// could overflow</span>
<span class="special">}</span>
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception</span> <span class="special">&amp;</span> <span class="identifier">e</span><span class="special">)</span><span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">e</span><span class="special">.</span><span class="identifier">what</span><span class="special">(</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">j</span><span class="special">;</span>
<span class="special">}</span></pre>
<p>The term "drop-in replacement" reveals the aspiration of
this library. In most cases, this aspiration is realized. But in some
cases it isn't and can't be. Consider:</p>
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span><span class="special">)</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="special">)</span><span class="special">{</span>
<span class="keyword">long</span> <span class="identifier">x</span><span class="special">;</span>
<span class="identifier">f</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span><span class="special">;</span> <span class="comment">// OK - builtin implicit version</span>
<span class="identifier">safe</span><span class="special">&lt;</span><span class="keyword">long</span><span class="special">&gt;</span> <span class="identifier">y</span><span class="special">;</span>
<span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">)</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span></pre>
<p>The built-in integer types are freely and silently converted
to other integer types in order to permit passing of integer arguments
to other function types. Our view is that this is bad practice and
creates the possibility of subtle bugs. It conflicts with the purpose of
the library in a fundamental way. The library specifies that these
conversions are errors that are to be invoked at compile time. If one
wants to switch between save and built-in types via an alias, this type
of code will have to be fixed so that implicit conversions to built-in
types do not occur. In our view, this will be a net improvement to the
code in any case.</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h5 class="title">
<a name="idm50879093888"></a>Guarantee correct behavior at compile time.</h5></div></div></div>
<p>In some instance catching an error at run time is not sufficient.
We want to be sure that the program can never fail. To achieve this, use
the trap_exception exception policy rather than the default throw
exception policy.</p>
<p>The following program will emit a compile error at any statement
which might possibly result in incorrect behavior.</p>
<p>This is because there is no way to guarantee that the expression i
* i will return an arithmetically correct result. Since we know that the
program cannot compile if there is any possibility of arithmetic error,
we can dispense with the exception handling used above.</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">numeric</span><span class="special">/</span><span class="identifier">safe</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="special">)</span><span class="special">{</span>
<span class="keyword">using</span> <span class="identifier">safe_int</span> <span class="special">=</span> <span class="identifier">safe</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">native</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">trap_exception</span><span class="special">&gt;</span><span class="special">;</span>
<span class="identifier">safe_int</span> <span class="identifier">i</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cin</span> <span class="special">&gt;&gt;</span> <span class="identifier">i</span><span class="special">;</span> <span class="comment">// could throw exception here !!!</span>
<span class="identifier">safe_int</span> <span class="identifier">j</span><span class="special">;</span>
<span class="identifier">j</span> <span class="special">=</span> <span class="identifier">i</span> <span class="special">*</span> <span class="identifier">i</span><span class="special">;</span> <span class="comment">// could throw exception here !!!</span>
<span class="special">}</span></pre>
</div>
<div class="section">
<div class="titlepage"><div><div><h5 class="title">
<a name="idm50879057008"></a>Adjust type promotion rules.</h5></div></div></div>
<p>Another way to avoid arithmetic errors like overflow is to promote
types to larger sizes before doing the arithmetic. This can be justified
by the observe</p>
<p>Stepping back, we can see that many of the cases of invalid
arithmetic are wouldn't exist if results types were larger. So we can
avoid these problems by replacing the C++ type promotion rules for
expressions with our own rules. This can be done by specifying a
non-default type promotion policy automatic. The policy stores the
result of an expression in the smallest size that can accommodate the
largest value that an expression can yield. All the work is done at
compile time - checking for exceptions necessary (input is of course an
exception). The following example illustrates this.</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">numeric</span><span class="special">/</span><span class="identifier">safe</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="special">)</span><span class="special">{</span>
<span class="keyword">using</span> <span class="identifier">safe_int</span> <span class="special">=</span> <span class="identifier">safe</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">automatic</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">throw_exception</span><span class="special">&gt;</span><span class="special">;</span>
<span class="identifier">safe_int</span> <span class="identifier">i</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cin</span> <span class="special">&gt;&gt;</span> <span class="identifier">i</span><span class="special">;</span> <span class="comment">// might throw exception</span>
<span class="keyword">auto</span> <span class="identifier">j</span> <span class="special">=</span> <span class="identifier">i</span> <span class="special">*</span> <span class="identifier">i</span><span class="special">;</span> <span class="comment">// won't ever trap - result type can hold the maximum value of i * i</span>
<span class="identifier">static_assert</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">is_safe</span><span class="special">&lt;</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">j</span><span class="special">)</span><span class="special">&gt;</span><span class="special">::</span><span class="identifier">value</span><span class="special">)</span><span class="special">;</span> <span class="comment">// result is another safe type</span>
<span class="identifier">static_assert</span><span class="special">(</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">i</span> <span class="special">*</span> <span class="identifier">i</span><span class="special">)</span><span class="special">&gt;</span><span class="special">::</span><span class="identifier">max</span><span class="special">(</span><span class="special">)</span> <span class="special">&gt;=</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">safe_int</span><span class="special">&gt;</span><span class="special">::</span><span class="identifier">max</span><span class="special">(</span><span class="special">)</span> <span class="special">*</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">safe_int</span><span class="special">&gt;</span><span class="special">::</span><span class="identifier">max</span><span class="special">(</span><span class="special">)</span>
<span class="special">)</span><span class="special">;</span> <span class="comment">// always true</span>
<span class="special">}</span></pre>
</div>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2012 Robert Ramey<p><a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">Subject to Boost
Software License</a></p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="types.html"><img src="images/prev.png" alt="Prev"></a><a accesskey="u" href="types.html"><img src="images/up.png" alt="Up"></a><a accesskey="h" href="index.html"><img src="images/home.png" alt="Home"></a><a accesskey="n" href="safe_range.html"><img src="images/next.png" alt="Next"></a>
</div>
</body>
</html>