Throw an exception to signal that a function can't perform its assigned task
Reason
To make error handling systematic, robust, and non-repetitive.
Example
struct Foo {
vector<Thing> v;
File_handle f;
string s;
};
void use()
{
Foo bar { {Thing{1}, Thing{2}, Thing{monkey} }, {"my_file", "r"}, "Here we go!"};
// ...
}
Here, vector and strings constructors might not be able to allocate sufficient memory for their elements, vectors constructor might not be able to copy the Things in its initializer list, and File_handle might not be able to open the required file. In each case, they throw an exception for use()'s caller to handle. If use() could handle the failure to construct bar it can take control using try/catch. In either case, Foo's constructor correctly destroys constructed members before passing control to whatever tried to create a Foo. Note that there is no return value that could contain an error code.
The File_handle constructor might be defined like this:
File_handle::File_handle(const string& name, const string& mode)
: f{fopen(name.c_str(), mode.c_str())}
{
if (!f)
throw runtime_error{"File_handle: could not open " + name + " as " + mode};
}
Note
It is often said that exceptions are meant to signal exceptional events and failures. However, that's a bit circular because "what is exceptional?" Examples:
- A precondition that cannot be met
- A constructor that cannot construct an object (failure to establish its class's invariant)
- An out-of-range error (e.g.,
v[v.size()] = 7) - Inability to acquire a resource (e.g., the network is down)
In contrast, termination of an ordinary loop is not exceptional. Unless the loop was meant to be infinite, termination is normal and expected.
Note
Don't use a throw as simply an alternative way of returning a value from a function.
Exception
Some systems, such as hard-real-time systems require a guarantee that an action is taken in a (typically short) constant maximum time known before execution starts. Such systems can use exceptions only if there is tool support for accurately predicting the maximum time to recover from a throw.
See also: RAII
See also: discussion
Note
Before deciding that you cannot afford or don't like exception-based error handling, have a look at the alternatives; they have their own complexities and problems. Also, as far as possible, measure before making claims about efficiency.