mirror of
https://github.com/boostorg/safe_numerics.git
synced 2026-02-22 15:42:30 +00:00
improved TOC and chunking. This is complicated by the fact we that we desire different depths. put copies of boost logo in subdirectories
269 lines
9.0 KiB
XML
269 lines
9.0 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.1//EN"
|
|
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
|
|
<section id="safe_numerics.safe">
|
|
<title>safe<T, PP = boost::numeric::native, EP =
|
|
boost::numeric::throw_exception></title>
|
|
|
|
<?dbhtml stop-chunking?>
|
|
|
|
<section>
|
|
<title>Description</title>
|
|
|
|
<para>A <code>safe<T, PP , EP></code> can be used anywhere a type T
|
|
can be used. Any expression which uses this type is guaranteed to return
|
|
an arithmetically correct value or trap in some way.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Notation</title>
|
|
|
|
<informaltable>
|
|
<tgroup cols="2">
|
|
<colspec align="left" colwidth="1*"/>
|
|
|
|
<colspec align="left" colwidth="10*"/>
|
|
|
|
<thead>
|
|
<row>
|
|
<entry align="left">Symbol</entry>
|
|
|
|
<entry align="left">Description</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry><code>T</code></entry>
|
|
|
|
<entry>Underlying type from which a safe type is being
|
|
derived</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Associated Types</title>
|
|
|
|
<informaltable>
|
|
<tgroup cols="2">
|
|
<colspec align="left" colwidth="1*"/>
|
|
|
|
<colspec align="left" colwidth="10*"/>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry><code>PP</code></entry>
|
|
|
|
<entry>A type which specifies the result type of an expression
|
|
using safe types.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><code>EP</code></entry>
|
|
|
|
<entry>A type containing members which are called when a correct
|
|
result cannot be returned</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Template Parameters</title>
|
|
|
|
<informaltable>
|
|
<tgroup cols="3">
|
|
<colspec colwidth="1*"/>
|
|
|
|
<colspec align="left" colwidth="3*"/>
|
|
|
|
<colspec align="left" colwidth="7*"/>
|
|
|
|
<thead>
|
|
<row>
|
|
<entry align="left">Parameter</entry>
|
|
|
|
<entry align="left">Type Requirements</entry>
|
|
|
|
<entry>Description</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry><code>T</code></entry>
|
|
|
|
<entry><ulink
|
|
url="http://en.cppreference.com/w/cpp/types/is_integral">Integer<T></ulink></entry>
|
|
|
|
<entry><para>The underlying type. Currently only integer types
|
|
supported</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><code>PP</code></entry>
|
|
|
|
<entry><link linkend="safe_numerics.numeric"><link
|
|
linkend="safe_numerics.promotion_policy">PromotionPolicy<PP></link></link></entry>
|
|
|
|
<entry><para>Default value is <link
|
|
linkend="safe_numerics.promotion_policy.models.native">boost::numeric::native</link></para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><code>EP</code></entry>
|
|
|
|
<entry><link linkend="safe_numerics.numeric"><link
|
|
linkend="safe_numerics.exception_policy">Exception
|
|
Policy<EP></link></link></entry>
|
|
|
|
<entry><para>Default value is <link
|
|
linkend="safe_numerics.exception_policy.models.thow_exception">boost::numeric::throw_exception</link></para></entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
|
|
<para>See examples below.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Model of</title>
|
|
|
|
<para><link linkend="safe_numerics.numeric">Integer</link></para>
|
|
|
|
<para><link
|
|
linkend="safe_numerics.safe_numeric_concept">SafeNumeric</link></para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Valid Expressions</title>
|
|
|
|
<para>Implements all expressions and only those expressions defined by the
|
|
<link linkend="safe_numerics.safe_numeric_concept">SafeNumeric</link> type
|
|
requirements. This, the result type of such an expression will be another
|
|
safe type. The actual type of the result of such an expression will depend
|
|
upon the specific promotion policy template parameter.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Header</title>
|
|
|
|
<para><filename><ulink url="../../include/safe_integer.hpp">#include
|
|
<boost/safe_numerics/safe_integer.hpp></ulink></filename></para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Examples of use</title>
|
|
|
|
<para>The most common usage would be safe<T> which uses the default
|
|
promotion and exception policies. This type is meant to be a "drop-in"
|
|
replacement of the intrinsic integer types. That is, expressions involving
|
|
these types will be evaluated into result types which reflect the standard
|
|
rules for evaluation of C++ expressions. Should it occur that such
|
|
evaluation cannot return a correct result, an exception will be
|
|
thrown.</para>
|
|
|
|
<para>There are two aspects of the operation of this type which can be
|
|
customized with a policy. The first is the result type of an arithmetic
|
|
operation. C++ defines the rules which define this result type in terms of
|
|
the constituent types of the operation. Here we refer to these rules a
|
|
"type promotion" rules. These rules will sometimes result in a type which
|
|
cannot hold the actual arithmetic result of the operation. This is the
|
|
main motivation for making this library in the first place. One way to
|
|
deal with this problem is to substitute our own type promotion rules for
|
|
the C++ ones.</para>
|
|
|
|
<section>
|
|
<title>Drop-in replacement for standard integer type.</title>
|
|
|
|
<para>The following program will throw an exception and emit a error
|
|
message at runtime if any of several events result in an incorrect
|
|
arithmetic type. Behavior of this program could vary according to the
|
|
machine architecture in question.</para>
|
|
|
|
<para><programlisting>#include <exception>
|
|
#include <iostream>
|
|
#include <boost/numeric/safe.hpp>
|
|
|
|
void f(){
|
|
using namespace boost::numeric;
|
|
safe<int> j;
|
|
try {
|
|
safe<int> i;
|
|
std::cin >> i; // could overflow !
|
|
j = i * i; // could overflow
|
|
}
|
|
catch(std::exception & e){
|
|
std::cout << e.what() << std::endl;
|
|
}
|
|
std::cout << j;
|
|
}</programlisting></para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Guarantee correct behavior at compile time.</title>
|
|
|
|
<para>In some instance catching an error at run time is not sufficient.
|
|
We want to be sure that the program can never fail. To achieve this, use
|
|
the trap_exception exception policy rather than the default throw
|
|
exception policy.</para>
|
|
|
|
<para>The following program will emit a compile error at any statement
|
|
which might possibly result in incorrect behavior.</para>
|
|
|
|
<para>This is because there is no way to guarantee that the expression i
|
|
* i will return an arithmetically correct result. Since we know that the
|
|
program cannot compile if there is any possibility of arithmetic error,
|
|
we can dispense with the exception handling used above.</para>
|
|
|
|
<para><programlisting>#include <iostream>
|
|
#include <boost/numeric/safe.hpp>
|
|
|
|
void f(){
|
|
using safe_int = safe<int, boost::numeric::native, boost::numeric::trap_exception>;
|
|
safe_int i;
|
|
std::cin >> i; // could throw exception here !!!
|
|
safe_int j;
|
|
j = i * i; // could throw exception here !!!
|
|
}</programlisting></para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Adjust type promotion rules.</title>
|
|
|
|
<para>Another way to avoid arithmetic errors like overflow is to promote
|
|
types to larger sizes before doing the arithmetic. This can be justified
|
|
by the observe</para>
|
|
|
|
<para>Stepping back, we can see that many of the cases of invalid
|
|
arithmetic are wouldn't exist if results types were larger. So we can
|
|
avoid these problems by replacing the C++ type promotion rules for
|
|
expressions with our own rules. This can be done by specifying a
|
|
non-default type promotion policy automatic. The policy stores the
|
|
result of an expression in the smallest size that can accommodate the
|
|
largest value that an expression can yield. All the work is done at
|
|
compile time - checking for exceptions necessary (input is of course an
|
|
exception). The following example illustrates this.</para>
|
|
|
|
<para><programlisting>#include <boost/numeric/safe.hpp>
|
|
#include <iostream>
|
|
void f(){
|
|
using safe_int = safe<int, boost::numeric::automatic, boost::numeric::throw_exception>;
|
|
safe_int i;
|
|
std::cin >> i; // might throw exception
|
|
auto j = i * i; // won't ever trap - result type can hold the maximum value of i * i
|
|
static_assert(boost::numeric::is_safe<decltype(j)>::value); // result is another safe type
|
|
static_assert(
|
|
std::numeric_limits<decltype(i * i)>::max() >=
|
|
std::numeric_limits<safe_int>::max() * std::numeric_limits<safe_int>::max()
|
|
); // always true
|
|
}</programlisting></para>
|
|
</section>
|
|
</section>
|
|
</section>
|