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 X
throw
exception X
throw
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) |