1.html 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <html>
  2. <head>
  3. <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
  4. <title>Using Automatic Type Promotion</title>
  5. <link rel="stylesheet" href="../boostbook.css" type="text/css">
  6. <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
  7. <link rel="home" href="../index.html" title="Safe Numerics">
  8. <link rel="up" href="../eliminate_runtime_penalty.html" title="Eliminating Runtime Penalty">
  9. <link rel="prev" href="2.html" title="Using safe_range and safe_literal">
  10. <link rel="next" href="3.html" title="Mixing Approaches">
  11. </head>
  12. <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
  13. <table cellpadding="2" width="100%"><tr>
  14. <td valign="top"><img href="index.html" height="164px" src="pre-boost.jpg" alt="Library Documentation Index"></td>
  15. <td><h2>Safe Numerics</h2></td>
  16. </tr></table>
  17. <div class="spirit-nav">
  18. <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>
  19. </div>
  20. <div class="section">
  21. <div class="titlepage"><div><div><h3 class="title">
  22. <a name="safe_numerics.eliminate_runtime_penalty.1"></a>Using Automatic Type Promotion</h3></div></div></div>
  23. <p>The C++ standard describes how binary operations on different
  24. integer types are handled. Here is a simplified version of the
  25. rules:</p>
  26. <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
  27. <li class="listitem"><p>promote any operand smaller than <code class="computeroutput">int</code> to an
  28. <code class="computeroutput">int</code> or <code class="computeroutput">unsigned int</code>.</p></li>
  29. <li class="listitem"><p>if the size of the signed operand is larger than the size of the
  30. signed operand, the type of the result will be signed. Otherwise, the
  31. type of the result will be unsigned.</p></li>
  32. <li class="listitem"><p>Convert the type each operand to the type of the result,
  33. expanding the size as necessary.</p></li>
  34. <li class="listitem"><p>Perform the operation the two resultant operands.</p></li>
  35. </ul></div>
  36. <p>So the type of the result of some binary operation may be different
  37. than the types of either or both of the original operands.</p>
  38. <p>If the values are large, the result can exceed the size that the
  39. resulting integer type can hold. This is what we call "overflow". The
  40. C/C++ standard characterizes this as undefined behavior and leaves to
  41. compiler implementors the decision as to how such a situation will be
  42. handled. Usually, this means just truncating the result to fit into the
  43. result type - which sometimes will make the result arithmetically
  44. incorrect. However, depending on the compiler and compile time switch
  45. settings, such cases may result in some sort of run time exception or
  46. silently producing some arbitrary result.</p>
  47. <p>The complete signature for a safe integer type is:</p>
  48. <pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span>
  49. <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="comment">// underlying integer type</span>
  50. <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>
  51. <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>
  52. <span class="special">&gt;</span>
  53. <span class="identifier">safe</span><span class="special">;</span>
  54. </pre>
  55. <p>The promotion rules for arithmetic operations are implemented in the
  56. default <code class="computeroutput"><a class="link" href="promotion_policies/native.html" title="native">native</a></code>
  57. type promotion policy are consistent with those of standard C++</p>
  58. <p>Up until now, we've focused on detecting when an arithmetic error
  59. occurs and invoking an exception or other kind of error handler.</p>
  60. <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>
  61. type promotion policy, we can change the rules of C++ arithmetic for safe
  62. types to something like the following:</p>
  63. <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
  64. <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>
  65. what the maximum and minimum values that a variable can be - this
  66. defines a closed interval.</p></li>
  67. <li class="listitem"><p>For any binary operation on these types, we can calculate the
  68. interval of the result at compile time.</p></li>
  69. <li class="listitem">
  70. <p>From this interval we can select a new type which can be
  71. guaranteed to hold the result and use this for the calculation. This
  72. is more or less equivalent to the following code:</p>
  73. <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>
  74. <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>
  75. <span class="comment">// so replace with the following:</span>
  76. <span class="keyword">int</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">y</span><span class="special">;</span>
  77. <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>
  78. <p>One could do this by editing his code manually as above, but
  79. such a task would be tedious, error prone, non-portable and leave
  80. 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>
  81. type promotion policy will achieve the equivalent result without
  82. these problems.</p>
  83. </li>
  84. </ul></div>
  85. <p>When using the <a class="link" href="promotion_policies/automatic.html" title="automatic"><code class="computeroutput">automatic</code></a>
  86. type promotion policy, with a given a binary operation, we silently
  87. promote the types of the operands to a wider result type so the result
  88. cannot overflow. This is a fundamental departure from the C++ Standard
  89. behavior.</p>
  90. <p>If the interval of the result cannot be guaranteed to fit in the
  91. largest type that the machine can handle (usually 64 bits these days), the
  92. largest available integer type with the correct result sign is used. So
  93. even with our "automatic" type promotion scheme, it's still possible to
  94. overflow. So while our <a class="link" href="promotion_policies/automatic.html" title="automatic"><code class="computeroutput">automatic</code></a>
  95. type promotion policy might eliminate exceptions in our example above, it
  96. wouldn't be guaranteed to eliminate them for all programs.</p>
  97. <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>
  98. exception policy will produce a compile time error anytime it's possible
  99. for an error to occur.</p>
  100. <p>This small example illustrates how to use automatic type promotion
  101. to eliminate all runtime penalty.</p>
  102. <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
  103. <span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
  104. <span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
  105. <span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
  106. <span class="preprocessor">#include</span> <span class="string">"safe_format.hpp"</span> <span class="comment">// prints out range and value of any type</span>
  107. <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">&lt;</span>
  108. <span class="keyword">int</span><span class="special">,</span>
  109. <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>
  110. <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>
  111. <span class="special">&gt;</span><span class="special">;</span>
  112. <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>
  113. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"example 82:\n"</span><span class="special">;</span>
  114. <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>
  115. <span class="identifier">safe_t</span> <span class="identifier">y</span> <span class="special">=</span> <span class="number">2</span><span class="special">;</span>
  116. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"x = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">safe_format</span><span class="special">(</span><span class="identifier">x</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>
  117. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"y = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">safe_format</span><span class="special">(</span><span class="identifier">y</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>
  118. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"x + y = "</span> <span class="special">&lt;&lt;</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">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
  119. <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
  120. <span class="special">}</span>
  121. </pre>
  122. <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
  123. <li class="listitem"><p>the <a class="link" href="promotion_policies/automatic.html" title="automatic"><code class="computeroutput">automatic</code></a>
  124. type promotion policy has rendered the result of the sum of two
  125. <code class="computeroutput">integers</code> as a <code class="computeroutput">safe&lt;long</code>&gt; type.</p></li>
  126. <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>
  127. exception policy. This is because since a <code class="computeroutput">long</code> can always
  128. hold the result of the sum of two integers.</p></li>
  129. <li class="listitem"><p>We do not need to use the <code class="computeroutput">try/catch</code> idiom to handle
  130. arithmetic errors - we will have no exceptions.</p></li>
  131. <li class="listitem"><p>We only needed to change two lines of code to achieve our goal
  132. of guaranteed program correctness with no runtime penalty.</p></li>
  133. </ul></div>
  134. <p>The above program produces the following output:</p>
  135. <pre class="screen">example 82:
  136. x = &lt;int&gt;[-2147483648,2147483647] = 2147483647
  137. y = &lt;int&gt;[-2147483648,2147483647] = 2
  138. x + y = &lt;long&gt;[-4294967296,4294967294] = 2147483649
  139. </pre>
  140. <p>Note that if any time in the future we were to change
  141. safe&lt;int&gt; to safe&lt;long long&gt; the program could now overflow.
  142. 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>
  143. the modified program would fail to compile. At this point we'd have to
  144. alter our yet program again to eliminate run time penalty or set aside our
  145. 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>
  146. .</p>
  147. <p>Note that once we use automatic type promotion, our programming
  148. language isn't C/C++ anymore. So don't be tempted to so something like the
  149. following:</p>
  150. <pre class="programlisting"><span class="comment">// DON'T DO THIS !</span>
  151. <span class="preprocessor">#if</span> <span class="identifier">defined</span><span class="special">(</span><span class="identifier">NDEBUG</span><span class="special">)</span>
  152. <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">&lt;</span>
  153. <span class="keyword">int</span><span class="special">,</span>
  154. <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>
  155. <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>
  156. <span class="special">&gt;</span><span class="special">;</span>
  157. <span class="preprocessor">#else</span>
  158. <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">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span><span class="special">;</span>
  159. <span class="preprocessor">#endif</span>
  160. </pre>
  161. </div>
  162. <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
  163. <td align="left"></td>
  164. <td align="right"><div class="copyright-footer">Copyright &#169; 2012-2018 Robert Ramey<p><a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">Subject to Boost
  165. Software License</a></p>
  166. </div></td>
  167. </tr></table>
  168. <hr>
  169. <div class="spirit-nav">
  170. <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>
  171. </div>
  172. </body>
  173. </html>