]> git.tdb.fi Git - ext/sigc++-2.0.git/blob - sigc++/adaptors/macros/exception_catch.h.m4
Import libsigc++ 2.10.8 sources
[ext/sigc++-2.0.git] / sigc++ / adaptors / macros / exception_catch.h.m4
1 dnl Copyright 2002, The libsigc++ Development Team
2 dnl
3 dnl This library is free software; you can redistribute it and/or
4 dnl modify it under the terms of the GNU Lesser General Public
5 dnl License as published by the Free Software Foundation; either
6 dnl version 2.1 of the License, or (at your option) any later version.
7 dnl
8 dnl This library is distributed in the hope that it will be useful,
9 dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
10 dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 dnl Lesser General Public License for more details.
12 dnl
13 dnl You should have received a copy of the GNU Lesser General Public
14 dnl License along with this library; if not, write to the Free Software
15 dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 dnl
17 divert(-1)
18
19 include(template.macros.m4)
20
21 define([EXCEPTION_CATCH_OPERATOR],[dnl
22   template <LOOP(class T_arg%1, $1)>
23   typename deduce_result_type<LOOP(T_arg%1,$1)>::type
24   operator()(LOOP(T_arg%1 _A_a%1, $1))
25     {
26       try
27         {
28           return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES<LOOP(_P_(T_arg%1), $1)>
29             (LOOP(_A_a%1, $1));
30         }
31       catch (...)
32         { return catcher_(); }
33     }
34
35 ])
36
37 divert(0)dnl
38 _FIREWALL([ADAPTORS_EXCEPTION_CATCH])
39 #include <sigc++/adaptors/adaptor_trait.h>
40
41 namespace sigc {
42
43 /*
44    functor adaptor:  exception_catch(functor, catcher)
45
46    usage:
47
48
49    Future directions:
50      The catcher should be told what type of return it needs to
51    return for multiple type functors,  to do this the user
52    will need to derive from catcher_base.
53 */
54 /** @defgroup exception_catch exception_catch()
55  * sigc::exception_catch() catches an exception thrown from within
56  * the wrapped functor and directs it to a catcher functor.
57  * This catcher can then rethrow the exception and catch it with the proper type.
58  *
59  * Note that the catcher is expected to return the same type
60  * as the wrapped functor so that normal flow can continue.
61  *
62  * Catchers can be cascaded to catch multiple types, because uncaught
63  * rethrown exceptions proceed to the next catcher adaptor.
64  *
65  * @par Examples:
66  * @code
67  * struct my_catch
68  * {
69  *   int operator()()
70  *   {
71  *     try { throw; }
72  *     catch (std::range_error e) // catch what types we know
73  *       { std::cerr << "caught " << e.what() << std::endl; }
74  *     return 1;
75  *   }
76  * }
77  * int foo(); // throws std::range_error
78  * sigc::exception_catch(&foo, my_catch())();
79  * @endcode
80  *
81  * The functor sigc::exception_catch() returns can be directly passed into
82  * sigc::signal::connect().
83  *
84  * @par Example:
85  * @code
86  * sigc::signal<int> some_signal;
87  * some_signal.connect(sigc::exception_catch(&foo, my_catch));
88  * @endcode
89  *
90  * @ingroup adaptors
91  */
92
93 template <class T_functor, class T_catcher, class T_return = typename adapts<T_functor>::result_type>
94 struct exception_catch_functor : public adapts<T_functor>
95 {
96   typedef typename adapts<T_functor>::adaptor_type adaptor_type;
97
98 #ifndef DOXYGEN_SHOULD_SKIP_THIS
99   template <LOOP(class T_arg%1=void, CALL_SIZE)>
100   struct deduce_result_type
101     { typedef typename adaptor_type::template deduce_result_type<LOOP(_P_(T_arg%1),CALL_SIZE)>::type type; };
102 #endif
103   typedef T_return result_type;
104
105   result_type
106   operator()();
107
108 FOR(1,CALL_SIZE,[[EXCEPTION_CATCH_OPERATOR(%1)]])dnl
109   exception_catch_functor(const T_functor& _A_func,
110                           const T_catcher& _A_catcher)
111     : adapts<T_functor>(_A_func), catcher_(_A_catcher)
112     {}
113
114   T_catcher catcher_;
115 };
116
117 template <class T_functor, class T_catcher, class T_return>
118 typename exception_catch_functor<T_functor, T_catcher, T_return>::result_type
119 exception_catch_functor<T_functor, T_catcher, T_return>::operator()()
120   {
121     try
122       { return this->functor_(); }
123     catch (...)
124       { return catcher_(); }
125   }
126
127 // void specialization
128 template <class T_functor, class T_catcher>
129 struct exception_catch_functor<T_functor, T_catcher, void> : public adapts<T_functor>
130 {
131   typedef void result_type;
132   typedef typename adapts<T_functor>::adaptor_type adaptor_type;
133
134 #ifndef DOXYGEN_SHOULD_SKIP_THIS
135   template <LOOP(class T_arg%1=void, CALL_SIZE)>
136   struct deduce_result_type
137     { typedef typename adaptor_type::template deduce_result_type<LOOP(_P_(T_arg%1),CALL_SIZE)>::type type; };
138 #endif
139
140   void
141   operator()();
142
143 FOR(1,CALL_SIZE,[[EXCEPTION_CATCH_OPERATOR(%1)]])dnl
144   exception_catch_functor() {}
145   exception_catch_functor(const T_functor& _A_func,
146                           const T_catcher& _A_catcher)
147     : adapts<T_functor>(_A_func), catcher_(_A_catcher)
148     {}
149   ~exception_catch_functor() {}
150
151     T_catcher catcher_;
152 };
153
154 template <class T_functor, class T_catcher>
155 void exception_catch_functor<T_functor, T_catcher, void>::operator()()
156   {
157     try
158       { this->functor_(); } // I don't understand why void return doesn't work here (Martin)
159     catch (...)
160       { this->catcher_(); }
161   }
162
163 #ifndef DOXYGEN_SHOULD_SKIP_THIS
164 //template specialization of visitor<>::do_visit_each<>(action, functor):
165 template <class T_functor, class T_catcher, class T_return>
166 struct visitor<exception_catch_functor<T_functor, T_catcher, T_return> >
167 {
168   template <typename T_action>
169   static void do_visit_each(const T_action& _A_action,
170                             const exception_catch_functor<T_functor, T_catcher, T_return>& _A_target)
171   {
172     sigc::visit_each(_A_action, _A_target.functor_);
173     sigc::visit_each(_A_action, _A_target.catcher_);
174   }
175 };
176 #endif // DOXYGEN_SHOULD_SKIP_THIS
177
178 template <class T_functor, class T_catcher>
179 inline exception_catch_functor<T_functor, T_catcher>
180 exception_catch(const T_functor& _A_func, const T_catcher& _A_catcher)
181   { return exception_catch_functor<T_functor, T_catcher>(_A_func, _A_catcher); }
182
183 } /* namespace sigc */