• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.1//EN"
3"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
4<section id="safe_numerics.safe">
5  <title>safe&lt;T, PP, EP&gt;</title>
6
7  <?dbhtml stop-chunking?>
8
9  <section>
10    <title>Description</title>
11
12    <para>A <code>safe&lt;T, PP , EP&gt;</code> can be used anywhere a type T
13    can be used. Any expression which uses this type is guaranteed to return
14    an arithmetically correct value or to trap in some way.</para>
15  </section>
16
17  <section>
18    <title>Model of</title>
19
20    <para><link linkend="safe_numerics.numeric">Integer</link></para>
21
22    <para><link
23    linkend="safe_numerics.safe_numeric_concept">SafeNumeric</link></para>
24
25    <para>This type inherits all the notation, associated types and template
26    parameters and valid expressions of <link
27    linkend="safe_numerics.safe_numeric_concept">SafeNumeric</link> types. The
28    following specify additional features of this type.</para>
29  </section>
30
31  <section>
32    <title>Notation</title>
33
34    <informaltable>
35      <tgroup cols="2">
36        <colspec align="left" colwidth="1*"/>
37
38        <colspec align="left" colwidth="10*"/>
39
40        <thead>
41          <row>
42            <entry align="left">Symbol</entry>
43
44            <entry align="left">Description</entry>
45          </row>
46        </thead>
47
48        <tbody>
49          <row>
50            <entry><code>T</code></entry>
51
52            <entry>Underlying type from which a safe type is being
53            derived</entry>
54          </row>
55        </tbody>
56      </tgroup>
57    </informaltable>
58  </section>
59
60  <section>
61    <title>Associated Types</title>
62
63    <informaltable>
64      <tgroup cols="2">
65        <colspec align="left" colwidth="1*"/>
66
67        <colspec align="left" colwidth="10*"/>
68
69        <tbody>
70          <row>
71            <entry><code>PP</code></entry>
72
73            <entry>A type which specifies the result type of an expression
74            using safe types.</entry>
75          </row>
76
77          <row>
78            <entry><code>EP</code></entry>
79
80            <entry>A type containing members which are called when a correct
81            result cannot be returned</entry>
82          </row>
83        </tbody>
84      </tgroup>
85    </informaltable>
86  </section>
87
88  <section>
89    <title>Template Parameters</title>
90
91    <informaltable>
92      <tgroup cols="3">
93        <colspec colwidth="1*"/>
94
95        <colspec align="left" colwidth="3*"/>
96
97        <colspec align="left" colwidth="7*"/>
98
99        <thead>
100          <row>
101            <entry align="left">Parameter</entry>
102
103            <entry align="left">Type Requirements</entry>
104
105            <entry>Description</entry>
106          </row>
107        </thead>
108
109        <tbody>
110          <row>
111            <entry><code>T</code></entry>
112
113            <entry><ulink
114            url="http://en.cppreference.com/w/cpp/types/is_integral">Integer&lt;T&gt;</ulink></entry>
115
116            <entry><para>The underlying type. Currently only integer types are
117            supported</para></entry>
118          </row>
119
120          <row>
121            <entry><code>PP</code></entry>
122
123            <entry><link linkend="safe_numerics.numeric"><link
124            linkend="safe_numerics.promotion_policy">PromotionPolicy&lt;PP&gt;</link></link></entry>
125
126            <entry><para>Optional promotion policy. Default value is <link
127            linkend="safe_numerics.promotion_policies.native"><code>boost::numeric::native</code></link></para></entry>
128          </row>
129
130          <row>
131            <entry><code>EP</code></entry>
132
133            <entry><link linkend="safe_numerics.numeric"><link
134            linkend="safe_numerics.exception_policy">Exception
135            Policy&lt;EP&gt;</link></link></entry>
136
137            <entry><para>Optional exception policy. Default value is <link
138            linkend="safe_numerics.exception_policies.default_exception_policy"><code>boost::numeric::default_exception_policy</code></link></para></entry>
139          </row>
140        </tbody>
141      </tgroup>
142    </informaltable>
143
144    <para>See examples below.</para>
145  </section>
146
147  <section>
148    <title>Valid Expressions</title>
149
150    <para>Implements all expressions and only those expressions defined by the
151    <link
152    linkend="safe_numerics.safe_numeric_concept">SafeNumeric</link>&lt;T&gt;
153    type requirements. Note that all these expressions are
154    <code>constexpr</code>. Thus, the result type of such an expression will
155    be another safe type. The actual type of the result of such an expression
156    will depend upon the specific promotion policy template parameter.</para>
157
158    <para>When a binary operand is applied to two instances of safe&lt;T, PP,
159    EP&gt;on of the following must be true:<itemizedlist>
160        <listitem>
161          <para>The promotion policies of the two operands must be the same or
162          one of them must be void</para>
163        </listitem>
164
165        <listitem>
166          <para>The exception policies of the two operands must be the same or
167          one of them must be void</para>
168        </listitem>
169      </itemizedlist>If either of the above is not true, a compile error will
170    result.</para>
171  </section>
172
173  <section>
174    <title>Examples of use</title>
175
176    <para>The most common usage would be safe&lt;T&gt; which uses the default
177    promotion and exception policies. This type is meant to be a "drop-in"
178    replacement of the intrinsic integer types. That is, expressions involving
179    these types will be evaluated into result types which reflect the standard
180    rules for evaluation of C++ expressions. Should it occur that such
181    evaluation cannot return a correct result, an exception will be
182    thrown.</para>
183
184    <para>There are two aspects of the operation of this type which can be
185    customized with a policy. The first is the result type of an arithmetic
186    operation. C++ defines the rules which define this result type in terms of
187    the constituent types of the operation. Here we refer to these rules as
188    "type promotion" rules. These rules will sometimes result in a type which
189    cannot hold the actual arithmetic result of the operation. This is the
190    main motivation for making this library in the first place. One way to
191    deal with this problem is to substitute our own type promotion rules for
192    the C++ ones.</para>
193
194    <section id="safe_numerics.drop_in_replacement">
195      <title>As a Drop-in replacement for standard integer types.</title>
196
197      <para>The following program will throw an exception and emit an error
198      message at runtime if any of several events result in an incorrect
199      arithmetic result. Behavior of this program could vary according to the
200      machine architecture in question.</para>
201
202      <para><programlisting>#include &lt;exception&gt;
203#include &lt;iostream&gt;
204#include &lt;safe_integer.hpp&gt;
205
206void f(){
207    using namespace boost::numeric;
208    safe&lt;int&gt; j;
209    try {
210        safe&lt;int&gt; i;
211        std::cin &gt;&gt; i;  // could overflow !
212        j = i * i;      // could overflow
213    }
214    catch(std::exception &amp; e){
215       std::cout &lt;&lt; e.what() &lt;&lt; std::endl;
216    }
217    std::cout &lt;&lt; j;
218}</programlisting>The term "drop-in replacement" reveals the aspiration of
219      this library. In most cases, this aspiration is realized. In the
220      following example, the normal implicit conversions function the same for
221      safe integers as they do for built-in integers. <programlisting><xi:include
222            href="../../example/example16.cpp" parse="text"
223            xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>When
224      the <code>safe&lt;long&gt;</code> is implicitly converted to an
225      <code>int</code> when calling <code>f</code>, the value is checked to be
226      sure that it is within the legal range of an int and will invoke an
227      exception if it cannot. We can easily verify this by altering the
228      exception handling policy in the above example to
229      <code>loose_trap_policy</code>. This will invoke a compile time error on
230      any conversion might invoke a runtime exception.</para>
231
232      <para><programlisting><xi:include href="../../example/example17.cpp"
233            parse="text" xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting></para>
234
235      <para>But this raises it's own questions. We can see that in this
236      example, the program can never fail:</para>
237
238      <itemizedlist>
239        <listitem>
240          <para>The value 97 is assigned to y</para>
241        </listitem>
242
243        <listitem>
244          <para>y is converted to an int</para>
245        </listitem>
246
247        <listitem>
248          <para>and used as an argument to f</para>
249        </listitem>
250      </itemizedlist>
251
252      <para>The conversion can never fail because the value of 97 can always
253      fit into an int. But the library code can't detect this and emits the
254      checking code even though it's not necessary.</para>
255
256      <para>This can be addressed by using a <link
257      linkend="safe_numerics.safe_literal"><code>safe_literal</code></link>. A
258      safe literal can contain one and only one value. All the functions in
259      this library are marked <code>constexpr</code>. So it can be determined
260      at compile time that conversion to an <code>int</code> can never fail
261      and no runtime checking code need be emitted. Making this small change
262      will permit the above example to run with zero runtime overhead while
263      guaranteeing that no error can ever occur.</para>
264
265      <programlisting><xi:include href="../../example/example18.cpp"
266          parse="text" xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>
267
268      <para>With this trivial example, such efforts would hardly be deemed
269      necessary. But in a more complex case, perhaps including compile time
270      arithmetic expressions, it could be much more difficult to verify that
271      the constant is valid and/or no checking code is needed. And there is
272      also possibility that over the life time of the application, the compile
273      time constants might change, thus rendering any ad hoc analyse obsolete.
274      Using <link
275      linkend="safe_numerics.safe_literal"><code>safe_literal</code></link>
276      will future-proof your code against well-meaning, but code-breaking
277      updates.</para>
278    </section>
279
280    <section>
281      <title>Adjust type promotion rules.</title>
282
283      <para>Another way to avoid arithmetic errors like overflow is to promote
284      types to larger sizes before doing the arithmetic.</para>
285
286      <para>Stepping back, we can see that many of the cases of invalid
287      arithmetic wouldn't exist if the result types were larger. So we can
288      avoid these problems by replacing the C++ type promotion rules for
289      expressions with our own rules. This can be done by specifying a
290      promotion policy <code><code>automatic</code></code>. The policy stores
291      the result of an expression in the smallest size type that can
292      accommodate the largest value that an expression can yield. No checking
293      for exceptions is necessary. The following example illustrates
294      this.</para>
295
296      <para><programlisting>#include &lt;boost/safe_numerics/safe_integer.hpp&gt;
297#include &lt;iostream&gt;
298
299int main(int, char[]){
300    using safe_int = safe&lt;
301        int, boost::numeric::automatic,
302        boost::numeric::default_exception_policy
303    &gt;;
304    safe_int i;
305    std::cin &gt;&gt; i; // might throw exception
306    auto j = i * i; // won't ever trap - result type can hold the maximum value of i * i
307    static_assert(boost::numeric::is_safe&lt;decltype(j)&gt;::value); // result is another safe type
308    static_assert(
309        std::numeric_limits&lt;decltype(i * i)&gt;::max() &gt;=
310        std::numeric_limits&lt;safe_int&gt;::max() * std::numeric_limits&lt;safe_int&gt;::max()
311    ); // always true
312
313    return 0;
314}</programlisting></para>
315    </section>
316  </section>
317
318  <section>
319    <title>Header</title>
320
321    <para><filename><ulink
322    url="../../include/boost/safe_numerics/safe_integer.hpp">#include
323    &lt;boost/numeric/safe_numerics/safe_integer.hpp&gt;</ulink></filename></para>
324  </section>
325</section>
326