• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
42<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>
43
44<span class="comment">// NOT using safe numerics - enforce program contract explicitly</span>
45<span class="comment">// return total number of minutes</span>
46<span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">contract_convert</span><span class="special">(</span>
47    <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>
48    <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>
49<span class="special">)</span> <span class="special">{</span>
50    <span class="comment">// check that parameters are within required limits</span>
51    <span class="comment">// invokes a runtime cost EVERYTIME the function is called</span>
52    <span class="comment">// and the overhead of supporting an interrupt.</span>
53    <span class="comment">// note high runtime cost!</span>
54    <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>
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">"minutes exceeded 59"</span><span class="special">)</span><span class="special">;</span>
56    <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>
57        <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>
58    <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>
59<span class="special">}</span>
60
61<span class="comment">// Use safe numerics to enforce program contract automatically</span>
62<span class="comment">// define convenient typenames for hours and minutes hh:mm</span>
63<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>
64<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>
65<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>
66
67<span class="comment">// return total number of minutes</span>
68<span class="comment">// type returned is safe_unsigned_range&lt;0, 24*60 - 1&gt;</span>
69<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>
70    <span class="comment">// no need to test pre-conditions</span>
71    <span class="comment">// input parameters are guaranteed to hold legitimate values</span>
72    <span class="comment">// no need to test post-conditions</span>
73    <span class="comment">// return value guaranteed to hold result</span>
74    <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>
75<span class="special">}</span>
76
77<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>
78    <span class="comment">// problem: checking of externally produced value can be expensive</span>
79    <span class="comment">// invalid parameters - detected - but at a heavy cost</span>
80    <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>
81<span class="special">}</span>
82
83<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>
84    <span class="comment">// solution: use safe numerics</span>
85    <span class="comment">// safe types can be implicitly constructed base types</span>
86    <span class="comment">// construction guarentees corectness</span>
87    <span class="comment">// return value is known to fit in unsigned int</span>
88    <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>
89<span class="special">}</span>
90
91<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>
92    <span class="comment">// actually we don't even need the convert function any more</span>
93    <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>
94<span class="special">}</span>
95
96<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>
97    <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>
98    <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>
99
100    <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">total_minutes</span><span class="special">;</span>
101
102    <span class="keyword">try</span> <span class="special">{</span>
103        <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>
104        <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>
105    <span class="special">}</span>
106    <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>
107        <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>
108    <span class="special">}</span>
109
110    <span class="keyword">try</span> <span class="special">{</span>
111        <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>
112        <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>
113    <span class="special">}</span>
114    <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>
115        <span class="comment">// should never arrive here</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">"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>
117        <span class="keyword">return</span> <span class="number">1</span><span class="special">;</span>
118    <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<pre class="screen">example 8:
123enforce contracts with zero runtime cost
124parameter error detected</pre>
125<p>In the example above, the function <code class="computeroutput">convert</code> incurs
126    significant runtime cost every time the function is called. By using
127    "safe" types, this cost is moved to the moment when the parameters are
128    constructed. Depending on how the program is constructed, this may totally
129    eliminate extraneous computations for parameter requirement type checking.
130    In this scenario, there is no reason to suppress the checking for release
131    mode and our program can be guaranteed to be always arithmetically
132    correct.</p>
133</div>
134<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
135<td align="left"></td>
136<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
137      Software License</a></p>
138</div></td>
139</tr></table>
140<hr>
141<div class="spirit-nav">
142<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>
143</div>
144</body>
145</html>
146