    Exceptions may be generated from inside constructors. How can exceptions
generated in such situations be caught by the constructor itself, rather than
outside the constructor? The intuitive solution, nesting the object
construction in a tt(try) block does not solve the problem. The exception by
then has left the constructor and the object we intended to construct isn't
visible anymore.

    Using a nested tt(try) block is illustrated in the next example, where
tt(main) defines an object of class tt(PersonDb). Assuming that
tt(PersonDb)'s constructor throws an exception, there is no way we can access
the resources that might have been allocated by tt(PersonDb)'s constructor
from the catch handler as the tt(pdb) object is out of scope:
        verb(
    int main(int argc, char **argv)
    {
        try
        {
            PersonDb pdb{ argc, argv }; // may throw exceptions
            ...                         // main()'s other code
        }
        catch(...)                      // and/or other handlers
        {
            ...                         // pdb is inaccessible from here
        }
    }
        )

    Although all objects and variables defined inside a tt(try) block are
inaccessible from its associated catch handlers, object data members were
available before starting the tt(try) block and so they may be accessed from a
catch handler. In the following example the catch handler in
tt(PersonDb)'s constructor is able to access its tt(d_data) member:
        verb(
    PersonDb::PersonDb(int argc, char **argv)
    :
        d_data(0),
        d_size(0)
    {
        try
        {
            initialize(argc, argv);
        }
        catch(...)
        {
            // d_data, d_size: accessible
        }
    }
        )

    Unfortunately, this does not help us much. The tt(initialize) member is
unable to reassign tt(d_data) and tt(d_size) if tt(PersonDb const pdb)
was defined; the tt(initialize) member should at least offer the basic
exception guarantee and return any resources it has acquired before
terminating due to a thrown exception; and although tt(d_data) and tt(d_size)
offer the nothrow guarantee as they are of primitive data types a class type
data member might throw an exception, possibly resulting in violation of the
basic guarantee.

    In the next implementation of tt(PersonDb) assume that constructor
receives a pointer to an already allocated block of tt(Person) objects. The
tt(PersonDb) object takes ownership of the allocated memory and it is
therefore responsible for the allocated memory's eventual destruction.
Moreover, tt(d_data) and tt(d_size) are also used by a composed object
tt(PersonDbSupport), having a constructor expecting a tt(Person const *) and
tt(size_t) argument. Our next implementation may then look something like
this:
        verb(
    PersonDb::PersonDb(Person *pData, size_t size)
    :
        d_data(pData),
        d_size(size),
        d_support(d_data, d_size)
    {
        // no further actions
    }
        )
    This setup allows us to define a tt(PersonDb const &pdb). Unfortunately,
tt(PersonDb) cannot offer the basic guarantee. If tt(PersonDbSupport)'s
constructor throws an exception it isn't caught although tt(d_data) already
points to allocated memory.

    The emi(function try block) offers a solution for this problem. A function
try block consists of a tt(try) block and its associated handlers. The
function tt(try) block starts em(immediately) after the function header, and
its block defines the function body. With constructors base class and data
member initializers may be placed between the tt(try) keyword and the opening
curly brace. Here is our final implementation of tt(PersonDb), now offering
the basic guarantee:
        verb(
    PersonDb::PersonDb(Person *pData, size_t size)
    try
    :
        d_data(pData),
        d_size(size),
        d_support(d_data, d_size)
    {}
    catch (...)
    {
        delete[] d_data;
    }
        )

    Let's have a look at a stripped-down example. A constructor defines a
function try block. The exception thrown by the tt(Throw) object is initially
caught by the object itself. Then it is rethrown. The surrounding
tt(Composer)'s constructor also defines a function try block, tt(Throw)'s
rethrown exception is properly caught by tt(Composer)'s exception handler,
even though the exception was generated from within its member initializer
list:
        verbinclude(-a examples/function.cc)

    When running this example, we're in for a nasty surprise: the program runs
and then breaks with an emi(abort exception). Here is the output it produces,
the last two lines being added by the system's final catch-all handler,
catching all remaining uncaught exceptions:
        verb(
    Throw's exception handled locally by Throw()
    Composer() caught exception as well
    terminate called after throwing an instance of 'int'
    Abort
        )
    The reason for this is documented in the bf(C++) standard: at the end of a
catch-handler belonging to a constructor or destructor function try block, the
original exception is automatically rethrown.

The exception is not rethrown if the handler itself throws another exception,
offering the constructor or destructor a way to
 hi(exception: replace) replace a thrown exception by another one. The
exception is only rethrown if it reaches the end of the catch handler of a
constructor or destructor function try block. Exceptions caught by nested
catch handlers are not automatically rethrown.

As only constructors and destructors rethrow exceptions caught by their
function try block catch handlers the run-time error encountered in the above
example may simply be repaired by providing tt(main) with its own function try
block:
        verb(
    int main()
    try
    {
        Composer c;
    }
    catch (...)
    {}
        )
    Now the program runs as planned, producing the following output:
        verb(
    Throw's exception handled locally by Throw()
    Composer() caught exception as well
        )

    A final note: if a function defining a function try block also declares an
exception throw list then only the types of rethrown exceptions must match
the types mentioned in the throw list.
