Commit f4dd104c authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

A smaller implementation of try_and_catch

Summary:
[Folly] A smaller implementation of `try_and_catch`.

No longer done as a derived class. This lets us make the protected members of `exception_wrapper` into private members.

Reviewed By: ericniebler

Differential Revision: D4366065

fbshipit-source-id: ae4763b55e431ac08260f74f6a23a257581247c9
parent 1e039743
......@@ -19,6 +19,7 @@
#include <exception>
#include <memory>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
......@@ -105,7 +106,7 @@ namespace folly {
*
*/
class exception_wrapper {
protected:
private:
template <typename Ex>
struct optimize;
......@@ -269,7 +270,7 @@ class exception_wrapper {
return std::exception_ptr();
}
protected:
private:
template <typename Ex>
struct optimize {
static const bool value =
......@@ -408,67 +409,43 @@ fbstring exceptionStr(const exception_wrapper& ew);
* });
*/
namespace detail {
template <typename... Exceptions>
class try_and_catch;
template <typename LastException, typename... Exceptions>
class try_and_catch<LastException, Exceptions...> :
public try_and_catch<Exceptions...> {
public:
template <typename F>
explicit try_and_catch(F&& fn) : Base() {
call_fn(fn);
}
namespace try_and_catch_detail {
protected:
typedef try_and_catch<Exceptions...> Base;
template <bool V, typename T = void>
using enable_if_t_ = typename std::enable_if<V, T>::type;
try_and_catch() : Base() {}
template <typename... Args>
using is_wrap_ctor = std::is_constructible<exception_wrapper, Args...>;
template <typename Ex>
typename std::enable_if<!exception_wrapper::optimize<Ex>::value>::type
assign_exception(Ex& e, std::exception_ptr eptr) {
exception_wrapper::assign_eptr(eptr, e);
}
template <typename Ex>
typename std::enable_if<exception_wrapper::optimize<Ex>::value>::type
assign_exception(Ex& e, std::exception_ptr /*eptr*/) {
exception_wrapper::assign_sptr(std::make_shared<Ex>(e));
}
template <typename Ex>
inline enable_if_t_<!is_wrap_ctor<Ex&>::value, exception_wrapper> make(Ex& ex) {
return exception_wrapper(std::current_exception(), ex);
}
template <typename F>
void call_fn(F&& fn) {
try {
Base::call_fn(std::move(fn));
} catch (LastException& e) {
if (typeid(e) == typeid(LastException&)) {
assign_exception(e, std::current_exception());
} else {
exception_wrapper::assign_eptr(std::current_exception(), e);
}
}
}
};
template <typename Ex>
inline enable_if_t_<is_wrap_ctor<Ex&>::value, exception_wrapper> make(Ex& ex) {
return typeid(Ex&) == typeid(ex)
? exception_wrapper(ex)
: exception_wrapper(std::current_exception(), ex);
}
template<>
class try_and_catch<> : public exception_wrapper {
public:
try_and_catch() = default;
template <typename F>
inline exception_wrapper impl(F&& f) {
return (f(), exception_wrapper());
}
protected:
template <typename F>
void call_fn(F&& fn) {
fn();
template <typename F, typename Ex, typename... Exs>
inline exception_wrapper impl(F&& f) {
try {
return impl<F, Exs...>(std::forward<F>(f));
} catch (Ex& ex) {
return make(ex);
}
};
}
} // try_and_catch_detail
template <typename... Exceptions, typename F>
exception_wrapper try_and_catch(F&& fn) {
return detail::try_and_catch<Exceptions...>(std::forward<F>(fn));
} // detail
return try_and_catch_detail::impl<F, Exceptions...>(std::forward<F>(fn));
}
} // folly
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment