During the member initialisation of a class with multiple members, it seems desirable to be able to catch an exception generated by any specific member initialiser, to wrap in additional context for rethrowing, but the syntax of a function-try-block doesn't appear to accomodate that.
#include <stdexcept>
#include <string>
#include <sstream>
using namespace std::literals::string_literals;
[[noreturn]]
int thrower() { throw std::runtime_error("unconditional throw"s); }
int nonThrower() { return 3; }
class C {
int x;
int y;
public:
C();
};
class XError : public std::runtime_error {
public:
XError(const std::string& what) : std::runtime_error((std::stringstream() << "xerror: "s << what).str()) {};
};
class YError : public std::runtime_error {
public:
YError(const std::string& what) : std::runtime_error((std::stringstream() << "yerror: "s << what).str()) {};
};
C::C() try:
x(nonThrower()),
y(thrower()) {}
catch(const std::exception& e) { /* ... */ }
In the above trivial example, on the final line, I would very much like to be able to throw XError()
if the exception occurs in initialisation of .x
, and YError()
if the exception occurs in initialisation of .y
.
Ideally I'd like to be able to do something like
// -std=c++3000
C::C():
try: x(nonThrower()) catch(const std::exception& e) { throw XError(e.what()); },
try: y(thrower()) catch(const std::exception& e) { throw YError(e.what()); } {}
But it seems my only option is to write separate functions per initialiser member which wrap the exceptions themselves, then use those in the member initialisers. Given how ghastly member initialiser syntax is, this will probably read better, but it's less compact and more non-linear, which is less than ideal. For completeness:
int makeX() {
try { return nonThrower(); }
catch(const std::exception& e) { throw XError(e.what()); }
}
int makeY() {
try { return thrower(); }
catch(const std::exception& e) { throw YError(e.what()); }
}
C::C():
x(makeX()),
y(makeY()) {}
Please excuse any antipatterns or mistakes in my C++. I am both very new to the language and not as smart as you might hope me to be.