]> git.tdb.fi Git - ext/sigc++-2.0.git/blob - sigc++/functors/macros/functor_trait.h.m4
Import libsigc++ 2.10.8 sources
[ext/sigc++-2.0.git] / sigc++ / functors / macros / functor_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 define([FUNCTOR_PTR_FUN],[dnl
21 template <LIST(LOOP(class T_arg%1, $1), class T_return)> class pointer_functor$1;
22 template <LIST(LOOP(class T_arg%1, $1), class T_return)>
23 struct functor_trait<T_return (*)(LOOP(T_arg%1, $1)), false, false>
24 {
25   typedef T_return result_type;
26   typedef pointer_functor$1<LIST(LOOP(T_arg%1, $1), T_return)> functor_type;
27 };
28
29 ])
30 define([FUNCTOR_MEM_FUN],[dnl
31 template <LIST(class T_return, class T_obj, LOOP(class T_arg%1, $1))> class mem_functor$1;
32 template <LIST(class T_return, class T_obj, LOOP(class T_arg%1, $1))> class const_mem_functor$1;
33 template <LIST(LOOP(class T_arg%1, $1), class T_return, class T_obj)>
34 struct functor_trait<T_return (T_obj::*)(LOOP(T_arg%1, $1)), false, false>
35 {
36   typedef T_return result_type;
37   typedef mem_functor$1<LIST(T_return, T_obj, LOOP(T_arg%1, $1))> functor_type;
38 };
39 template <LIST(LOOP(class T_arg%1, $1), class T_return, class T_obj)>
40 struct functor_trait<T_return (T_obj::*)(LOOP(T_arg%1, $1)) const, false, false>
41 {
42   typedef T_return result_type;
43   typedef const_mem_functor$1<LIST(T_return, T_obj, LOOP(T_arg%1, $1))> functor_type;
44 };
45
46 ])
47
48 divert(0)dnl
49 _FIREWALL([FUNCTORS_FUNCTOR_TRAIT])
50 #include <sigc++/type_traits.h>
51 #include <type_traits>
52
53 namespace sigc {
54
55 //TODO: When we can break ABI, replace nil by something else, such as sigc_nil.
56 // nil is a keyword in Objective C++. When gcc is used for compiling Objective C++
57 // programs, nil is defined as a preprocessor macro.
58 // https://bugzilla.gnome.org/show_bug.cgi?id=695235
59 #if defined(nil) && defined(SIGC_PRAGMA_PUSH_POP_MACRO)
60   #define SIGC_NIL_HAS_BEEN_PUSHED 1
61   #pragma push_macro("nil")
62   #undef nil
63 #endif
64
65 /** nil struct type.
66  * The nil struct type is used as default template argument in the
67  * unnumbered sigc::signal and sigc::slot templates.
68  *
69  * @ingroup signal
70  * @ingroup slot
71  */
72 #ifndef DOXYGEN_SHOULD_SKIP_THIS
73 struct nil;
74 #else
75 struct nil {};
76 #endif
77
78 #ifdef SIGC_NIL_HAS_BEEN_PUSHED
79   #undef SIGC_NIL_HAS_BEEN_PUSHED
80   #pragma pop_macro("nil")
81 #endif
82
83 /** @defgroup sigcfunctors Functors
84  * Functors are copyable types that define operator()().
85  *
86  * Types that define operator()() overloads with different return types are referred to
87  * as multi-type functors. Multi-type functors are only partially supported in libsigc++.
88  *
89  * Closures are functors that store all information needed to invoke a callback from operator()().
90  *
91  * Adaptors are functors that alter the signature of a functor's operator()().
92  *
93  * libsigc++ defines numerous functors, closures and adaptors.
94  * Since libsigc++ is a callback library, most functors are also closures.
95  * The documentation doesn't distinguish between functors and closures.
96  *
97  * The basic functor types libsigc++ provides are created with ptr_fun() and mem_fun()
98  * and can be converted into slots implicitly.
99  * The set of adaptors that ships with libsigc++ is documented in the @ref adaptors module.
100  *
101  * If you want to mix user-defined and third party functors with libsigc++,
102  * and you want them to be implicitly convertible into slots, libsigc++ must know
103  * the result type of your functors. There are different ways to achieve that.
104  *
105  * - Derive your functors from sigc::functor_base and place
106  *   <tt>typedef T_return result_type;</tt> in the class definition.
107  * - Use the macro SIGC_FUNCTOR_TRAIT(T_functor,T_return) in namespace sigc.
108  *   Multi-type functors are only partly supported.
109  * - For functors not derived from sigc::functor_base, and not specified with
110  *   SIGC_FUNCTOR_TRAIT(), libsigc++ tries to deduce the result type with the
111  *   C++11 decltype() specifier. That attempt usually succeeds if the functor
112  *   has a single operator()(), but it fails if operator()() is overloaded.
113  * - Use the macro #SIGC_FUNCTORS_HAVE_RESULT_TYPE, if you want libsigc++ to assume
114  *   that result_type is defined in all user-defined or third party functors,
115  *   whose result type can't be deduced in any other way.
116  *
117  * If all these ways to deduce the result type fail, void is assumed.
118  *
119  * With libsigc++ versions before 2.6, the macro 
120  * #SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE activated the test with
121  * decltype(). That macro is now unneccesary and deprecated.
122  */
123
124 /** A hint to the compiler.
125  * All functors which define @p result_type should publically inherit from this hint.
126  *
127  * @ingroup sigcfunctors
128  */
129 struct functor_base {};
130
131 /** Helper class, to determine if decltype() can deduce the result type of a functor.
132  *
133  * @ingroup sigcfunctors
134  */
135 template <typename T_functor>
136 class can_deduce_result_type_with_decltype
137 {
138 private:
139   struct biggerthanint
140   {
141     int memory1;
142     int memory2;
143     int memory3;
144     int memory4;
145   };
146
147   static biggerthanint checksize(...);
148
149   // If decltype(&X_functor::operator()) can't be evaluated, this checksize() overload
150   // is ignored because of the SFINAE rule (Substitution Failure Is Not An Error).
151   template <typename X_functor>
152   static int checksize(X_functor* obj, decltype(&X_functor::operator()) p = nullptr);
153
154 public:
155   static const bool value
156 #ifndef DOXYGEN_SHOULD_SKIP_THIS
157     = sizeof(checksize(static_cast<T_functor*>(nullptr))) == sizeof(int)
158 #endif
159     ;
160 };
161
162
163 /** Trait that specifies the return type of any type.
164  * Template specializations for functors derived from sigc::functor_base,
165  * for other functors whose result type can be deduced with decltype(),
166  * for function pointers and for class methods are provided.
167  *
168  * @tparam T_functor Functor type.
169  * @tparam I_derives_functor_base Whether @p T_functor inherits from sigc::functor_base.
170  * @tparam I_can_use_decltype Whether the result type of @p T_functor can be deduced
171  *                            with decltype().
172  *
173  * @ingroup sigcfunctors
174  */
175 template <class T_functor,
176           bool I_derives_functor_base = std::is_base_of<functor_base,T_functor>::value,
177           bool I_can_use_decltype = can_deduce_result_type_with_decltype<T_functor>::value>
178 struct functor_trait
179 {
180   typedef void result_type;
181   typedef T_functor functor_type;
182 };
183
184 #ifndef DOXYGEN_SHOULD_SKIP_THIS
185 template <class T_functor, bool I_can_use_decltype>
186 struct functor_trait<T_functor, true, I_can_use_decltype>
187 {
188   typedef typename T_functor::result_type result_type;
189   typedef T_functor functor_type;
190 };
191
192 template <typename T_functor>
193 struct functor_trait<T_functor, false, true>
194 {
195   typedef typename functor_trait<decltype(&T_functor::operator()), false, false>::result_type result_type;
196   typedef T_functor functor_type;
197 };
198 #endif // DOXYGEN_SHOULD_SKIP_THIS
199
200 /** Helper macro, if you want to mix user-defined and third party functors with libsigc++.
201  *
202  * If you want to mix functors not derived from sigc::functor_base with libsigc++, and
203  * these functors define @p result_type, use this macro inside namespace sigc like so:
204  * @code
205  * namespace sigc { SIGC_FUNCTORS_HAVE_RESULT_TYPE }
206  * @endcode
207  *
208  * @ingroup sigcfunctors
209  */
210 #define SIGC_FUNCTORS_HAVE_RESULT_TYPE                 \
211 template <class T_functor>                             \
212 struct functor_trait<T_functor, false, false>          \
213 {                                                      \
214   typedef typename T_functor::result_type result_type; \
215   typedef T_functor functor_type;                      \
216 };
217
218 /** Helper macro, if you want to mix user-defined and third party functors with libsigc++.
219  *
220  * If you want to mix functors not derived from sigc::functor_base with libsigc++, and
221  * these functors don't define @p result_type, use this macro inside namespace sigc
222  * to expose the return type of the functors like so:
223  * @code
224  * namespace sigc {
225  *   SIGC_FUNCTOR_TRAIT(first_functor_type, return_type_of_first_functor_type)
226  *   SIGC_FUNCTOR_TRAIT(second_functor_type, return_type_of_second_functor_type)
227  *   ...
228  * }
229  * @endcode
230  *
231  * @ingroup sigcfunctors
232  */
233 #define SIGC_FUNCTOR_TRAIT(T_functor,T_return) \
234 template <>                                    \
235 struct functor_trait<T_functor, false, false>  \
236 {                                              \
237   typedef T_return result_type;                \
238   typedef T_functor functor_type;              \
239 };                                             \
240 template <>                                    \
241 struct functor_trait<T_functor, false, true>   \
242 {                                              \
243   typedef T_return result_type;                \
244   typedef T_functor functor_type;              \
245 };
246
247 #ifndef SIGCXX_DISABLE_DEPRECATED
248 /** Helper macro, if you want to mix user-defined and third party functors with libsigc++.
249  *
250  * If you want to mix functors not derived from sigc::functor_base with libsigc++,
251  * and your compiler can deduce the result type of the functor with the C++11
252  * keyword <tt>decltype</tt>, use this macro inside namespace sigc like so:
253  * @code
254  * namespace sigc {
255  *   SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
256  * }
257  * @endcode
258  *
259  * Functors with overloaded operator()() are not supported.
260  *
261  * @newin{2,2,11}
262  *
263  * @deprecated This macro does nothing. The test it activated in libsigc++
264  *             versions before 2.6, is now unconditionally activated.
265  *
266  * @ingroup sigcfunctors
267  */
268 #define SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE // Empty
269 #endif // SIGCXX_DISABLE_DEPRECATED
270
271 #ifndef DOXYGEN_SHOULD_SKIP_THIS
272 // detect the return type and the functor version of non-functor types.
273 FOR(0,CALL_SIZE,[[FUNCTOR_PTR_FUN(%1)]])
274 FOR(0,CALL_SIZE,[[FUNCTOR_MEM_FUN(%1)]])
275 #endif // DOXYGEN_SHOULD_SKIP_THIS
276
277 } /* namespace sigc */