![]() |
Arene Base
Fundamental Utilities For Safety Critical C++
|
arene-base uses 3 different mechanisms for reporting errors, depending on the form of the error:
arene-base.arene-base. It is only used for functions explicitly documented to throw, usually for consistency between arene-base APIs and similar standard library APIs.arene-base, or a bug in the implementation of arene-base itself.Many arene-base facilities have clearly-documented preconditions that must be satisfied in order to use those facilities. They also may have internal invariants that are maintained during correct operation. Failure to meet any preconditions is considered a programming logic error in the calling code, and the program must therefore be in an unanticipated state. Similarly, if any internal invariant is broken, then there is a logic error in the calling code, or in the arene-base implementation, and the program must again be in an unanticipated state.
Consequently, if arene-base code detects violation of any preconditions or internal invariants, the process is terminated. The program must be in an unanticipated state, so the only safe action is to terminate, as the only certain way to return the system to a defined state. See contracts: Precondition and Invariant Checking for details, including how to use this mechanism in code outside arene-base.
arene-base often exposes facilities that would enable the calling code to check prior to using the facility. For example, when accessing an element of an arene::base::inline_vector using an index, the index must be less than the size of the container; this can be checked beforehand by comparing the index to the result of the arene::base::inline_vector::size() member function for that vector.In general, arene-base does not throw exceptions as an error handling strategy. However, it is used for consistency between arene-base APIs and similar standard library APIs, and in a small number of other cases. For example, arene::base::inline_vector::at() will throw an exception (rather than encounter a precondition violation) if the index is out of range.
All operations that throw exceptions are clearly documented as doing so.
noexcept, if they use standard library facilities that may throw, or if they use user-provided facilities that may throw. Generic facilities will still pass through any exception thrown by the operations performed on their input types if those types throw.Where a function may fail even if the inputs satisfy the preconditions, the most common error handling strategy in arene-base is to convey the error via the return value of the function.
The form of the error indication depends on two aspects:
If the reason for the failure does not need enumerating, a function that can fail will return a bool, with true for success and false for failure.
Where the reason does need enumerating, then an error code enum will be used to specify the reasons for the failure. The return value for the function is then arene::base::result<void,the_error_code_enum>, holding an empty value on success, or the error code on failure.
For a function that returns a value of type Foo on success, if the reason for the failure does not need enumerating, that function will return an arene::base::optional<Foo> that holds a value on success, or arene::base::nullopt on failure.
Where the reason does need enumerating, then an error code enum will be used to specify the reasons for the failure. The return value for the function is then arene::base::result<Foo,the_error_code_enum>, holding the successful value on success, or the error code on failure.
There are no direct return values from a constructor, so the only mechanisms available to report errors are exceptions and process termination. For some arene-base classes where constructors may fail, if the class is Foo, then a Foo::try_construct static member function is provided as a factory function, in addition to the constructors. Foo::try_construct returns either an arene::base::optional<Foo> or an arene::base::result<Foo,some_error_code> as described above. The result contains the correctly-constructed Foo instance on success.