Item 8. Writing Exception-Safe
Code—Part 1
Difficulty: 7
Exception handling and
templates are two of C++'s most powerful features. Writing
exception-safe code, however, can be difficult—especially in a
template, when you may have no idea when (or what) a certain
function might throw your way.
We'll begin where Cargill left off—namely, by
progressively creating a safe version of the Stack
template he critiqued. Later on, we'll significantly improve the
Stack container by reducing the requirements on
T, the contained type, and show advanced techniques for
managing resources exception-safely. Along the way, we'll find the
answers to such questions as:
-
What are the different "levels" of exception
safety?
-
Can or should generic containers be fully
exception-neutral?
-
Are the standard library containers
exception-safe or exception-neutral?
-
Does exception safety affect the design of your
container's public interface?
-
Should generic containers use exception
specifications?
Here is the declaration of the Stack
template, substantially the same as in Cargill's article. Your
mission: Make Stack exception-safe and exception-neutral.
That is, Stack objects should always be in a correct and
consistent state, regardless of any exceptions that might be thrown
in the course of executing Stack's member functions. If
any exceptions are thrown, they should be propagated seamlessly
through to the caller, who can deal with them as he pleases,
because he knows the context of T and we don't.
template <class T> class Stack
{
public:
Stack();
~Stack();
/*...*/
private:
T* v_; // ptr to a memory area big
size_t vsize_; // enough for 'vsize_' T's
size_t vused_; // # of T's actually in use
};
Write the Stack default constructor and
destructor in a way that is demonstrably exception-safe (works
properly in the presence of exceptions) and exception-neutral
(propagates all exceptions to the caller, without causing integrity
problems in a Stack object).
|