remove \r
[extl.git] / extl / functional / func_ptr.h
blob15cb96b327b3cb0c5ae1cf8b26b6ecbed9b72ef8
1 /* ///////////////////////////////////////////////////////////////////////
2 * File: func_ptr.h
4 * Created: 08.06.09
5 * Updated: 08.07.18
7 * Brief: func_ptr class
9 * [<Home>]
10 * Copyright (c) 2008-2020, Waruqi All rights reserved.
11 * //////////////////////////////////////////////////////////////////// */
13 #ifndef EXTL_FUNCTIONAL_FUNC_PTR_H
14 #define EXTL_FUNCTIONAL_FUNC_PTR_H
16 /*!\file func_ptr.h
17 * \brief func_ptr class
19 #ifndef __cplusplus
20 # error func_ptr.h need be supported by c++.
21 #endif
23 /* ///////////////////////////////////////////////////////////////////////
24 * Includes
26 #include "prefix.h"
27 #include "../type/traits/func_ptr_traits.h"
28 #include "../type/traits/is_void.h"
29 #include "../algorithm/algorithm.h"
30 #include "../utility/operator_bool.h"
32 #ifdef EXTL_TYPE_TRAITS_CALL_TRAITS_SUPPORT
33 # include "../type/traits/call_traits.h"
34 #endif
36 /* ///////////////////////////////////////////////////////////////////////
37 * Compatibility
39 #if !defined(EXTL_FUNCTIONAL_FUNC_PTR_SUPPORT)
40 # error extl::func_ptr is not supported by current compiler.
41 #endif
42 /* ///////////////////////////////////////////////////////////////////////
43 * Macros
45 #define EXTL_FUNC_PTR_PARAM_TYPE(T) typename_type_k call_traits<T>::param_type
47 #define EXTL_FUNC_PTR_OPERATOR_0
49 #define EXTL_FUNC_PTR_OPERATOR_1 \
50 EXTL_FUNC_PTR_PARAM_TYPE(param1_type) a1
52 #define EXTL_FUNC_PTR_OPERATOR_2 \
53 EXTL_FUNC_PTR_PARAM_TYPE(param1_type) a1 \
54 , EXTL_FUNC_PTR_PARAM_TYPE(param2_type) a2
56 #define EXTL_FUNC_PTR_OPERATOR_3 \
57 EXTL_FUNC_PTR_PARAM_TYPE(param1_type) a1 \
58 , EXTL_FUNC_PTR_PARAM_TYPE(param2_type) a2 \
59 , EXTL_FUNC_PTR_PARAM_TYPE(param3_type) a3
61 #define EXTL_FUNC_PTR_OPERATOR_4 \
62 EXTL_FUNC_PTR_PARAM_TYPE(param1_type) a1 \
63 , EXTL_FUNC_PTR_PARAM_TYPE(param2_type) a2 \
64 , EXTL_FUNC_PTR_PARAM_TYPE(param3_type) a3 \
65 , EXTL_FUNC_PTR_PARAM_TYPE(param4_type) a4
67 #define EXTL_FUNC_PTR_OPERATOR_5 \
68 EXTL_FUNC_PTR_PARAM_TYPE(param1_type) a1 \
69 , EXTL_FUNC_PTR_PARAM_TYPE(param2_type) a2 \
70 , EXTL_FUNC_PTR_PARAM_TYPE(param3_type) a3 \
71 , EXTL_FUNC_PTR_PARAM_TYPE(param4_type) a4 \
72 , EXTL_FUNC_PTR_PARAM_TYPE(param5_type) a5
74 #define EXTL_FUNC_PTR_OPERATOR_6 \
75 EXTL_FUNC_PTR_PARAM_TYPE(param1_type) a1 \
76 , EXTL_FUNC_PTR_PARAM_TYPE(param2_type) a2 \
77 , EXTL_FUNC_PTR_PARAM_TYPE(param3_type) a3 \
78 , EXTL_FUNC_PTR_PARAM_TYPE(param4_type) a4 \
79 , EXTL_FUNC_PTR_PARAM_TYPE(param5_type) a5 \
80 , EXTL_FUNC_PTR_PARAM_TYPE(param6_type) a6
82 #define EXTL_FUNC_PTR_OPERATOR_7 \
83 EXTL_FUNC_PTR_PARAM_TYPE(param1_type) a1 \
84 , EXTL_FUNC_PTR_PARAM_TYPE(param2_type) a2 \
85 , EXTL_FUNC_PTR_PARAM_TYPE(param3_type) a3 \
86 , EXTL_FUNC_PTR_PARAM_TYPE(param4_type) a4 \
87 , EXTL_FUNC_PTR_PARAM_TYPE(param5_type) a5 \
88 , EXTL_FUNC_PTR_PARAM_TYPE(param6_type) a6 \
89 , EXTL_FUNC_PTR_PARAM_TYPE(param7_type) a7
91 #define EXTL_FUNC_PTR_OPERATOR_8 \
92 EXTL_FUNC_PTR_PARAM_TYPE(param1_type) a1 \
93 , EXTL_FUNC_PTR_PARAM_TYPE(param2_type) a2 \
94 , EXTL_FUNC_PTR_PARAM_TYPE(param3_type) a3 \
95 , EXTL_FUNC_PTR_PARAM_TYPE(param4_type) a4 \
96 , EXTL_FUNC_PTR_PARAM_TYPE(param5_type) a5 \
97 , EXTL_FUNC_PTR_PARAM_TYPE(param6_type) a6 \
98 , EXTL_FUNC_PTR_PARAM_TYPE(param7_type) a7 \
99 , EXTL_FUNC_PTR_PARAM_TYPE(param8_type) a8
101 #define EXTL_FUNC_PTR_OPERATOR_9 \
102 EXTL_FUNC_PTR_PARAM_TYPE(param1_type) a1 \
103 , EXTL_FUNC_PTR_PARAM_TYPE(param2_type) a2 \
104 , EXTL_FUNC_PTR_PARAM_TYPE(param3_type) a3 \
105 , EXTL_FUNC_PTR_PARAM_TYPE(param4_type) a4 \
106 , EXTL_FUNC_PTR_PARAM_TYPE(param5_type) a5 \
107 , EXTL_FUNC_PTR_PARAM_TYPE(param6_type) a6 \
108 , EXTL_FUNC_PTR_PARAM_TYPE(param7_type) a7 \
109 , EXTL_FUNC_PTR_PARAM_TYPE(param8_type) a8 \
110 , EXTL_FUNC_PTR_PARAM_TYPE(param9_type) a9
112 #define EXTL_FUNC_PTR_OPERATOR_PARAM_0
113 #define EXTL_FUNC_PTR_OPERATOR_PARAM_1 a1
114 #define EXTL_FUNC_PTR_OPERATOR_PARAM_2 a1, a2
115 #define EXTL_FUNC_PTR_OPERATOR_PARAM_3 a1, a2, a3
116 #define EXTL_FUNC_PTR_OPERATOR_PARAM_4 a1, a2, a3, a4
117 #define EXTL_FUNC_PTR_OPERATOR_PARAM_5 a1, a2, a3, a4, a5
118 #define EXTL_FUNC_PTR_OPERATOR_PARAM_6 a1, a2, a3, a4, a5, a6
119 #define EXTL_FUNC_PTR_OPERATOR_PARAM_7 a1, a2, a3, a4, a5, a6, a7
120 #define EXTL_FUNC_PTR_OPERATOR_PARAM_8 a1, a2, a3, a4, a5, a6, a7, a8
121 #define EXTL_FUNC_PTR_OPERATOR_PARAM_9 a1, a2, a3, a4, a5, a6, a7, a8, a9
123 #define EXTL_FUNC_PTR_OPERATION_IMPL(num) \
124 return_type operator()(EXTL_FUNC_PTR_OPERATOR_##num) \
126 EXTL_ASSERT(!get_derive().is_empty()); \
127 return (*(get_derive().get_ptr()))(EXTL_FUNC_PTR_OPERATOR_PARAM_##num); \
130 #define EXTL_FUNC_PTR_VOID_RET_OPERATION_IMPL(num) \
131 return_type operator()(EXTL_FUNC_PTR_OPERATOR_##num) \
133 EXTL_ASSERT(!get_derive().is_empty()); \
134 (*(get_derive().get_ptr()))(EXTL_FUNC_PTR_OPERATOR_PARAM_##num); \
137 #define EXTL_FUNC_PTR_IMPL_SPEC_(is_void_return, operation_impl, param_num) \
138 EXTL_TEMPLATE_SPECIALISATION \
139 class func_ptr_impl<is_void_return, param_num> \
141 public: \
142 template<typename_param_k D, typename_param_k FP> \
143 class result \
145 public: \
146 typedef D derived_type; \
147 typedef result class_type; \
148 typedef FP func_ptr_type; \
149 typedef func_ptr_traits<func_ptr_type> func_ptr_traits_type; \
151 public: \
152 typedef typename_type_k func_ptr_traits_type::return_type return_type; \
153 typedef typename_type_k func_ptr_traits_type::param1_type param1_type; \
154 typedef typename_type_k func_ptr_traits_type::param2_type param2_type; \
155 typedef typename_type_k func_ptr_traits_type::param3_type param3_type; \
156 typedef typename_type_k func_ptr_traits_type::param4_type param4_type; \
157 typedef typename_type_k func_ptr_traits_type::param5_type param5_type; \
158 typedef typename_type_k func_ptr_traits_type::param6_type param6_type; \
159 typedef typename_type_k func_ptr_traits_type::param7_type param7_type; \
160 typedef typename_type_k func_ptr_traits_type::param8_type param8_type; \
161 typedef typename_type_k func_ptr_traits_type::param9_type param9_type; \
163 private: \
164 derived_type& get_derive() { return static_cast<derived_type&>(*this); } \
165 derived_type const& get_derive() const { return static_cast<derived_type const&>(*this); } \
167 public: \
168 operation_impl \
170 public: \
171 result(){}; \
172 private: \
173 result(class_type const&); \
174 class_type& operator =(class_type const&); \
175 }; \
178 #define EXTL_FUNC_PTR_IMPL_SPEC(num) EXTL_FUNC_PTR_IMPL_SPEC_(e_false_v, EXTL_FUNC_PTR_OPERATION_IMPL(num), num)
179 #define EXTL_FUNC_PTR_IMPL_VOID_RET_SPEC(num) EXTL_FUNC_PTR_IMPL_SPEC_(e_true_v, EXTL_FUNC_PTR_VOID_RET_OPERATION_IMPL(num), num)
181 /* ///////////////////////////////////////////////////////////////////////
182 * ::extl namespace
184 EXTL_BEGIN_NAMESPACE
185 EXTL_DETAIL_BEGIN_NAMESPACE
187 template< e_bool_t is_void_return
188 , e_size_t param_num
190 class func_ptr_impl{};
192 EXTL_FUNC_PTR_IMPL_SPEC(0)
193 EXTL_FUNC_PTR_IMPL_SPEC(1)
194 EXTL_FUNC_PTR_IMPL_SPEC(2)
195 EXTL_FUNC_PTR_IMPL_SPEC(3)
196 EXTL_FUNC_PTR_IMPL_SPEC(4)
197 EXTL_FUNC_PTR_IMPL_SPEC(5)
198 EXTL_FUNC_PTR_IMPL_SPEC(6)
199 EXTL_FUNC_PTR_IMPL_SPEC(7)
200 EXTL_FUNC_PTR_IMPL_SPEC(8)
201 EXTL_FUNC_PTR_IMPL_SPEC(9)
203 EXTL_FUNC_PTR_IMPL_VOID_RET_SPEC(0)
204 EXTL_FUNC_PTR_IMPL_VOID_RET_SPEC(1)
205 EXTL_FUNC_PTR_IMPL_VOID_RET_SPEC(2)
206 EXTL_FUNC_PTR_IMPL_VOID_RET_SPEC(3)
207 EXTL_FUNC_PTR_IMPL_VOID_RET_SPEC(4)
208 EXTL_FUNC_PTR_IMPL_VOID_RET_SPEC(5)
209 EXTL_FUNC_PTR_IMPL_VOID_RET_SPEC(6)
210 EXTL_FUNC_PTR_IMPL_VOID_RET_SPEC(7)
211 EXTL_FUNC_PTR_IMPL_VOID_RET_SPEC(8)
212 EXTL_FUNC_PTR_IMPL_VOID_RET_SPEC(9)
213 /* ///////////////////////////////////////////////////////////////////////
214 * ::extl::detail namespace
216 EXTL_DETAIL_END_NAMESPACE
218 /* ///////////////////////////////////////////////////////////////////////
219 * Macros
221 #undef EXTL_FUNC_PTR_OPERATOR_0
222 #undef EXTL_FUNC_PTR_OPERATOR_1
223 #undef EXTL_FUNC_PTR_OPERATOR_2
224 #undef EXTL_FUNC_PTR_OPERATOR_3
225 #undef EXTL_FUNC_PTR_OPERATOR_4
226 #undef EXTL_FUNC_PTR_OPERATOR_5
227 #undef EXTL_FUNC_PTR_OPERATOR_6
228 #undef EXTL_FUNC_PTR_OPERATOR_7
229 #undef EXTL_FUNC_PTR_OPERATOR_8
230 #undef EXTL_FUNC_PTR_OPERATOR_9
232 #undef EXTL_FUNC_PTR_OPERATOR_PARAM_0
233 #undef EXTL_FUNC_PTR_OPERATOR_PARAM_1
234 #undef EXTL_FUNC_PTR_OPERATOR_PARAM_2
235 #undef EXTL_FUNC_PTR_OPERATOR_PARAM_3
236 #undef EXTL_FUNC_PTR_OPERATOR_PARAM_4
237 #undef EXTL_FUNC_PTR_OPERATOR_PARAM_5
238 #undef EXTL_FUNC_PTR_OPERATOR_PARAM_6
239 #undef EXTL_FUNC_PTR_OPERATOR_PARAM_7
240 #undef EXTL_FUNC_PTR_OPERATOR_PARAM_8
241 #undef EXTL_FUNC_PTR_OPERATOR_PARAM_9
243 #undef EXTL_FUNC_PTR_OPERATION_IMPL
244 #undef EXTL_FUNC_PTR_VOID_RET_OPERATION_IMPL
245 #undef EXTL_FUNC_PTR_IMPL_SPEC_
246 #undef EXTL_FUNC_PTR_IMPL_SPEC
247 #undef EXTL_FUNC_PTR_IMPL_VOID_RET_SPEC
248 #undef EXTL_FUNC_PTR_PARAM_TYPE
249 /*!\brief func_ptr class
251 * \param FP The function pointer type
253 * \ingroup extl_group_functional
255 template<typename_param_k FP>
256 class func_ptr
257 : public EXTL_NS_DETAIL(func_ptr_impl) < (is_void< typename_type_k func_ptr_traits<FP>::return_type >::value)
258 #if EXTL_WORKAROUND_MSVC(==, 1200) // need not bracket at VC6.0
259 , func_ptr_traits<FP>::param_num
260 #else
261 , (func_ptr_traits<FP>::param_num) // need bracket at BCC 5.51
262 #endif
263 >::template_qual_k result<func_ptr<FP>, FP>
265 /// \name Types
266 /// @{
267 public:
268 typedef func_ptr<FP> class_type;
269 typedef FP func_ptr_type;
270 typedef func_ptr_traits<FP> func_ptr_traits_type;
271 typedef e_size_t size_type;
272 typedef e_bool_t bool_type;
273 /// @}
275 /// \name The parameter type
276 /// @{
277 public:
278 typedef typename_type_k func_ptr_traits_type::return_type return_type;
279 typedef typename_type_k func_ptr_traits_type::param1_type param1_type;
280 typedef typename_type_k func_ptr_traits_type::param2_type param2_type;
281 typedef typename_type_k func_ptr_traits_type::param3_type param3_type;
282 typedef typename_type_k func_ptr_traits_type::param4_type param4_type;
283 typedef typename_type_k func_ptr_traits_type::param5_type param5_type;
284 typedef typename_type_k func_ptr_traits_type::param6_type param6_type;
285 typedef typename_type_k func_ptr_traits_type::param7_type param7_type;
286 typedef typename_type_k func_ptr_traits_type::param8_type param8_type;
287 typedef typename_type_k func_ptr_traits_type::param9_type param9_type;
288 /// @
290 public:
291 /// The number of parameter
292 EXTL_STATIC_MEMBER_CONST(size_type, param_num = func_ptr_traits_type::param_num);
294 /// \name Members
295 /// @{
296 private:
297 func_ptr_type m_fp;
298 /// @}
300 /// \name Constructors
301 /// @{
302 public:
303 func_ptr()
304 : m_fp(NULL)
307 explicit_k func_ptr(func_ptr_type fp)
308 : m_fp(fp)
311 func_ptr(class_type const& rhs)
312 : m_fp(rhs.m_fp)
315 ~func_ptr()
317 clear();
319 /// @}
321 /// \name Attributes
322 /// @{
323 public:
324 func_ptr_type get_ptr() { return m_fp; }
325 func_ptr_type const get_ptr() const { return m_fp; }
326 bool_type is_empty() const { return NULL == m_fp; }
327 bool_type empty() const { return is_empty(); }
328 /// @}
330 /// \name Mutators
331 /// @{
332 public:
333 void swap(class_type& rhs) { std_swap(m_fp, rhs.m_fp); }
334 void clear() { m_fp = NULL; }
335 void reset(func_ptr_type fp) { class_type(fp).swap(*this); }
336 void reset(class_type const& rhs) { class_type(rhs).swap(*this); }
338 class_type& operator =(class_type const& rhs)
340 class_type(rhs).swap(*this);
341 return *this;
343 class_type& operator =(func_ptr_type fp)
345 class_type(fp).swap(*this);
346 return *this;
348 /// @}
350 /// \name Operators Overload
351 /// @{
352 public:
353 /// safe implicit conversion to the bool type
354 EXTL_OPERATOR_BOOL_DEFINE_TYPE_T(class_type, safe_bool_type);
355 operator safe_bool_type() const
357 return EXTL_OPERATOR_BOOL_RETURN_RESULT(!is_empty());
359 /// operator!() overload
360 bool_type operator !() const { return is_empty(); }
361 /// @}
365 /* ///////////////////////////////////////////////////////////////////////
366 * Unit-testing
368 #ifdef EXTL_FUNCTIONAL_FUNC_PTR_TEST_ENABLE
369 # include "unit_test/func_ptr_test.h"
370 #endif
372 /* ///////////////////////////////////////////////////////////////////////
373 * ::extl namespace
375 EXTL_END_NAMESPACE
377 /* //////////////////////////////////////////////////////////////////// */
378 #endif /* EXTL_FUNCTIONAL_FUNC_PTR_H */
379 /* //////////////////////////////////////////////////////////////////// */