]> git.tdb.fi Git - ext/sigc++-2.0.git/blob - sigc++/adaptors/macros/adaptor_trait.h.m4
Import libsigc++ 2.10.8 sources
[ext/sigc++-2.0.git] / sigc++ / adaptors / macros / adaptor_trait.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 include(template.macros.m4)
19
20 dnl
21 dnl The idea here is simple.  To prevent the need to
22 dnl specializing every adaptor for every type of functor
23 dnl and worse non-functors like function pointers, we
24 dnl will make an adaptor trait which can take ordinary
25 dnl functors and make them adaptor functors for which
26 dnl we will of course be able to avoid excess copies.
27 dnl (in theory)
28 dnl
29 dnl this all depends on partial specialization to allow
30 dnl us to do
31 dnl   functor_.template operator() <types> (args);
32 dnl
33
34 dnl I don't understand much of the above. However, I can
35 dnl see that adaptors are implemented like they are because
36 dnl there is no way to extract the return type and the argument
37 dnl types from a functor type. Therefore, operator() is templated.
38 dnl It's instatiated in slot_call#<>::operator() where the
39 dnl argument types are known. The return type is finally determined
40 dnl via the callof<> template - a tricky way to detect the return
41 dnl type of a functor when the argument types are known. Martin.
42
43 ])
44 define([ADAPTOR_DO],[dnl
45 ifelse($1,0,[dnl
46 dnl  typename internal::callof_safe0<T_functor>::result_type // doesn't compile if T_functor has an overloaded operator()!
47 dnl  typename functor_trait<T_functor>::result_type
48 dnl  operator()() const
49 dnl    { return functor_(); }
50 ],[dnl
51   /** Invokes the wrapped functor passing on the arguments.dnl
52 FOR(1, $1,[
53    * @param _A_arg%1 Argument to be passed on to the functor.])
54    * @return The return value of the functor invocation.
55    */
56   template <LOOP([class T_arg%1], $1)>
57   typename deduce_result_type<LOOP(T_arg%1, $1)>::type
58   operator()(LOOP(T_arg%1 _A_arg%1, $1)) const
59     { return functor_(LOOP(_A_arg%1, $1)); }
60
61   #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD
62   template <LOOP([class T_arg%1], $1)>
63   typename deduce_result_type<LOOP(T_arg%1, $1)>::type
64   sun_forte_workaround(LOOP(T_arg%1 _A_arg%1, $1)) const
65     { //Just calling operator() tries to copy the argument:
66       return functor_(LOOP(_A_arg%1, $1));
67     }
68   #endif
69
70 ])dnl
71 ])
72
73 divert(0)dnl
74 _FIREWALL([ADAPTORS_ADAPTOR_TRAIT])
75 #include <sigc++config.h> //To get SIGC_TEMPLATE_KEYWORD_OPERATOR_OVERLOAD
76 #include <sigc++/visit_each.h>
77 #include <sigc++/functors/functor_trait.h>
78 #include <sigc++/functors/ptr_fun.h>
79 #include <sigc++/functors/mem_fun.h>
80 #include <sigc++/adaptors/deduce_result_type.h>
81
82 namespace sigc {
83
84 // Call either operator()<>() or sun_forte_workaround<>(),
85 // depending on the compiler:
86 #ifdef SIGC_GCC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD
87   #define SIGC_WORKAROUND_OPERATOR_PARENTHESES template operator()
88   #define SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD
89 #else
90   #ifdef SIGC_MSVC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD
91     #define SIGC_WORKAROUND_OPERATOR_PARENTHESES operator()
92     #define SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD
93   #else
94     #define SIGC_WORKAROUND_OPERATOR_PARENTHESES sun_forte_workaround
95   #endif
96 #endif
97
98
99 #ifndef DOXYGEN_SHOULD_SKIP_THIS
100 template <class T_functor> struct adapts;
101 #endif
102
103 /** @defgroup adaptors Adaptors
104  * Adaptors are functors that alter the signature of a functor's
105  * operator()().
106  *
107  * The adaptor types libsigc++ provides
108  * are created with bind(), bind_return(), hide(), hide_return(),
109  * retype_return(), retype(), compose(), exception_catch(), track_obj()
110  * and group().
111  *
112  * You can easily derive your own adaptor type from sigc::adapts.
113  */
114
115 /** Converts an arbitrary functor into an adaptor type.
116  * All adaptor types in libsigc++ have
117  * a <tt>template operator()</tt> member of every argument count
118  * they support. These functions in turn invoke a stored adaptor's
119  * <tt>template operator()</tt>, processing the arguments and return
120  * value in a characteristic manner. Explicit function template
121  * instantiation is used to pass type hints thus saving copy costs.
122  *
123  * adaptor_functor is a glue between adaptors and arbitrary functors
124  * that just passes on the arguments. You won't use this type directly.
125  *
126  * The template argument @e T_functor determines the type of stored
127  * functor.
128  *
129  * @ingroup adaptors
130  */
131 template <class T_functor>
132 struct adaptor_functor : public adaptor_base
133 {
134 #ifndef DOXYGEN_SHOULD_SKIP_THIS
135   template <LOOP(class T_arg%1=void, CALL_SIZE)>
136   struct deduce_result_type
137     { typedef sigc::deduce_result_t<LIST(T_functor, LOOP(T_arg%1,CALL_SIZE))> type; };
138 #endif
139   typedef typename functor_trait<T_functor>::result_type result_type;
140
141   /** Invokes the wrapped functor passing on the arguments.
142    * @return The return value of the functor invocation.
143    */
144   result_type
145   operator()() const;
146
147   #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD
148   result_type sun_forte_workaround() const
149     { return operator(); }
150   #endif
151
152 FOR(0,CALL_SIZE,[[ADAPTOR_DO(%1)]])dnl
153   /// Constructs an invalid functor.
154   adaptor_functor()
155     {}
156
157   /** Constructs an adaptor_functor object that wraps the passed functor.
158    * @param _A_functor Functor to invoke from operator()().
159    */
160   explicit adaptor_functor(const T_functor& _A_functor)
161     : functor_(_A_functor)
162     {}
163
164   /** Constructs an adaptor_functor object that wraps the passed (member)
165    * function pointer.
166    * @param _A_type Pointer to function or class method to invoke from operator()().
167    */
168   template <class T_type>
169   explicit adaptor_functor(const T_type& _A_type)
170     : functor_(_A_type)
171     {}
172
173   /// Functor that is invoked from operator()().
174   mutable T_functor functor_;
175 };
176
177 template <class T_functor>
178 typename adaptor_functor<T_functor>::result_type
179 adaptor_functor<T_functor>::operator()() const
180   { return functor_(); }
181
182 #ifndef DOXYGEN_SHOULD_SKIP_THIS
183 //template specialization of visitor<>::do_visit_each<>(action, functor):
184 /** Performs a functor on each of the targets of a functor.
185  * The function overload for sigc::adaptor_functor performs a functor
186  * on the functor stored in the sigc::adaptor_functor object.
187  *
188  * @ingroup adaptors
189  */
190 template <class T_functor>
191 struct visitor<adaptor_functor<T_functor> >
192 {
193   template <class T_action>
194   static void do_visit_each(const T_action& _A_action,
195                             const adaptor_functor<T_functor>& _A_target)
196   {
197     sigc::visit_each(_A_action, _A_target.functor_);
198   }
199 };
200 #endif // DOXYGEN_SHOULD_SKIP_THIS
201
202 /** Trait that specifies what is the adaptor version of a functor type.
203  * Template specializations for sigc::adaptor_base derived functors,
204  * for function pointers and for class methods are provided.
205  *
206  * The template argument @e T_functor is the functor type to convert.
207  * @e I_isadaptor indicates whether @e T_functor inherits from sigc::adaptor_base.
208  *
209  * @ingroup adaptors
210  */
211 #ifndef DOXYGEN_SHOULD_SKIP_THIS
212 template <class T_functor, bool I_isadaptor = std::is_base_of<adaptor_base, T_functor>::value> struct adaptor_trait;
213 #else
214 template <class T_functor, bool I_isadaptor = std::is_base_of<adaptor_base, T_functor>::value> struct adaptor_trait {};
215 #endif
216
217 /** Trait that specifies what is the adaptor version of a functor type.
218  * This template specialization is used for types that inherit from adaptor_base.
219  * adaptor_type is equal to @p T_functor in this case.
220  */
221 template <class T_functor>
222 struct adaptor_trait<T_functor, true>
223 {
224   typedef typename T_functor::result_type result_type;
225   typedef T_functor functor_type;
226   typedef T_functor adaptor_type;
227 };
228
229 /** Trait that specifies what is the adaptor version of a functor type.
230  * This template specialization is used for arbitrary functors,
231  * for function pointers and for class methods are provided.
232  * The latter are converted into @p pointer_functor or @p mem_functor types.
233  * adaptor_type is equal to @p adaptor_functor<functor_type>.
234  */
235 template <class T_functor>
236 struct adaptor_trait<T_functor, false>
237 {
238   typedef typename functor_trait<T_functor>::result_type result_type;
239   typedef typename functor_trait<T_functor>::functor_type functor_type;
240   typedef adaptor_functor<functor_type> adaptor_type;
241 };
242
243 // Doxygen (at least version 1.8.4) removes blank lines in a code block.
244 // That's why there are empty comment lines in the following code block.
245 /** Base type for adaptors.
246  * sigc::adapts wraps adaptors, functors, function pointers and class methods.
247  * It contains a single member functor which is always a sigc::adaptor_base.
248  * The typedef adaptor_type defines the exact type that is used
249  * to store the adaptor, functor, function pointer or class method passed
250  * into the constructor. It differs from @a T_functor unless @a T_functor
251  * inherits from sigc::adaptor_base.
252  *
253  * @par Example of a simple adaptor:
254  * @code
255  * namespace my_ns
256  * {
257  * template <class T_functor>
258  * struct my_adaptor : public sigc::adapts<T_functor>
259  * {
260  *   template <class T_arg1=void, class T_arg2=void>
261  *   struct deduce_result_type
262  *   { typedef sigc::deduce_result_t<T_functor, T_arg1, T_arg2> type; };
263  *   typedef typename sigc::functor_trait<T_functor>::result_type result_type;
264  *   //
265  *   result_type
266  *   operator()() const;
267  *   //
268  *   template <class T_arg1>
269  *   typename deduce_result_type<T_arg1>::type
270  *   operator()(T_arg1 _A_arg1) const;
271  *   //
272  *   template <class T_arg1, class T_arg2>
273  *   typename deduce_result_type<T_arg1, T_arg2>::type
274  *   operator()(T_arg1 _A_arg1, T_arg2 _A_arg2) const;
275  *   //
276  *   // Constructs a my_adaptor object that wraps the passed functor.
277  *   // Initializes adapts<T_functor>::functor_, which is invoked from operator()().
278  *   explicit my_adaptor(const T_functor& _A_functor)
279  *     : sigc::adapts<T_functor>(_A_functor) {}
280  * };
281  * } // end namespace my_ns
282  * //
283  * // Specialization of sigc::visitor for my_adaptor.
284  * namespace sigc
285  * {
286  * template <class T_functor>
287  * struct visitor<my_ns::my_adaptor<T_functor> >
288  * {
289  *   template <class T_action>
290  *   static void do_visit_each(const T_action& _A_action,
291  *                             const my_ns::my_adaptor<T_functor>& _A_target)
292  *   {
293  *     sigc::visit_each(_A_action, _A_target.functor_);
294  *   }
295  * };
296  * } // end namespace sigc
297  * @endcode
298  *
299  * If you implement your own adaptor, you must also provide your specialization
300  * of sigc::visitor<>::do_visit_each<>() that will forward the call to the functor(s)
301  * your adapter is wrapping. Otherwise, pointers stored within the functor won't be
302  * invalidated when a sigc::trackable object is destroyed and you can end up
303  * executing callbacks on destroyed objects.
304  *
305  * Your specialization of sigc::visitor<> must be in namespace sigc.
306  *
307  * @ingroup adaptors
308  */
309 template <class T_functor>
310 struct adapts : public adaptor_base
311 {
312   typedef typename adaptor_trait<T_functor>::result_type  result_type;
313   typedef typename adaptor_trait<T_functor>::adaptor_type adaptor_type;
314
315   /** Constructs an adaptor that wraps the passed functor.
316    * @param _A_functor Functor to invoke from operator()().
317    */
318   explicit adapts(const T_functor& _A_functor)
319     : functor_(_A_functor)
320     {}
321
322   /// Adaptor that is invoked from operator()().
323   mutable adaptor_type functor_;
324 };
325
326 } /* namespace sigc */