123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
- <title>Using Automatic Type Promotion</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="../eliminate_runtime_penalty.html" title="Eliminating Runtime Penalty">
- <link rel="prev" href="2.html" title="Using safe_range and safe_literal">
- <link rel="next" href="3.html" title="Mixing Approaches">
- </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="2.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../eliminate_runtime_penalty.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="3.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.eliminate_runtime_penalty.1"></a>Using Automatic Type Promotion</h3></div></div></div>
- <p>The C++ standard describes how binary operations on different
- integer types are handled. Here is a simplified version of the
- rules:</p>
- <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
- <li class="listitem"><p>promote any operand smaller than <code class="computeroutput">int</code> to an
- <code class="computeroutput">int</code> or <code class="computeroutput">unsigned int</code>.</p></li>
- <li class="listitem"><p>if the size of the signed operand is larger than the size of the
- signed operand, the type of the result will be signed. Otherwise, the
- type of the result will be unsigned.</p></li>
- <li class="listitem"><p>Convert the type each operand to the type of the result,
- expanding the size as necessary.</p></li>
- <li class="listitem"><p>Perform the operation the two resultant operands.</p></li>
- </ul></div>
- <p>So the type of the result of some binary operation may be different
- than the types of either or both of the original operands.</p>
- <p>If the values are large, the result can exceed the size that the
- resulting integer type can hold. This is what we call "overflow". The
- C/C++ standard characterizes this as undefined behavior and leaves to
- compiler implementors the decision as to how such a situation will be
- handled. Usually, this means just truncating the result to fit into the
- result type - which sometimes will make the result arithmetically
- incorrect. However, depending on the compiler and compile time switch
- settings, such cases may result in some sort of run time exception or
- silently producing some arbitrary result.</p>
- <p>The complete signature for a safe integer type is:</p>
- <pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span>
- <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="comment">// underlying integer type</span>
- <span class="keyword">class</span> <span class="identifier">P</span> <span class="special">=</span> <span class="identifier">native</span><span class="special">,</span> <span class="comment">// type promotion policy class</span>
- <span class="keyword">class</span> <span class="identifier">E</span> <span class="special">=</span> <span class="identifier">default_exception_policy</span> <span class="comment">// error handling policy class</span>
- <span class="special">></span>
- <span class="identifier">safe</span><span class="special">;</span>
- </pre>
- <p>The promotion rules for arithmetic operations are implemented in the
- default <code class="computeroutput"><a class="link" href="promotion_policies/native.html" title="native">native</a></code>
- type promotion policy are consistent with those of standard C++</p>
- <p>Up until now, we've focused on detecting when an arithmetic error
- occurs and invoking an exception or other kind of error handler.</p>
- <p>But now we look at another option. Using the <a class="link" href="promotion_policies/automatic.html" title="automatic"><code class="computeroutput">automatic</code></a>
- type promotion policy, we can change the rules of C++ arithmetic for safe
- types to something like the following:</p>
- <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
- <li class="listitem"><p>for any C++ numeric type, we know from <a href="http://en.cppreference.com/w/cpp/types/numeric_limits" target="_top"><code class="computeroutput">std::numeric_limits</code></a>
- what the maximum and minimum values that a variable can be - this
- defines a closed interval.</p></li>
- <li class="listitem"><p>For any binary operation on these types, we can calculate the
- interval of the result at compile time.</p></li>
- <li class="listitem">
- <p>From this interval we can select a new type which can be
- guaranteed to hold the result and use this for the calculation. This
- is more or less equivalent to the following code:</p>
- <pre class="programlisting"><span class="keyword">int</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">y</span><span class="special">;</span>
- <span class="keyword">int</span> <span class="identifier">z</span> <span class="special">=</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span> <span class="comment">// could overflow</span>
- <span class="comment">// so replace with the following:</span>
- <span class="keyword">int</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">y</span><span class="special">;</span>
- <span class="keyword">long</span> <span class="identifier">z</span> <span class="special">=</span> <span class="special">(</span><span class="keyword">long</span><span class="special">)</span><span class="identifier">x</span> <span class="special">+</span> <span class="special">(</span><span class="keyword">long</span><span class="special">)</span><span class="identifier">y</span><span class="special">;</span> <span class="comment">// can never overflow</span></pre>
- <p>One could do this by editing his code manually as above, but
- such a task would be tedious, error prone, non-portable and leave
- the resulting code hard to read and verify. Using the <a class="link" href="promotion_policies/automatic.html" title="automatic"><code class="computeroutput">automatic</code></a>
- type promotion policy will achieve the equivalent result without
- these problems.</p>
- </li>
- </ul></div>
- <p>When using the <a class="link" href="promotion_policies/automatic.html" title="automatic"><code class="computeroutput">automatic</code></a>
- type promotion policy, with a given a binary operation, we silently
- promote the types of the operands to a wider result type so the result
- cannot overflow. This is a fundamental departure from the C++ Standard
- behavior.</p>
- <p>If the interval of the result cannot be guaranteed to fit in the
- largest type that the machine can handle (usually 64 bits these days), the
- largest available integer type with the correct result sign is used. So
- even with our "automatic" type promotion scheme, it's still possible to
- overflow. So while our <a class="link" href="promotion_policies/automatic.html" title="automatic"><code class="computeroutput">automatic</code></a>
- type promotion policy might eliminate exceptions in our example above, it
- wouldn't be guaranteed to eliminate them for all programs.</p>
- <p>Using the <a class="link" href="exception_policies.html#safe_numerics.exception_policies.loose_trap_policy"><code class="computeroutput">loose_trap_policy</code></a>
- exception policy will produce a compile time error anytime it's possible
- for an error to occur.</p>
- <p>This small example illustrates how to use automatic type promotion
- to eliminate all runtime penalty.</p>
- <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
- <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">safe_numerics</span><span class="special">/</span><span class="identifier">safe_integer</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
- <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">safe_numerics</span><span class="special">/</span><span class="identifier">exception_policies</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
- <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">safe_numerics</span><span class="special">/</span><span class="identifier">automatic</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
- <span class="preprocessor">#include</span> <span class="string">"safe_format.hpp"</span> <span class="comment">// prints out range and value of any type</span>
- <span class="keyword">using</span> <span class="identifier">safe_t</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">safe</span><span class="special"><</span>
- <span class="keyword">int</span><span class="special">,</span>
- <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">automatic</span><span class="special">,</span> <span class="comment">// note use of "automatic" policy!!!</span>
- <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">loose_trap_policy</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="keyword">int</span><span class="special">,</span> <span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="special">[</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">cout</span> <span class="special"><<</span> <span class="string">"example 82:\n"</span><span class="special">;</span>
- <span class="identifier">safe_t</span> <span class="identifier">x</span><span class="special">(</span><span class="identifier">INT_MAX</span><span class="special">)</span><span class="special">;</span>
- <span class="identifier">safe_t</span> <span class="identifier">y</span> <span class="special">=</span> <span class="number">2</span><span class="special">;</span>
- <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"x = "</span> <span class="special"><<</span> <span class="identifier">safe_format</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
- <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"y = "</span> <span class="special"><<</span> <span class="identifier">safe_format</span><span class="special">(</span><span class="identifier">y</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
- <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"x + y = "</span> <span class="special"><<</span> <span class="identifier">safe_format</span><span class="special">(</span><span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
- <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
- <span class="special">}</span>
- </pre>
- <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
- <li class="listitem"><p>the <a class="link" href="promotion_policies/automatic.html" title="automatic"><code class="computeroutput">automatic</code></a>
- type promotion policy has rendered the result of the sum of two
- <code class="computeroutput">integers</code> as a <code class="computeroutput">safe<long</code>> type.</p></li>
- <li class="listitem"><p>our program compiles without error - even when using the <a class="link" href="exception_policies.html#safe_numerics.exception_policies.loose_trap_policy"><code class="computeroutput">loose_trap_policy</code></a>
- exception policy. This is because since a <code class="computeroutput">long</code> can always
- hold the result of the sum of two integers.</p></li>
- <li class="listitem"><p>We do not need to use the <code class="computeroutput">try/catch</code> idiom to handle
- arithmetic errors - we will have no exceptions.</p></li>
- <li class="listitem"><p>We only needed to change two lines of code to achieve our goal
- of guaranteed program correctness with no runtime penalty.</p></li>
- </ul></div>
- <p>The above program produces the following output:</p>
- <pre class="screen">example 82:
- x = <int>[-2147483648,2147483647] = 2147483647
- y = <int>[-2147483648,2147483647] = 2
- x + y = <long>[-4294967296,4294967294] = 2147483649
- </pre>
- <p>Note that if any time in the future we were to change
- safe<int> to safe<long long> the program could now overflow.
- But since we're using <a class="link" href="exception_policies.html#safe_numerics.exception_policies.loose_trap_policy"><code class="computeroutput">loose_trap_policy</code></a>
- the modified program would fail to compile. At this point we'd have to
- alter our yet program again to eliminate run time penalty or set aside our
- goal of zero run time overhead and change the exception policy to <a class="link" href="exception_policies.html#safe_numerics.exception_policies.default_exception_policy"><code class="computeroutput">default_exception_policy</code></a>
- .</p>
- <p>Note that once we use automatic type promotion, our programming
- language isn't C/C++ anymore. So don't be tempted to so something like the
- following:</p>
- <pre class="programlisting"><span class="comment">// DON'T DO THIS !</span>
- <span class="preprocessor">#if</span> <span class="identifier">defined</span><span class="special">(</span><span class="identifier">NDEBUG</span><span class="special">)</span>
- <span class="keyword">using</span> <span class="identifier">safe_t</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">safe</span><span class="special"><</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="comment">// note use of "automatic" policy!!!</span>
- <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">loose_trap_policy</span>
- <span class="special">></span><span class="special">;</span>
- <span class="preprocessor">#else</span>
- <span class="keyword">using</span> <span class="identifier">safe_t</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">safe</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span><span class="special">;</span>
- <span class="preprocessor">#endif</span>
- </pre>
- </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 © 2012-2018 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="2.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../eliminate_runtime_penalty.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="3.html"><img src="../images/next.png" alt="Next"></a>
- </div>
- </body>
- </html>
|