Info
-
Did you know about function-try-block and that exceptions caught inside that block are implicitly rethrown?
Example
struct foo {
foo() { throw 0; }
};
struct bar {
bar() try : foo_{} {
// constructor body
}
catch (...)
{
// exceptions from the initializer list are caught here
// but also re-thrown after this block (unless the program is aborted)
}
private:
foo foo_;
};
int main() try {
bar b{};
}
catch(...) {
// okay, exception cought here!
}
Puzzle
- Can you implement
foo
's constructor which initializesTs...
and setsexception
to true if any exception is thrown and rethrows it?
template<class TException>
struct ctor_except {
ctor_except() { throw TException{}; }
};
template<class... Ts>
struct foo : Ts... {
explicit(true) foo(bool& exception); // TODO
};
int main() {
using namespace boost::ut;
"function-try-block"_test = [] {
bool exception{false};
struct bar { };
should("not set exception with empty list") = [=] {
expect(nothrow([&]{ foo<>{mut(exception)}; }) and not exception);
};
should("not set exception with non-throwing types") = [=] {
expect(nothrow([&]{ foo<bar>{mut(exception)}; }) and not exception);
};
should("catch exception if thrown from within the constructor") = [=] {
expect(throws<int>([&]{ foo<ctor_except<int>>{mut(exception)}; }) and exception);
};
should("catch exception if thrown from within the constructor with muliple types") = [=] {
expect(throws<int>([&]{ foo<bar, ctor_except<int>>{mut(exception)}; }) and exception);
};
};
}
Solutions
template<class... Ts>
struct foo : Ts... {
explicit(true) foo (bool& exception) try : Ts{}... {
} catch (...) {
exception = true;
}
};
template<class... Ts>
struct foo : Ts... {
explicit(true) foo(bool& exception) try : Ts()... {
exception = false;
} catch(...) {
exception = true;
}
};