Should my exception classes provide details in public fields in addition to what()?
Consider for example boost::property_tree::ptree_bad_path which might give a message:
"No such node (mynode.value1)"
The only way to access the path ("mynode.value1") is by parsing the string. Is there an argument against adding additional public fields to carry such information, that is:
class ptree_bad_path : public ptree_error {
public:
const std::string path; // <- additional detail by public field
....
Are there drawbacks to this approach?
In theory, you run the risk of having your program
terminateif you ever have two unhandled exceptions at the same time. This is, however, a rather rare situation.catch): fine (after all, rethrowing a different exception is common)So, the avoidable risk here is if the copy constructor of your exception might happen to throw. It is trivial to elude the issue by moving the state off to a
shared_ptrcontained within the exception. It makes copies a bit “special” (since they share their state with the original) but if it’s documented properly it should not cause any grief.The greater risk is during stack unwinding. It only occurs if a destructor throws, though.
Personally, the exceptions I use contain:
The only controversial point here is the on the fly bit, since it might effectively crash. On the other hand, I work on servers so crashes are easily (and urgently) fixed and for the last 5 years I was careful enough not to cause a crash (this way ;)).
Note that this scheme is obviously only available if you use exceptions sparsely. If you routinely throw a dozen exceptions per task, the performance might be unnacceptable. On the other hand, the Zero Cost model used by major compilers already harshly penalize the exceptional path so…