10.html 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <html>
  2. <head>
  3. <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
  4. <title>Programming by Contract is Too Slow</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="../tutorial.html" title="Tutorial and Motivating Examples">
  9. <link rel="prev" href="9.html" title="Compile Time Arithmetic is Not Always Correct">
  10. <link rel="next" href="../eliminate_runtime_penalty.html" title="Eliminating Runtime Penalty">
  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="9.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="../eliminate_runtime_penalty.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.tutorial.10"></a>Programming by Contract is Too Slow</h3></div></div></div>
  23. <p>Programming by Contract is a highly regarded technique. There has
  24. been much written about it and it has been proposed as an addition to the
  25. C++ language [<span class="citation"><a class="xref" href="bibliography.html#garcia" title="C++ language support for contract programming"><abbr class="abbrev">Garcia</abbr></a></span>][<span class="citation"><a class="xref" href="bibliography.html#crowl2" title="Proposal to add Contract Programming to C++"><abbr class="abbrev">Crowl &amp; Ottosen</abbr></a></span>] It (mostly) depends upon runtime checking of
  26. parameter and object values upon entry to and exit from every function.
  27. This can slow the program down considerably which in turn undermines the
  28. main motivation for using C++ in the first place! One popular scheme for
  29. addressing this issue is to enable parameter checking only during
  30. debugging and testing which defeats the guarantee of correctness which we
  31. are seeking here! Programming by Contract will never be accepted by
  32. programmers as long as it is associated with significant additional
  33. runtime cost.</p>
  34. <p>The Safe Numerics Library has facilities which, in many cases, can
  35. check guaranteed parameter requirements with little or no runtime
  36. overhead. Consider the following example:</p>
  37. <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cassert</span><span class="special">&gt;</span>
  38. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">stdexcept</span><span class="special">&gt;</span>
  39. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">sstream</span><span class="special">&gt;</span>
  40. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
  41. <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_range</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  42. <span class="comment">// NOT using safe numerics - enforce program contract explicitly</span>
  43. <span class="comment">// return total number of minutes</span>
  44. <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">contract_convert</span><span class="special">(</span>
  45. <span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="special">&amp;</span> <span class="identifier">hours</span><span class="special">,</span>
  46. <span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="special">&amp;</span> <span class="identifier">minutes</span>
  47. <span class="special">)</span> <span class="special">{</span>
  48. <span class="comment">// check that parameters are within required limits</span>
  49. <span class="comment">// invokes a runtime cost EVERYTIME the function is called</span>
  50. <span class="comment">// and the overhead of supporting an interrupt.</span>
  51. <span class="comment">// note high runtime cost!</span>
  52. <span class="keyword">if</span><span class="special">(</span><span class="identifier">minutes</span> <span class="special">&gt;</span> <span class="number">59</span><span class="special">)</span>
  53. <span class="keyword">throw</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">domain_error</span><span class="special">(</span><span class="string">"minutes exceeded 59"</span><span class="special">)</span><span class="special">;</span>
  54. <span class="keyword">if</span><span class="special">(</span><span class="identifier">hours</span> <span class="special">&gt;</span> <span class="number">23</span><span class="special">)</span>
  55. <span class="keyword">throw</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">domain_error</span><span class="special">(</span><span class="string">"hours exceeded 23"</span><span class="special">)</span><span class="special">;</span>
  56. <span class="keyword">return</span> <span class="identifier">hours</span> <span class="special">*</span> <span class="number">60</span> <span class="special">+</span> <span class="identifier">minutes</span><span class="special">;</span>
  57. <span class="special">}</span>
  58. <span class="comment">// Use safe numerics to enforce program contract automatically</span>
  59. <span class="comment">// define convenient typenames for hours and minutes hh:mm</span>
  60. <span class="keyword">using</span> <span class="identifier">hours_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_unsigned_range</span><span class="special">&lt;</span><span class="number">0</span><span class="special">,</span> <span class="number">23</span><span class="special">&gt;</span><span class="special">;</span>
  61. <span class="keyword">using</span> <span class="identifier">minutes_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_unsigned_range</span><span class="special">&lt;</span><span class="number">0</span><span class="special">,</span> <span class="number">59</span><span class="special">&gt;</span><span class="special">;</span>
  62. <span class="keyword">using</span> <span class="identifier">minutes_total_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_unsigned_range</span><span class="special">&lt;</span><span class="number">0</span><span class="special">,</span> <span class="number">59</span><span class="special">&gt;</span><span class="special">;</span>
  63. <span class="comment">// return total number of minutes</span>
  64. <span class="comment">// type returned is safe_unsigned_range&lt;0, 24*60 - 1&gt;</span>
  65. <span class="keyword">auto</span> <span class="identifier">convert</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">hours_t</span> <span class="special">&amp;</span> <span class="identifier">hours</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">minutes_t</span> <span class="special">&amp;</span> <span class="identifier">minutes</span><span class="special">)</span> <span class="special">{</span>
  66. <span class="comment">// no need to test pre-conditions</span>
  67. <span class="comment">// input parameters are guaranteed to hold legitimate values</span>
  68. <span class="comment">// no need to test post-conditions</span>
  69. <span class="comment">// return value guaranteed to hold result</span>
  70. <span class="keyword">return</span> <span class="identifier">hours</span> <span class="special">*</span> <span class="number">60</span> <span class="special">+</span> <span class="identifier">minutes</span><span class="special">;</span>
  71. <span class="special">}</span>
  72. <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">test1</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">hours</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">minutes</span><span class="special">)</span><span class="special">{</span>
  73. <span class="comment">// problem: checking of externally produced value can be expensive</span>
  74. <span class="comment">// invalid parameters - detected - but at a heavy cost</span>
  75. <span class="keyword">return</span> <span class="identifier">contract_convert</span><span class="special">(</span><span class="identifier">hours</span><span class="special">,</span> <span class="identifier">minutes</span><span class="special">)</span><span class="special">;</span>
  76. <span class="special">}</span>
  77. <span class="keyword">auto</span> <span class="identifier">test2</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">hours</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">minutes</span><span class="special">)</span><span class="special">{</span>
  78. <span class="comment">// solution: use safe numerics</span>
  79. <span class="comment">// safe types can be implicitly constructed base types</span>
  80. <span class="comment">// construction guarentees corectness</span>
  81. <span class="comment">// return value is known to fit in unsigned int</span>
  82. <span class="keyword">return</span> <span class="identifier">convert</span><span class="special">(</span><span class="identifier">hours</span><span class="special">,</span> <span class="identifier">minutes</span><span class="special">)</span><span class="special">;</span>
  83. <span class="special">}</span>
  84. <span class="keyword">auto</span> <span class="identifier">test3</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">hours</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">minutes</span><span class="special">)</span><span class="special">{</span>
  85. <span class="comment">// actually we don't even need the convert function any more</span>
  86. <span class="keyword">return</span> <span class="identifier">hours_t</span><span class="special">(</span><span class="identifier">hours</span><span class="special">)</span> <span class="special">*</span> <span class="number">60</span> <span class="special">+</span> <span class="identifier">minutes_t</span><span class="special">(</span><span class="identifier">minutes</span><span class="special">)</span><span class="special">;</span>
  87. <span class="special">}</span>
  88. <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>
  89. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"example 7: "</span><span class="special">;</span>
  90. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"enforce contracts with zero runtime cost"</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>
  91. <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">total_minutes</span><span class="special">;</span>
  92. <span class="keyword">try</span> <span class="special">{</span>
  93. <span class="identifier">total_minutes</span> <span class="special">=</span> <span class="identifier">test3</span><span class="special">(</span><span class="number">17</span><span class="special">,</span> <span class="number">83</span><span class="special">)</span><span class="special">;</span>
  94. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"total minutes = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">total_minutes</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>
  95. <span class="special">}</span>
  96. <span class="keyword">catch</span><span class="special">(</span><span class="keyword">const</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>
  97. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"parameter error detected"</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>
  98. <span class="special">}</span>
  99. <span class="keyword">try</span> <span class="special">{</span>
  100. <span class="identifier">total_minutes</span> <span class="special">=</span> <span class="identifier">test3</span><span class="special">(</span><span class="number">17</span><span class="special">,</span> <span class="number">10</span><span class="special">)</span><span class="special">;</span>
  101. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"total minutes = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">total_minutes</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>
  102. <span class="special">}</span>
  103. <span class="keyword">catch</span><span class="special">(</span><span class="keyword">const</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>
  104. <span class="comment">// should never arrive here</span>
  105. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"parameter error erroneously detected"</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>
  106. <span class="keyword">return</span> <span class="number">1</span><span class="special">;</span>
  107. <span class="special">}</span>
  108. <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
  109. <span class="special">}</span>
  110. </pre>
  111. <pre class="screen">example 8:
  112. enforce contracts with zero runtime cost
  113. parameter error detected</pre>
  114. <p>In the example above, the function <code class="computeroutput">convert</code> incurs
  115. significant runtime cost every time the function is called. By using
  116. "safe" types, this cost is moved to the moment when the parameters are
  117. constructed. Depending on how the program is constructed, this may totally
  118. eliminate extraneous computations for parameter requirement type checking.
  119. In this scenario, there is no reason to suppress the checking for release
  120. mode and our program can be guaranteed to be always arithmetically
  121. correct.</p>
  122. </div>
  123. <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
  124. <td align="left"></td>
  125. <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
  126. Software License</a></p>
  127. </div></td>
  128. </tr></table>
  129. <hr>
  130. <div class="spirit-nav">
  131. <a accesskey="p" href="9.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="../eliminate_runtime_penalty.html"><img src="../images/next.png" alt="Next"></a>
  132. </div>
  133. </body>
  134. </html>