faq.xml 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
  3. "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
  4. <section id="safe_numerics.rationale">
  5. <title>Rationale and FAQ</title>
  6. <qandaset defaultlabel="number">
  7. <qandaentry>
  8. <question>
  9. <para>Is this really necessary? If I'm writing the program with the
  10. requisite care and competence, problems noted in the introduction will
  11. never arise. Should they arise, they should be fixed "at the source"
  12. and not with a "band aid" to cover up bad practice.</para>
  13. </question>
  14. <answer>
  15. <para>This surprised me when it was first raised. But some of the
  16. feedback I've received makes me think that it's a widely held view.
  17. The best answer is to consider the examples in the <link
  18. linkend="safe_numerics.tutorial">Tutorials and Motivating
  19. Examples</link> section of the library documentation. I believe they
  20. convincingly demonstrate that any program which does not use this
  21. library must be assumed to contain arithmetic errors.</para>
  22. </answer>
  23. </qandaentry>
  24. <qandaentry>
  25. <question>
  26. <para>Can safe types be used as drop-in replacements for built-in
  27. types?</para>
  28. </question>
  29. <answer>
  30. <para>Almost. Replacing all built-in types with their safe
  31. counterparts should result in a program that will compile and run as
  32. expected. Occasionally compile time errors will occur and adjustments
  33. to the source code will be required. Typically these will result in
  34. code which is more correct.</para>
  35. </answer>
  36. </qandaentry>
  37. <qandaentry>
  38. <question>
  39. <para>Why are there special types for literal such as
  40. <code>safe_signed_literal&lt;42&gt;</code>? Why not just use
  41. std::integral_const&lt;int, 42&gt;?</para>
  42. </question>
  43. <answer>
  44. <para>By defining our own "special" type we can simplify the
  45. interface. Using <code>std::integral_const</code> requires one to
  46. specify both the type <emphasis>and</emphasis> the value. Using
  47. <code>safe_signed_literal&lt;42&gt;</code> doesn't require a parameter
  48. for the type. So the library can select the best type to hold the
  49. specified value. It also means that one won't have the opportunity to
  50. specify a type-value pair which are inconsistent.</para>
  51. </answer>
  52. </qandaentry>
  53. <qandaentry>
  54. <question>
  55. <para>Why is safe...literal needed at all? What's the matter with
  56. <code>const safe&lt;int&gt;(42)</code>?</para>
  57. </question>
  58. <answer>
  59. <para><code>const safe&lt;int&gt;(42)</code> looks like it might be
  60. what we want: An immutable value which invokes the "safe" operators
  61. when used in an expression. But there is one problem. The
  62. <code>std::numeric_limits&lt;safe&lt;int&gt;&gt;</code> is a range
  63. from INTMIN to INTMAX even though the value is fixed to 42 at compile
  64. time. It is this range which is used at compile time to calculate the
  65. range of the result of the operation.</para>
  66. <para>So when an operation is performed, the range of the result is
  67. calculated from [INTMIN, INTMAX] rather than from [42,42].</para>
  68. </answer>
  69. </qandaentry>
  70. <qandaentry>
  71. <question>
  72. <para>Are safe type operations <code>constexpr</code>? That is, can
  73. they be invoked at compile time?</para>
  74. </question>
  75. <answer>
  76. <para>Yes. safe type construction and calculations are all
  77. <code>constexpr</code>. Note that to get maximum benefit, you'll have
  78. to use <code>safe...literal</code> to specify the primitive values at
  79. compile time.</para>
  80. </answer>
  81. </qandaentry>
  82. <qandaentry>
  83. <question>
  84. <para>Why define <link
  85. linkend="safe_numerics.safe_literal"><code>safe_literal</code></link>?
  86. Isn't it effectively the same as
  87. <code>std::integral_constant</code>?</para>
  88. </question>
  89. <answer>
  90. <para>Almost, but there are still good reasons to create a different
  91. type.<itemizedlist>
  92. <listitem>
  93. <para><code>std::integral_constant&lt;int, 42&gt;</code>
  94. requires specification of type as well as value so it's less
  95. convenient than safe_signed_literal which maps to the smallest
  96. type required to hold the value.</para>
  97. </listitem>
  98. <listitem>
  99. <para><code>std::numeric_limits&lt;std::integral_constant&lt;int,
  100. 42&gt;&gt;::is_integer</code> returns <code>false</code>. This
  101. would complicate implementation of the library</para>
  102. </listitem>
  103. <listitem>
  104. <para>type trait <code>is_safe&lt;std::integral_constant&lt;int,
  105. 42&gt;&gt;</code> would have to be defined to return
  106. <code>true</code>.</para>
  107. </listitem>
  108. <listitem>
  109. <para>But globally altering the traits of
  110. <code>std::integral_constant</code> might have unintended
  111. side-effects related to other code. These might well be
  112. surprises which are create errors which are hard to find and
  113. hard to work around.</para>
  114. </listitem>
  115. </itemizedlist></para>
  116. </answer>
  117. </qandaentry>
  118. <qandaentry>
  119. <question>
  120. <para>Why is Boost.Convert not used?</para>
  121. </question>
  122. <answer>
  123. <para>I couldn't figure out how to use it from the
  124. documentation.</para>
  125. </answer>
  126. </qandaentry>
  127. <qandaentry>
  128. <question>
  129. <para>Why is the library named "safe ..." rather than something like
  130. "checked ..." ?</para>
  131. </question>
  132. <answer>
  133. <para>I used "safe" in large part because this is what has been used
  134. by other similar libraries. Maybe a better word might have been
  135. "correct" but that would raise similar concerns. I'm not inclined to
  136. change this. I've tried to make it clear in the documentation what the
  137. problem that the library addressed is.</para>
  138. </answer>
  139. </qandaentry>
  140. <qandaentry>
  141. <question>
  142. <para>Given that the library is called "numerics" why is floating
  143. point arithmetic not addressed?</para>
  144. </question>
  145. <answer>
  146. <para>Actually, I believe that this can/should be applied to any type
  147. T which satisfies the type requirement <code>Numeric</code> type as
  148. defined in the documentation. So there should be specializations
  149. <code>safe&lt;float&gt;</code> and related types as well as new types
  150. like <code>safe&lt;fixed_decimal&gt;</code> etc. But the current
  151. version of the library only addresses integer types. Hopefully the
  152. library will evolve to match the promise implied by its name.</para>
  153. </answer>
  154. </qandaentry>
  155. <qandaentry>
  156. <question>
  157. <para>Isn't putting a defensive check just before any potential
  158. undefined behavior often considered a bad practice?</para>
  159. </question>
  160. <answer>
  161. <para>By whom? Is leaving code which can produce incorrect results
  162. better? Note that the documentation contains references to various
  163. sources which recommend exactly this approach to mitigate the problems
  164. created by this C/C++ behavior. See
  165. <citation>Seacord</citation></para>
  166. </answer>
  167. </qandaentry>
  168. <qandaentry>
  169. <question>
  170. <para>It looks like the implementation presumes two's complement
  171. arithmetic at the hardware level. So this library is not portable -
  172. correct? What about other hardware architectures?</para>
  173. </question>
  174. <answer>
  175. <para>As far as is known as of this writing, the library does not
  176. presume that the underlying hardware is two's complement. However,
  177. this has yet to be verified in any rigorous way.</para>
  178. </answer>
  179. </qandaentry>
  180. <qandaentry>
  181. <question>
  182. <para>According to C/C++ standards, <code>unsigned integers</code>
  183. cannot overflow - they are modular integers which "wrap around". Yet
  184. the safe numerics library detects and traps this behavior as errors.
  185. Why is that?</para>
  186. </question>
  187. <answer>
  188. <para>The guiding purpose of the library is to trap incorrect
  189. arithmetic behavior - not just undefined behavior. Although a savvy
  190. user may understand and keep present in his mind that an unsigned
  191. integer is really a modular type, the plain reading of an arithmetic
  192. expression conveys the idea that all operands are common integers.
  193. Also in many cases, <code>unsigned integers</code> are used in cases
  194. where modular arithmetic is not intended, such as array indices.
  195. Finally, the modulus for such an integer would vary depending upon the
  196. machine architecture. For these reasons, in the context of this
  197. library, an <code>unsigned integer</code> is considered to be a
  198. representation of a subset of integers. Note that this decision is
  199. consistent with <citation>INT30-C</citation>, “Ensure that unsigned
  200. integer operations do not wrap” in the CERT C Secure Coding Standard
  201. <citation>Seacord</citation>.</para>
  202. </answer>
  203. </qandaentry>
  204. <qandaentry>
  205. <question>
  206. <para>Why does the library require C++14?</para>
  207. </question>
  208. <answer>
  209. <para>The original version of the library used C++11. Feedback from
  210. CPPCon, <ulink url="http://www.blincubator.com">Boost Library
  211. Incubator</ulink> and Boost developer's mailing list convinced me that
  212. I had to address the issue of run-time penalty much more seriously. I
  213. resolved to eliminate or minimize it. This led to more elaborate
  214. meta-programming. But this wasn't enough. It became apparent that the
  215. only way to really minimize run-time penalty was to implement
  216. compile-time integer range arithmetic - a pretty elaborate sub
  217. library. By doing range arithmetic at compile-time, I could skip
  218. runtime checking on many/most integer operations. While C++11
  219. <code>constexpr</code> wasn't quite powerful enough to do the job,
  220. C++14 <code>constexpr</code> is. The library currently relies very
  221. heavily on C++14 <code>constexpr</code>. I think that those who delve
  222. into the library will be very surprised at the extent that minor
  223. changes in user code can produce guaranteed correct integer code with
  224. zero run-time penalty.</para>
  225. </answer>
  226. </qandaentry>
  227. <qandaentry>
  228. <question>
  229. <para>This is a C++ library - yet you refer to C/C++. Which is
  230. it?</para>
  231. </question>
  232. <answer>
  233. <para>C++ has evolved way beyond the original C language. But C++ is
  234. still (mostly) compatible with C. So most C programs can be compiled
  235. with a C++ compiler. The problems of incorrect arithmetic afflict both
  236. C and C++. Suppose we have a legacy C program designed for some
  237. embedded system.<itemizedlist>
  238. <listitem>
  239. <para>Replace all <code>int</code> declarations with
  240. <code>int16_t</code> and all <code>long</code> declarations with
  241. <code>int32_t</code>.</para>
  242. </listitem>
  243. <listitem>
  244. <para>Create a file containing something like the following and
  245. include it at the beginning of every source file.</para>
  246. <programlisting>#ifdef TEST
  247. // using C++ on test platform
  248. #include &lt;cstdint&gt;
  249. #include &lt;boost/numeric/safe_numerics/safe_integer.hpp&gt;
  250. #include &lt;cpp.hpp&gt;
  251. using pic16_promotion = boost::numeric::cpp&lt;
  252. 8, // char
  253. 8, // short
  254. 8, // int
  255. 16, // long
  256. 32 // long long
  257. &gt;;
  258. // define safe types used in the desktop version of the program.
  259. template &lt;typename T&gt; // T is char, int, etc data type
  260. using safe_t = boost::numeric::safe&lt;
  261. T,
  262. pic16_promotion,
  263. boost::numeric::default_exception_policy // use for compiling and running tests
  264. &gt;;
  265. typedef safe_t&lt;std::int_least16_t&gt; int16_t;
  266. typedef safe_t&lt;std::int_least32_t&gt; int32_t;
  267. #else
  268. /* using C on embedded platform */
  269. typedef int int_least16_t;
  270. typedef long int_least16_t;
  271. #endif
  272. </programlisting>
  273. </listitem>
  274. <listitem>
  275. <para>Compile tests on the desktop with a C++14 compiler and
  276. with the macro TEST defined.</para>
  277. </listitem>
  278. <listitem>
  279. <para>Run the tests and change the code to address any thrown
  280. exceptions.</para>
  281. </listitem>
  282. <listitem>
  283. <para>Compile for the target C platform with the macro TEST
  284. undefined.</para>
  285. </listitem>
  286. </itemizedlist></para>
  287. <para>This example illustrates how this library, implemented with
  288. C++14 can be useful in the development of correct code for programs
  289. written in C.</para>
  290. </answer>
  291. </qandaentry>
  292. <qandaentry>
  293. <question>
  294. <para>Some compilers (including gcc and clang) include builtin
  295. functions for checked addition, multiplication, etc. Does this library
  296. use these intrinsics?</para>
  297. </question>
  298. <answer>
  299. <para>No. I attempted to use these but they are currently not
  300. <code>constexpr</code>. So I couldn't use these without breaking
  301. <code>constexpr</code> compatibility for the safe numerics
  302. primitives.</para>
  303. </answer>
  304. </qandaentry>
  305. <qandaentry>
  306. <question>
  307. <para>Some compilers (including gcc and clang) included a builtin
  308. function for detecting constants. This seemed attractive to eliminate
  309. the requirement for the safe_literal type. Alas, these builtin
  310. functions are defined as macros. Constants passed through functions
  311. down into the safe numerics library cannot be detected as constants.
  312. So the opportunity to make the library even more efficient by moving
  313. more operations to compile time doesn't exist - contrary to my hopes
  314. and expections.</para>
  315. </question>
  316. </qandaentry>
  317. </qandaset>
  318. </section>