struct myStupidCustomString {
myStupidCustomString(char const *what) : what (what) {}
char const *what;
};
void throws() {
throw myStupidCustomString("here is some really useful information");
}
// The external library can provide a function, or you can provide a wrapper, which
// extracts information from "unknown" exception types.
std::string extract_from_unknown_external_exception() {
try { throw; }
catch (myStupidCustomString &e) {
return e.what;
}
catch (...) {
throw; // Rethrow original exception.
}
}
typedef std::string Extract();
std::vector<Extract*> chain (1, &extract_from_unknown_external_exception);
// Chain would normally be initialized using whatever scheme you prefer for
// initializing global objects.
// A list or other container (including a manual linked list that doesn't
// require dynamic allocation) may be more appropriate, depending on how you
// want to register and unregister handlers.
std::string process_chain() {
for (std::vector<Extract*>::iterator x = chain.begin(); x != chain.end(); ++x) {
try {
return (*x)();
}
catch (...) { // That handler couldn't handle it. Proceed to next.
}
}
throw; // None could handle it, rethrow original exception.
}
void example() {
try { throws(); }
catch (...) {
try {
std::string extracted = process_chain();
std::cout << "extracted: " << extracted << '\n';
}
catch (...) {
throw; // Rethrow unknown exception, or otherwise handle it.
}
}
}
int main() {
example();
return 0;
}