|
BDE 4.14.0 Production release
|
Macros | |
| #define | BSLS_TRY if (1) |
| #define | BSLS_CATCH(X) else if (0) |
| #define | BSLS_THROW(X) |
| #define | BSLS_RETHROW |
| #define | BSLS_EXCEPTION_SPEC(SPEC) |
| #define | BSLS_NOTHROW_SPEC |
| #define | BSLS_EXCEPTION_VIRTUAL_NOTHROW |
Provide simplified exception constructs for non-exception builds.
try-blockcatch-block for exception Xthrow exception Xthrow the current exceptionSPEC to function exception specificationexception method except. spec.exception::what() except. spec.Code that uses try, throw and catch constructs will often fail to compile when exceptions are disabled using a compiler switch, even if the throw statement is unlikely to be executed at run-time or if the catch clause can safely ignore an exception that will never occur. This component provides macros to replace try, throw and catch. These macros expand to normal exception constructs when exceptions are enabled and reasonable alternatives (usually no-ops) when exceptions are disabled.
This section illustrates intended use of this component.
Suppose we wanted to define an implementation of a standard-defined vector template. Unfortunately, the C++ standard requires that vector provide an at method that throws an out_of_range exception if the supplied index is not in the valid range of elements in the vector. In this example we show using BSLS_THROW so that such an implementation will compile in both exception enabled and non-exception enabled builds. Note that apart from memory allocation, and where required by the C++ standard, types defined in the BDE libraries do not throw exceptions, and are typically "exception-neutral" (see bsldoc_glossary ), meaning they behave reasonably in the presence of injected exceptions, but do not themselves throw any exceptions.
First we open a namespace myStd and define an out_of_range exception that the at method will throw (note that in practice, out_of_range would inherit from logic_error )':
Next, we declare the vector template and its template parameters (note that the majority of the implementation is elided, for clarity):
Then, we define the at method, which is required to throw an out_of_range exception.
Now, we use BSLS_THROW to throw an out_of_range exception:
Finally, we complete the (mostly elided) vector implementation:
The following example demonstrates the macros defined in the bsls_exceptionutil component to both throw and catch exceptions in a way that will allow the code to compile in non-exception enabled builds.
First, we define a couple of example exception classes (note that we cannot use bsl::exception in this example, as this component is defined below bsl_exception.h):
Then, we define a function that never throws an exception, and use the BSLS_NOTHROW_SPEC to ensure the no-throw exception specification will be present in exception enabled builds, and elided in non-exception enabled builds:
Next, we define a function that might throw my_ExClass1 or my_ExClass2, and docuemnt which exception types might be thrown. Note that dynamic exception specifications are deprecated in C++11 and removed from the language in C++17, so should not be used as a substitute for documentation in earlier language dialects:
Then, we start the definition of a testMain function:
Next, we use the BDE_BUILD_TARGET_EXC exception build flag to determine, at compile time, whether to initialize ITERATIONS to 3 (for exception enabled builds) or 1 (for non-exception enabled builds). The different values of the ITERATOR ensure the subsequent for-loop calls mightThrowFunc in a way that generates exceptions for only exception enabled builds:
Then, we use a pair of nested try blocks constructed using BSLS_TRY, so that the code will compile whether or not exceptions are enabled (note that the curly brace placement is identical to normal try and catch constructs):
Notice that this example is careful to call mightThrowFunc in such a way that it will not throw in non-exception builds. Although the use of BSLS_TRY, BSLS_THROW, and BSLS_CATCH ensures the code compiles in both exception, and non-exception enabled builds, attempting to BSLS_THROW an exception in a non-exception enabled build will invoke the assert handler and will typically abort the task.
Next, we use BSLS_CATCH to define blocks for handling exceptions that may have been thrown from the preceding BSLS_TRY:
Here, within the catch-all handler, we use the BSLS_RETHROW macro to re-throw the exception to the outer try block:
| #define BSLS_CATCH | ( | X | ) | else if (0) |
| #define BSLS_EXCEPTION_SPEC | ( | SPEC | ) |
| #define BSLS_EXCEPTION_VIRTUAL_NOTHROW |
The exception specification that overrides of the exception::what() virtual method should use. It is a separate macro from BSLS_NOTHROW_SPEC because the GNU library unconditionally declares the function throw(), regardless if exceptions are enabled or not - and overrides must do the same.
| #define BSLS_NOTHROW_SPEC |
| #define BSLS_RETHROW |
| #define BSLS_THROW | ( | X | ) |
| #define BSLS_TRY if (1) |