1 #ifndef _SIGC_FUNCTORS_FUNCTOR_TRAIT_H_
2 #define _SIGC_FUNCTORS_FUNCTOR_TRAIT_H_
3 #include <sigc++/functors/functor_base.h>
4 #include <sigc++/functors/mem_fun.h>
5 #include <sigc++/functors/ptr_fun.h>
6 #include <sigc++/type_traits.h>
11 /** @defgroup sigcfunctors Functors
12 * Functors are copyable types that define operator()().
14 * Types that define operator()() overloads with different return types are referred to
15 * as multi-type functors. Multi-type functors are only partially supported in libsigc++.
17 * Closures are functors that store all information needed to invoke a callback from operator()().
19 * Adaptors are functors that alter the signature of a functor's operator()().
21 * libsigc++ defines numerous functors, closures and adaptors.
22 * Since libsigc++ is a callback library, most functors are also closures.
23 * The documentation doesn't distinguish between functors and closures.
25 * The basic functor types libsigc++ provides are created with ptr_fun() and mem_fun()
26 * and can be converted into slots implicitly.
27 * The set of adaptors that ships with libsigc++ is documented in the @ref adaptors module.
29 * If you want to mix user-defined and third party functors with libsigc++,
30 * and you want them to be implicitly convertible into slots, libsigc++ must know
31 * the result type of your functors. There are different ways to achieve that.
33 * - Derive your functors from sigc::functor_base and place
34 * <tt>using result_type = T_return;</tt> in the class definition.
35 * - Use the macro SIGC_FUNCTOR_TRAIT(T_functor,T_return) in namespace sigc.
36 * Multi-type functors are only partly supported.
37 * - For functors not derived from sigc::functor_base, and not specified with
38 * SIGC_FUNCTOR_TRAIT(), libsigc++ tries to deduce the result type with the
39 * C++11 decltype() specifier. That attempt usually succeeds if the functor
40 * has a single operator()(), but it fails if operator()() is overloaded.
41 * - Use the macro #SIGC_FUNCTORS_HAVE_RESULT_TYPE, if you want libsigc++ to assume
42 * that result_type is defined in all user-defined or third party functors,
43 * whose result type can't be deduced in any other way.
45 * If all these ways to deduce the result type fail, void is assumed.
47 * With libsigc++ versions before 2.6, the macro
48 * #SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE activated the test with
49 * decltype(). That macro is now unneccesary and deprecated.
52 /** Helper class, to determine if decltype() can deduce the result type of a functor.
54 * @ingroup sigcfunctors
56 template <typename T_functor>
57 class can_deduce_result_type_with_decltype
68 static biggerthanint checksize(...);
70 // If decltype(&X_functor::operator()) can't be evaluated, this checksize() overload
71 // is ignored because of the SFINAE rule (Substitution Failure Is Not An Error).
72 template <typename X_functor>
73 static int checksize(X_functor* obj, decltype(&X_functor::operator()) p = nullptr);
76 static const bool value
77 #ifndef DOXYGEN_SHOULD_SKIP_THIS
78 = sizeof(checksize(static_cast<T_functor*>(nullptr))) == sizeof(int)
84 /** Trait that specifies the return type of any type.
85 * Template specializations for functors derived from sigc::functor_base,
86 * for other functors whose result type can be deduced with decltype(),
87 * for function pointers and for class methods are provided.
89 * @tparam T_functor Functor type.
90 * @tparam I_derives_functor_base Whether @p T_functor inherits from sigc::functor_base.
91 * @tparam I_can_use_decltype Whether the result type of @p T_functor can be deduced
94 * @ingroup sigcfunctors
96 template <class T_functor,
97 bool I_derives_functor_base = std::is_base_of<functor_base,T_functor>::value,
98 bool I_can_use_decltype = can_deduce_result_type_with_decltype<T_functor>::value>
101 using result_type = void;
102 using functor_type = T_functor;
105 #ifndef DOXYGEN_SHOULD_SKIP_THIS
106 template <class T_functor, bool I_can_use_decltype>
107 struct functor_trait<T_functor, true, I_can_use_decltype>
109 using result_type = typename T_functor::result_type;
110 using functor_type = T_functor;
113 template <typename T_functor>
114 struct functor_trait<T_functor, false, true>
116 using result_type = typename functor_trait<decltype(&T_functor::operator()), false, false>::result_type;
117 using functor_type = T_functor;
119 #endif // DOXYGEN_SHOULD_SKIP_THIS
121 /** Helper macro, if you want to mix user-defined and third party functors with libsigc++.
123 * If you want to mix functors not derived from sigc::functor_base with libsigc++, and
124 * these functors define @p result_type, use this macro inside namespace sigc like so:
126 * namespace sigc { SIGC_FUNCTORS_HAVE_RESULT_TYPE }
129 * @ingroup sigcfunctors
131 #define SIGC_FUNCTORS_HAVE_RESULT_TYPE \
132 template <class T_functor> \
133 struct functor_trait<T_functor, false, false> \
135 using result_type = typename T_functor::result_type; \
136 using functor_type = T_functor; \
139 /** Helper macro, if you want to mix user-defined and third party functors with libsigc++.
141 * If you want to mix functors not derived from sigc::functor_base with libsigc++, and
142 * these functors don't define @p result_type, use this macro inside namespace sigc
143 * to expose the return type of the functors like so:
146 * SIGC_FUNCTOR_TRAIT(first_functor_type, return_type_of_first_functor_type)
147 * SIGC_FUNCTOR_TRAIT(second_functor_type, return_type_of_second_functor_type)
152 * @ingroup sigcfunctors
154 #define SIGC_FUNCTOR_TRAIT(T_functor,T_return) \
156 struct functor_trait<T_functor, false, false> \
158 using result_type = T_return; \
159 using functor_type = T_functor; \
162 struct functor_trait<T_functor, false, true> \
164 using result_type = T_return; \
165 using functor_type = T_functor; \
168 #ifndef SIGCXX_DISABLE_DEPRECATED
169 /** Helper macro, if you want to mix user-defined and third party functors with libsigc++.
171 * If you want to mix functors not derived from sigc::functor_base with libsigc++,
172 * and your compiler can deduce the result type of the functor with the C++11
173 * keyword <tt>decltype</tt>, use this macro inside namespace sigc like so:
176 * SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
180 * Functors with overloaded operator()() are not supported.
184 * @deprecated This macro does nothing. The test it activated in libsigc++
185 * versions before 2.6, is now unconditionally activated.
187 * @ingroup sigcfunctors
189 #define SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE // Empty
190 #endif // SIGCXX_DISABLE_DEPRECATED
192 #ifndef DOXYGEN_SHOULD_SKIP_THIS
193 // detect the return type and the functor version of non-functor types.
197 template <class T_return, class... T_arg>
198 struct functor_trait<T_return (*)(T_arg...), false, false>
200 using result_type = T_return;
201 using functor_type = pointer_functor<T_return(T_arg...)>;
207 template <class T_return, class T_obj, class... T_arg>
208 struct functor_trait<T_return (T_obj::*)(T_arg...), false, false>
210 using result_type = T_return;
211 using functor_type = mem_functor<
212 T_return (T_obj::*)(T_arg...),
216 template <class T_return, class T_obj, class... T_arg>
217 struct functor_trait<T_return (T_obj::*)(T_arg...) const, false, false>
219 using result_type = T_return;
220 using functor_type = mem_functor<
221 T_return (T_obj::*)(T_arg...) const,
225 #endif // DOXYGEN_SHOULD_SKIP_THIS
227 } /* namespace sigc */
228 #endif /* _SIGC_FUNCTORS_FUNCTOR_TRAIT_H_ */