Safe Numerics |
Create a valid exception policy from 4 function objects. This specifies the actions to be taken for different types of invalid results.
Parameter | Type Requirements | Invoked when: |
---|---|---|
AE |
Function object callable with the expression AE(e, message) | The operation cannot produce valid arithmetic result such as overflows, divide by zero, etc. |
UB |
Function object callable with the expression UB(e, message) | The result is undefined by the C++ standard |
IDB |
Function object callable with the expression IDB(e, | The result depends upon implementation defined behavior according to the C++ standard |
UV |
Function object callable with the expression UV(e, message) | A variable is not initialized |
This class implements all the valid operations from the type requirements ExceptionPolicy. Aside from these, there are no other operations implemented.
In order to create an exception policy, one needs some function objects. The library includes some appropriate examples of these:
Name | Description |
---|---|
ignore_exception |
Ignore any runtime exception and just return - thus propagating the error. This is what would happen with unsafe data types |
throw_exception |
throw an exception of type std::system_error |
trap_exception |
Invoke a function which is undefined. Compilers will include this function if and only if there is a possibility of a runtime error. Conversely, This will create a compile time error if there is any possibility that the operation will fail at runtime. Use the action to guarantee that your application will never produce an invalid result. Any operation invoke |
But of course one is free to provide his own. Here is an example of a function object which would could be used exception conditions.
// log an exception condition but continue processing as though nothing has happened // this would emulate the behavior of an unsafe type. struct log_runtime_exception { log_runtime_exception(const safe_numerics_error & e, const char * message){ std::cout << "Caught system_error with code " << e.code() << " meaning " << e.what() << '\n'; } };
The above function object can be composed into an exception policy by this class. The library provides common policies all ready to use. In the table below, the word "loose" is used to indicate that implementation defined and undefined behavior is not considered an exceptional condition, while "strict" means the opposite. The word "exception" means that a runtime exception will be thrown. The word "trap" means that the mere possibility of an error condition will result in a compile time error.
Name | Description |
---|---|
loose_exception_policy | Throws runtime exception on any arithmetic error. Undefined and implementation defined behavior is permitted as long as it does not produce an arithmetic error. |
loose_trap_policy
|
Invoke a compile time error in any case where it's possible to result in an arithmetic error. |
strict_exception_policy
|
Throws runtime exception on any arithmetic error. Any undefined or implementation defined behavior also results in throwing an exception. |
strict_trap_policy
|
Invoke a compile time error in any case where it's possible to result in an arithmetic error, undefined behavior or implementation defined behavior |
default_exception_policy
|
an alias for strict_exception_policy
|
If none of the above suit your needs, you're free to create your own. Here is one where use the logging function object defined above as a component in a loose exception policy which logs any arithmetic errors and ignores any other types of errors.
// logging policy // log arithmetic errors but ignore them and continue to execute // implementation defined and undefined behavior is just executed // without logging. using logging_exception_policy = exception_policy< log_runtime_exception, // arithmetic error ignore_exception, // implementation defined behavior ignore_exception, // undefined behavior ignore_exception // uninitialized value >;