Imported Upstream version 2.99.2
[platform/upstream/libsigc++.git] / sigc++ / adaptors / exception_catch.h
1 #ifndef _SIGC_ADAPTORS_EXCEPTION_CATCH_H_
2 #define _SIGC_ADAPTORS_EXCEPTION_CATCH_H_
3 #include <sigc++/adaptors/adaptor_trait.h>
4
5 namespace sigc {
6
7 /*
8    functor adaptor:  exception_catch(functor, catcher)
9
10    usage:
11
12
13    Future directions:
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.
17 */
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.
22  *
23  * Note that the catcher is expected to return the same type
24  * as the wrapped functor so that normal flow can continue.
25  *
26  * Catchers can be cascaded to catch multiple types, because uncaught
27  * rethrown exceptions proceed to the next catcher adaptor.
28  *
29  * @par Examples:
30  * @code
31  * struct my_catch
32  * {
33  *   int operator()()
34  *   {
35  *     try { throw; }
36  *     catch (std::range_error e) // catch what types we know
37  *       { std::cerr << "caught " << e.what() << std::endl; }
38  *     return 1;
39  *   }
40  * }
41  * int foo(); // throws std::range_error
42  * sigc::exception_catch(&foo, my_catch())();
43  * @endcode
44  *
45  * The functor sigc::exception_catch() returns can be directly passed into
46  * sigc::signal::connect().
47  *
48  * @par Example:
49  * @code
50  * sigc::signal<int()> some_signal;
51  * some_signal.connect(sigc::exception_catch(&foo, my_catch));
52  * @endcode
53  *
54  * @ingroup adaptors
55  */
56
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>
59 {
60   using adaptor_type = typename adapts<T_functor>::adaptor_type;
61   using result_type = T_return;
62
63   decltype(auto)
64   operator()()
65     {
66       try
67         { return this->functor_(); }
68       catch (...)
69         { return catcher_(); }
70     }
71
72
73   template <class... T_arg>
74   decltype(auto)
75   operator()(T_arg... _A_a)
76     {
77       try
78         {
79           return this->functor_.template operator()<type_trait_pass_t<T_arg>...>
80             (_A_a...);
81         }
82       catch (...)
83         { return catcher_(); }
84     }
85
86
87   exception_catch_functor(const T_functor& _A_func,
88                           const T_catcher& _A_catcher)
89     : adapts<T_functor>(_A_func), catcher_(_A_catcher)
90     {}
91
92   T_catcher catcher_;
93 };
94
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>
98 {
99   using result_type = void;
100   using adaptor_type = typename adapts<T_functor>::adaptor_type;
101
102   template <class... T_arg>
103   decltype(auto)
104   operator()(T_arg... _A_a)
105     {
106       try
107         {
108           return this->functor_.template operator()<type_trait_pass_t<T_arg>...>
109             (_A_a...);
110         }
111       catch (...)
112         { return catcher_(); }
113     }
114
115
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)
120     {}
121   ~exception_catch_functor() {}
122
123     T_catcher catcher_;
124 };
125
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> >
130 {
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)
134   {
135     sigc::visit_each(_A_action, _A_target.functor_);
136     sigc::visit_each(_A_action, _A_target.catcher_);
137   }
138 };
139 #endif // DOXYGEN_SHOULD_SKIP_THIS
140
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); }
145
146 } /* namespace sigc */
147 #endif /* _SIGC_ADAPTORS_EXCEPTION_CATCH_H_ */