File: emptythrow.yo

package info (click to toggle)
c%2B%2B-annotations 12.2.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 13,044 kB
  • sloc: cpp: 24,337; makefile: 1,517; ansic: 165; sh: 121; perl: 90
file content (90 lines) | stat: -rw-r--r-- 4,203 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
Sometimes it is required to inspect a thrown exception. An exception catcher
may decide to ignore the exception, to process the exception, to rethrow it
after inspection or to change it into another kind of exception. For example,
in a server-client application the client may submit requests to the server by
entering them into a queue. Normally every request is eventually answered by
the server. The server may reply that the request was successfully processed,
or that some sort of error has occurred. On the other hand, the server may
have died, and the client should be able to discover this calamity, by not
waiting indefinitely for the server to reply.

In this situation an intermediate exception handler is called for. A thrown
exception is first inspected at the middle level. If possible it is processed
there. If it is not possible to process the exception at the middle level, it
is passed on, unaltered, to a more superficial level, where the really tough
exceptions are handled.

By placing an hi(throw: empty) em(empty) tt(throw) statement in the exception
handler's code the received exception is passed on to the next level that
might be able to process that particular type of exception. The em(rethrown)
exception is never handled by one of its neighboring exception handlers; it
is always transferred to an exception handler at a more superficial level.

In our server-client situation a function
        verb(    initialExceptionHandler(string &exception))

could be designed to handle the tt(string) exception. The received message
is inspected. If it's a simple message it's processed, otherwise the exception
is passed on to an outer level. In tt(initialExceptionHandler)'s
implementation the empty tt(throw) statement is used:
        verb(    void initialExceptionHandler(string &exception)
    {
        if (!plainMessage(exception))
            throw;

        handleTheMessage(exception);
    })

Below (section ref(EXCEPTIONCATCH)), the empty tt(throw) statement is used
to pass on the exception received by a tt(catch)-block. Therefore, a function
like tt(initialExceptionHandler) can be used for a variety of thrown
exceptions, as long as their types match tt(initialExceptionHandler)'s
parameter, which is a string.

The next example jumps slightly ahead, using some of the topics covered in
chapter ref(POLYMORPHISM). The example may be skipped, though, without
loss of continuity.

A basic exception handling class can be constructed from which specific
exception types are derived.  Suppose we have a class tt(Exception), having a
member function tt(ExceptionType Exception::severity).  This member function
tells us (little wonder!) the severity of a thrown exception. It might be
tt(Info, Notice, Warning, Error) or tt(Fatal).  The information contained in
the exception depends on its severity and is processed by a function
tt(handle). In addition, all exceptions support a member function like
ti(textMsg), returning textual information about the exception in a
tt(string).

By defining a polymorphic function tt(handle) it can be made to behave
differently, depending on the nature of a thrown exception, when called
from a basic tt(Exception) pointer or reference.

In this case, a program may throw any of these five exception types.  Assuming
that the classes tt(Message) and tt(Warning) were derived from the class
tt(Exception), then the tt(handle) function matching the exception type will
automatically be called by the following exception catcher:
        verb(    //
    catch(Exception &ex)
    {
        cout << e.textMsg() << '\n';

        if
        (
            ex.severity() != ExceptionType::Warning
            &&
            ex.severity() != ExceptionType::Message
        )
            throw;              // Pass on other types of Exceptions

        ex.handle();            // Process a message or a warning
    })

Now anywhere in the tt(try) block preceding the exception handler
tt(Exception) objects or objects of one of its derived classes may be
thrown. All those exceptions will be caught by the above handler. E.g.,
        verb(    throw Info{};
    throw Warning{};
    throw Notice{};
    throw Error{};
    throw Fatal{};)