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<T, PP, EP></title> 6 7 <?dbhtml stop-chunking?> 8 9 <section> 10 <title>Description</title> 11 12 <para>A <code>safe<T, PP , EP></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<T></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<PP></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<EP></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><T> 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<T, PP, 159 EP>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<T> 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 <exception> 203#include <iostream> 204#include <safe_integer.hpp> 205 206void f(){ 207 using namespace boost::numeric; 208 safe<int> j; 209 try { 210 safe<int> i; 211 std::cin >> i; // could overflow ! 212 j = i * i; // could overflow 213 } 214 catch(std::exception & e){ 215 std::cout << e.what() << std::endl; 216 } 217 std::cout << 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<long></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 <boost/safe_numerics/safe_integer.hpp> 297#include <iostream> 298 299int main(int, char[]){ 300 using safe_int = safe< 301 int, boost::numeric::automatic, 302 boost::numeric::default_exception_policy 303 >; 304 safe_int i; 305 std::cin >> 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<decltype(j)>::value); // result is another safe type 308 static_assert( 309 std::numeric_limits<decltype(i * i)>::max() >= 310 std::numeric_limits<safe_int>::max() * std::numeric_limits<safe_int>::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 <boost/numeric/safe_numerics/safe_integer.hpp></ulink></filename></para> 324 </section> 325</section> 326