1 #ifndef _SIGC_ADAPTORS_EXCEPTION_CATCH_H_
2 #define _SIGC_ADAPTORS_EXCEPTION_CATCH_H_
3 #include <sigc++/adaptors/adaptor_trait.h>
8 functor adaptor: exception_catch(functor, catcher)
14 The catcher should be told what type of return it needs to
15 return for multiple type functors, to do this the user
16 will need to derive from catcher_base.
18 /** @defgroup exception_catch exception_catch()
19 * sigc::exception_catch() catches an exception thrown from within
20 * the wrapped functor and directs it to a catcher functor.
21 * This catcher can then rethrow the exception and catch it with the proper type.
23 * Note that the catcher is expected to return the same type
24 * as the wrapped functor so that normal flow can continue.
26 * Catchers can be cascaded to catch multiple types, because uncaught
27 * rethrown exceptions proceed to the next catcher adaptor.
36 * catch (std::range_error e) // catch what types we know
37 * { std::cerr << "caught " << e.what() << std::endl; }
41 * int foo(); // throws std::range_error
42 * sigc::exception_catch(&foo, my_catch())();
45 * The functor sigc::exception_catch() returns can be directly passed into
46 * sigc::signal::connect().
50 * sigc::signal<int()> some_signal;
51 * some_signal.connect(sigc::exception_catch(&foo, my_catch));
57 template <class T_functor, class T_catcher, class T_return = typename adapts<T_functor>::result_type>
58 struct exception_catch_functor : public adapts<T_functor>
60 using adaptor_type = typename adapts<T_functor>::adaptor_type;
61 using result_type = T_return;
67 { return this->functor_(); }
69 { return catcher_(); }
73 template <class... T_arg>
75 operator()(T_arg... _A_a)
79 return this->functor_.template operator()<type_trait_pass_t<T_arg>...>
83 { return catcher_(); }
87 exception_catch_functor(const T_functor& _A_func,
88 const T_catcher& _A_catcher)
89 : adapts<T_functor>(_A_func), catcher_(_A_catcher)
95 // void specialization
96 template <class T_functor, class T_catcher>
97 struct exception_catch_functor<T_functor, T_catcher, void> : public adapts<T_functor>
99 using result_type = void;
100 using adaptor_type = typename adapts<T_functor>::adaptor_type;
102 template <class... T_arg>
104 operator()(T_arg... _A_a)
108 return this->functor_.template operator()<type_trait_pass_t<T_arg>...>
112 { return catcher_(); }
116 exception_catch_functor() {}
117 exception_catch_functor(const T_functor& _A_func,
118 const T_catcher& _A_catcher)
119 : adapts<T_functor>(_A_func), catcher_(_A_catcher)
121 ~exception_catch_functor() {}
126 #ifndef DOXYGEN_SHOULD_SKIP_THIS
127 //template specialization of visitor<>::do_visit_each<>(action, functor):
128 template <class T_functor, class T_catcher, class T_return>
129 struct visitor<exception_catch_functor<T_functor, T_catcher, T_return> >
131 template <typename T_action>
132 static void do_visit_each(const T_action& _A_action,
133 const exception_catch_functor<T_functor, T_catcher, T_return>& _A_target)
135 sigc::visit_each(_A_action, _A_target.functor_);
136 sigc::visit_each(_A_action, _A_target.catcher_);
139 #endif // DOXYGEN_SHOULD_SKIP_THIS
141 template <class T_functor, class T_catcher>
142 inline decltype(auto)
143 exception_catch(const T_functor& _A_func, const T_catcher& _A_catcher)
144 { return exception_catch_functor<T_functor, T_catcher>(_A_func, _A_catcher); }
146 } /* namespace sigc */
147 #endif /* _SIGC_ADAPTORS_EXCEPTION_CATCH_H_ */