template <class Ex, class F>
bool with_exception(F f) {
- if (item_) {
- if (auto ex = dynamic_cast<Ex*>(getCopied())) {
- f(*ex);
- return true;
- }
- } else if (eptr_) {
- try {
- std::rethrow_exception(eptr_);
- } catch (std::exception& e) {
- if (auto ex = dynamic_cast<Ex*>(&e)) {
- f(*ex);
- return true;
- }
- } catch (...) {
- // fall through
- }
- }
- return false;
+ return with_exception1<Ex>(f, this);
}
template <class Ex, class F>
bool with_exception(F f) const {
- return with_exception<const Ex>(f);
+ return with_exception1<const Ex>(f, this);
}
std::exception_ptr getExceptionPtr() const {
return std::exception_ptr();
}
- protected:
+protected:
// Optimized case: if we know what type the exception is, we can
// store a copy of the concrete type, and a helper function so we
// can rethrow it.
template <class T, class... Args>
friend exception_wrapper make_exception_wrapper(Args&&... args);
+
+private:
+ // What makes this useful is that T can be exception_wrapper* or
+ // const exception_wrapper*, and the compiler will use the
+ // instantiation which works with F.
+ template <class Ex, class F, class T>
+ static bool with_exception1(F f, T* that) {
+ if (that->item_) {
+ if (auto ex = dynamic_cast<Ex*>(that->getCopied())) {
+ f(*ex);
+ return true;
+ }
+ } else if (that->eptr_) {
+ try {
+ std::rethrow_exception(that->eptr_);
+ } catch (std::exception& e) {
+ if (auto ex = dynamic_cast<Ex*>(&e)) {
+ f(*ex);
+ return true;
+ }
+ } catch (...) {
+ // fall through
+ }
+ }
+ return false;
+ }
};
template <class T, class... Args>
EXPECT_EQ(ie.getInt(), expected);
EXPECT_EQ(typeid(ie), typeid(IntException));
});
+
+ // Test with const this. If this compiles and does not crash due to
+ // infinite loop when it runs, it succeeds.
+ const exception_wrapper& cew = ew;
+ cew.with_exception<IntException>([&](const IntException& ie) {
+ SUCCEED();
+ });
+
+ // This won't even compile. You can't use a function which takes a
+ // non-const reference with a const exception_wrapper.
+/*
+ cew.with_exception<IntException>([&](IntException& ie) {
+ SUCCEED();
+ });
+*/
}
TEST(ExceptionWrapper, non_std_exception_test) {