I think your code would be just fine, but here is an alternative to consider:
void DoTheJob(Logger &log/*,args*/)
{
std::unique_ptr<Res1Holder> r1 = acquireRes1(/*args*/);
if (!r1) {
log.log("Can't acquire resource 1, using fallback");
DoTheJobTheSlowAndPainfulWay(log);
return;
}
std::unique_ptr<Res2Holder> r2 = acquireRes2(/*args*/);
if (!r2) {
log.log("Can't acquire resource 2, that'll slow us down a bit.");
DoTheJobWithModerateSuffering(log,*r1);
return;
}
DoTheJobQuicklyAndEasily(log,*r1,*r2);
}
Where the acquireRes functions return a null unique_ptr when the resource fails to initialize:
std::unique_ptr<Res1Holder> acquireRes1()
{
try {
return std::unique_ptr<Res1Holder>(new Res1Holder());
}
catch (Res1InitializationException& e) {
return std::unique_ptr<Res1Holder>();
}
}
std::unique_ptr<Res2Holder> acquireRes2()
{
try {
return std::unique_ptr<Res2Holder>(new Res2Holder());
}
catch (Res2InitializationException& e) {
return std::unique_ptr<Res2Holder>();
}
}