safe.xml 12 KB

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