BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_exceptionutil.h
Go to the documentation of this file.
1/// @file bsls_exceptionutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_exceptionutil.h -*-C++-*-
8#ifndef INCLUDED_BSLS_EXCEPTIONUTIL
9#define INCLUDED_BSLS_EXCEPTIONUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_exceptionutil bsls_exceptionutil
15/// @brief Provide simplified exception constructs for non-exception builds.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_exceptionutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_exceptionutil-purpose"> Purpose</a>
25/// * <a href="#bsls_exceptionutil-classes"> Classes </a>
26/// * <a href="#bsls_exceptionutil-macros"> Macros </a>
27/// * <a href="#bsls_exceptionutil-description"> Description </a>
28/// * <a href="#bsls_exceptionutil-usage"> Usage </a>
29/// * <a href="#bsls_exceptionutil-example-1-using-ref-bsls_exceptionutil-to-implement-vector"> Example 1: Using @ref bsls_exceptionutil to Implement vector </a>
30/// * <a href="#bsls_exceptionutil-example-2-using-ref-bsls_exceptionutil-to-throw-and-catch-exceptions"> Example 2: Using @ref bsls_exceptionutil to Throw and Catch Exceptions </a>
31///
32/// # Purpose {#bsls_exceptionutil-purpose}
33/// Provide simplified exception constructs for non-exception builds.
34///
35/// # Classes {#bsls_exceptionutil-classes}
36///
37///
38/// # Macros {#bsls_exceptionutil-macros}
39///
40/// - BSLS_TRY: begin a `try`-block
41/// - BSLS_CATCH(X): begin a `catch`-block for exception `X`
42/// - BSLS_THROW(X): `throw` exception `X`
43/// - BSLS_RETHROW: re-`throw` the current exception
44/// - BSLS_EXCEPTION_SPEC(SPEC): add `SPEC` to function exception specification
45/// - BSLS_NOTHROW_SPEC: declare that a function throws no exceptions
46/// - BSLS_EXCEPTION_VIRTUAL_NOTHROW: virtual `exception` method except. spec.
47/// - BSLS_EXCEPTION_WHAT_NOTHROW: `exception::what()` except. spec.
48///
49/// @see bsls_compilerfeatures, bsls_cpp11
50///
51/// # Description {#bsls_exceptionutil-description}
52/// Code that uses `try`, `throw` and `catch` constructs will
53/// often fail to compile when exceptions are disabled using a compiler switch,
54/// even if the `throw` statement is unlikely to be executed at run-time or if
55/// the `catch` clause can safely ignore an exception that will never occur.
56/// This component provides macros to replace `try`, `throw` and `catch`.
57/// These macros expand to normal exception constructs when exceptions are
58/// enabled and reasonable alternatives (usually no-ops) when exceptions are
59/// disabled.
60///
61/// ## Usage {#bsls_exceptionutil-usage}
62///
63///
64/// This section illustrates intended use of this component.
65///
66/// ### Example 1: Using @ref bsls_exceptionutil to Implement vector {#bsls_exceptionutil-example-1-using-ref-bsls_exceptionutil-to-implement-vector}
67///
68///
69/// Suppose we wanted to define an implementation of a standard-defined `vector`
70/// template. Unfortunately, the C++ standard requires that `vector` provide an
71/// `at` method that throws an `out_of_range` exception if the supplied index is
72/// not in the valid range of elements in the vector. In this example we show
73/// using `BSLS_THROW` so that such an implementation will compile in both
74/// exception enabled and non-exception enabled builds. Note that apart from
75/// memory allocation, and where required by the C++ standard, types defined in
76/// the BDE libraries do not throw exceptions, and are typically
77/// "exception-neutral" (see @ref bsldoc_glossary ), meaning they behave
78/// reasonably in the presence of injected exceptions, but do not themselves
79/// throw any exceptions.
80///
81/// First we open a namespace `myStd` and define an `out_of_range` exception
82/// that the `at` method will throw (note that in practice, `out_of_range` would
83/// inherit from @ref logic_error )':
84/// @code
85/// namespace myStd {
86///
87/// class out_of_range // ...
88/// {
89/// // ...
90/// };
91/// @endcode
92/// Next, we declare the `vector` template and its template parameters (note
93/// that the majority of the implementation is elided, for clarity):
94/// @code
95/// template <class VALUE, class ALLOCATOR /* ... */>
96/// class vector {
97/// // DATA
98/// VALUE *d_begin_p;
99/// VALUE *d_end_p;
100/// // ...
101///
102/// public:
103///
104/// typedef typename ALLOCATOR::size_type size_type;
105///
106/// //...
107/// @endcode
108/// Then, we define the `at` method, which is required to throw an
109/// `out_of_range` exception.
110/// @code
111/// const VALUE& at(size_type index) const
112/// {
113/// if (d_begin_p + index < d_end_p) {
114/// return d_begin_p[index]; // RETURN
115/// }
116/// @endcode
117/// Now, we use `BSLS_THROW` to throw an `out_of_range` exception:
118/// @code
119/// BSLS_THROW(out_of_range(/* ... */));
120/// }
121/// @endcode
122/// Finally, we complete the (mostly elided) `vector` implementation:
123/// @code
124/// // ...
125///
126/// };
127///
128/// } // close namespace myStd
129///
130/// struct DummyAllocator {
131/// typedef int size_type;
132/// };
133/// @endcode
134///
135/// ### Example 2: Using @ref bsls_exceptionutil to Throw and Catch Exceptions {#bsls_exceptionutil-example-2-using-ref-bsls_exceptionutil-to-throw-and-catch-exceptions}
136///
137///
138/// The following example demonstrates the macros defined in the
139/// @ref bsls_exceptionutil component to both throw and catch exceptions in a way
140/// that will allow the code to compile in non-exception enabled builds.
141///
142/// First, we define a couple of example exception classes (note that we cannot
143/// use `bsl::exception` in this example, as this component is defined below
144///`bsl_exception.h`):
145/// @code
146/// class my_ExClass1
147/// {
148/// };
149///
150/// class my_ExClass2
151/// {
152/// };
153/// @endcode
154/// Then, we define a function that never throws an exception, and use the
155/// `BSLS_NOTHROW_SPEC` to ensure the no-throw exception specification will be
156/// present in exception enabled builds, and elided in non-exception enabled
157/// builds:
158/// @code
159/// int noThrowFunc() BSLS_NOTHROW_SPEC
160/// {
161/// return -1;
162/// }
163/// @endcode
164/// Next, we define a function that might throw `my_ExClass1` or `my_ExClass2`,
165/// and docuemnt which exception types might be thrown. Note that dynamic
166/// exception specifications are deprecated in C++11 and removed from the
167/// language in C++17, so should not be used as a substitute for documentation
168/// in earlier language dialects:
169/// @code
170/// int mightThrowFunc(int i)
171/// // Return the specified integer 'i', unless '1 == 1' or '2 == i'. If
172/// // '1 == i' throw an exception of type 'my_ExcClass1'. If '2 == i'
173/// // throw an exception of type 'my_ExcClass2'. Note that if exceptions
174/// // are not enabled in the current build mode, then the program will
175/// // 'abort' rather than throw.
176/// {
177/// switch (i) {
178/// case 0: break;
179/// case 1: BSLS_THROW(my_ExClass1());
180/// case 2: BSLS_THROW(my_ExClass2());
181/// }
182/// return i;
183/// }
184/// @endcode
185/// Then, we start the definition of a `testMain` function:
186/// @code
187/// int testMain()
188/// {
189/// @endcode
190/// Next, we use the `BDE_BUILD_TARGET_EXC` exception build flag to determine,
191/// at compile time, whether to initialize `ITERATIONS` to 3 (for exception
192/// enabled builds) or 1 (for non-exception enabled builds). The different
193/// values of the `ITERATOR` ensure the subsequent for-loop calls
194/// `mightThrowFunc` in a way that generates exceptions for only exception
195/// enabled builds:
196/// @code
197/// #ifdef BDE_BUILD_TARGET_EXC
198/// const int ITERATIONS = 3;
199/// #else
200/// const int ITERATIONS = 1;
201/// #endif
202///
203/// for (int i = 0; i < ITERATIONS; ++i) {
204/// @endcode
205/// Then, we use a pair of nested `try` blocks constructed using
206/// `BSLS_TRY`, so that the code will compile whether or not exceptions are
207/// enabled (note that the curly brace placement is identical to normal
208/// `try` and `catch` constructs):
209/// @code
210/// int caught = -1;
211/// BSLS_TRY {
212///
213/// BSLS_TRY {
214/// noThrowFunc();
215/// mightThrowFunc(i);
216/// @endcode
217/// Notice that this example is careful to call `mightThrowFunc` in such a way
218/// that it will not throw in non-exception builds. Although the use of
219/// `BSLS_TRY`, `BSLS_THROW`, and `BSLS_CATCH` ensures the code *compiles* in
220/// both exception, and non-exception enabled builds, attempting to `BSLS_THROW`
221/// an exception in a non-exception enabled build will invoke the assert handler
222/// and will typically abort the task.
223/// @code
224/// caught = 0; // Got here if no throw
225/// }
226/// @endcode
227/// Next, we use `BSLS_CATCH` to define blocks for handling exceptions that may
228/// have been thrown from the preceding `BSLS_TRY`:
229/// @code
230/// BSLS_CATCH(my_ExClass1) {
231/// caught = 1;
232/// }
233/// BSLS_CATCH(...) {
234/// @endcode
235/// Here, within the catch-all handler, we use the `BSLS_RETHROW` macro to
236/// re-throw the exception to the outer `try` block:
237/// @code
238/// BSLS_RETHROW;
239/// } // end inner try-catch
240/// }
241/// BSLS_CATCH(my_ExClass2) {
242/// caught = 2;
243/// }
244/// BSLS_CATCH(...) {
245/// assert("Should not get here" && 0);
246/// } // end outer try-catch
247///
248/// if (0 != caught) {
249/// if (verbose)
250/// printf("Caught exception my_ExClass: %d\n", caught);
251/// }
252/// else {
253/// if (verbose)
254/// printf("Caught no exceptions: %d\n", caught);
255/// }
256/// assert(i == caught);
257///
258/// } // end for (i)
259///
260/// return 0;
261/// }
262/// @endcode
263/// @}
264/** @} */
265/** @} */
266
267/** @addtogroup bsl
268 * @{
269 */
270/** @addtogroup bsls
271 * @{
272 */
273/** @addtogroup bsls_exceptionutil
274 * @{
275 */
276
277#include <bsls_assert.h>
278#include <bsls_buildtarget.h>
280#include <bsls_deprecate.h>
281#include <bsls_libraryfeatures.h>
282
283 // ======
284 // macros
285 // ======
286
287#ifdef BDE_BUILD_TARGET_EXC
288
289 // ------------------
290 // Exceptions enabled
291 // ------------------
292
293# define BSLS_TRY try
294 // Start a try block.
295 // Exceptions enabled: 'try'
296 // Exceptions disabled: start of a normal (non-try) block
297
298# define BSLS_CATCH(X) catch (X)
299 // Catch exception 'X'. 'X' must be a type with optional variable name
300 // Exceptions enabled: 'catch (X)'
301 // Exceptions disabled: ignore following block
302
303# define BSLS_THROW(X) throw X
304 // Throw exception object 'X'.
305 // Exceptions enabled: 'throw (X)'
306 // Exceptions disabled: abort with a message
307
308# define BSLS_RETHROW throw
309 // Within a 'BSLS_CATCH' clause, re-throw the last exception
310 // Exceptions enabled: 'throw'
311 // Exceptions disabled: abort with a message
312
313# if !BSLS_DEPRECATE_IS_ACTIVE(BDE, 3, 17)
314# if defined(BSLS_COMPILERFEATURES_SUPPORT_THROW_SPECIFICATIONS)
315 /// @deprecated This macro is deprecated, as the language feature itself
316 /// is deprecated in C++11, and is entirely removed in C++17. It is
317 /// recommended to simply document the potential set of exceptions that
318 /// may be thrown by a function instead.
319 ///
320 /// Declare a dynamic exception specification for a function.
321 /// Usage:
322 /// @code
323 /// void f() BSLS_EXCEPTION_SPEC((std::logic_error));
324 /// @endcode
325 /// `SPEC` must be a comma-separated list of one or more exception
326 /// types enclosed in parenthesis. (Double parenthesis are mandatory)
327 /// Use `BSLS_NOTHROW_SPEC` (below) to declare that a function does not
328 /// throw.
329 /// Exceptions enabled: `throw SPEC`
330 /// Exceptions disabled: empty
331# define BSLS_EXCEPTION_SPEC(SPEC) throw SPEC
332# else
333 /// @deprecated This macro is deprecated, and cannot expand to a
334 /// supported syntax on the current platform.
335# define BSLS_EXCEPTION_SPEC(SPEC)
336# endif // BSLS_COMPILERFEATURES_SUPPORT_THROW_SPECIFICATIONS
337# endif // BSLS_DEPRECATE_IS_ACTIVE
338
339 /// Declare that a function does not throw any exceptions:
340 /// Usage:
341 /// @code
342 /// void f() BSLS_NOTHROW_SPEC;
343 /// @endcode
344 /// Exceptions enabled: `throw ()` or `noexcept`
345 /// Exceptions disabled: empty
346# if defined(BSLS_COMPILERFEATURES_SUPPORT_NOEXCEPT)
347# define BSLS_NOTHROW_SPEC noexcept
348# else
349# define BSLS_NOTHROW_SPEC throw ()
350# endif
351
352 /// The exception specification that overrides of the virtual destructor
353 /// and the `exception::what()` virtual method should use. It is a
354 /// separate macro from `BSLS_NOTHROW_SPEC` because the GNU library
355 /// unconditionally declares the function `throw()`, regardless if
356 /// exceptions are enabled or not - and overrides must do the same.
357# define BSLS_EXCEPTION_VIRTUAL_NOTHROW BSLS_NOTHROW_SPEC
358
359 /// More specialized name for the no-throw declaration of the
360 /// `exception::what()` method. Use `BSLS_EXCEPTION_VIRTUAL_NOTHROW`
361 /// instead.
362# define BSLS_EXCEPTION_WHAT_NOTHROW BSLS_EXCEPTION_VIRTUAL_NOTHROW
363
364#else // If exceptions are disabled
365
366 // -------------------
367 // Exceptions disabled
368 // -------------------
369
370# define BSLS_TRY if (1)
371
372# define BSLS_CATCH(X) else if (0)
373
374# define BSLS_THROW(X) BSLS_ASSERT_INVOKE_NORETURN( \
375 "Tried to throw " #X \
376 " with exceptions disabled");
377
378# define BSLS_RETHROW BSLS_ASSERT_INVOKE_NORETURN( \
379 "Tried to re-throw exception " \
380 "with exceptions disabled");
381
382# if !BSLS_DEPRECATE_IS_ACTIVE(BDE, 3, 17)
383# define BSLS_EXCEPTION_SPEC(SPEC)
384# endif // BSLS_DEPRECATE_IS_ACTIVE
385
386# define BSLS_NOTHROW_SPEC
387
388 /// The exception specification that overrides of the
389 /// `exception::what()` virtual method should use. It is a separate
390 /// macro from `BSLS_NOTHROW_SPEC` because the GNU library
391 /// unconditionally declares the function `throw()`, regardless if
392 /// exceptions are enabled or not - and overrides must do the same.
393# if defined(BSLS_LIBRARYFEATURES_STDCPP_GNU) || \
394 defined(BSLS_LIBRARYFEATURES_STDCPP_LIBCSTD) || \
395 defined(BSLS_LIBRARYFEATURES_STDCPP_IBM)
396# if defined(BSLS_COMPILERFEATURES_SUPPORT_NOEXCEPT)
397# define BSLS_EXCEPTION_VIRTUAL_NOTHROW noexcept
398# else
399# define BSLS_EXCEPTION_VIRTUAL_NOTHROW throw ()
400# endif
401# else
402# define BSLS_EXCEPTION_VIRTUAL_NOTHROW
403# endif
404
405
406#endif // BDE_BUILD_TARGET_EXC
407
408
409
410
411#endif // ! defined(INCLUDED_BSLS_EXCEPTIONUTIL)
412
413// ----------------------------------------------------------------------------
414// Copyright 2013 Bloomberg Finance L.P.
415//
416// Licensed under the Apache License, Version 2.0 (the "License");
417// you may not use this file except in compliance with the License.
418// You may obtain a copy of the License at
419//
420// http://www.apache.org/licenses/LICENSE-2.0
421//
422// Unless required by applicable law or agreed to in writing, software
423// distributed under the License is distributed on an "AS IS" BASIS,
424// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
425// See the License for the specific language governing permissions and
426// limitations under the License.
427// ----------------------------- END-OF-FILE ----------------------------------
428
429/** @} */
430/** @} */
431/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195