1 // This file is part of the ustl library, an STL implementation.
3 // Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
4 // This file is free software, distributed under the MIT License.
8 // \brief Implements STL standard functors.
10 // See STL specification and bvts for usage of these. The only
11 // extension is the mem_var functors for member variable access:
13 // f = find_if (ctr, mem_var_equal_to(&MyClass::m_Var, matchVar));
14 // f = find_if (ctr, mem_var_less(&MyClass::m_Var, matchVar));
16 // There are a couple of others but the syntax is much harder to grasp.
17 // See bvt10.cc for more examples.
20 #ifndef UFUNCTION_H_221ABA8551801799263C927234C085F3
21 #define UFUNCTION_H_221ABA8551801799263C927234C085F3
25 //----------------------------------------------------------------------
27 //----------------------------------------------------------------------
29 /// \brief void-returning function abstract interface.
30 /// \ingroup FunctorObjects
31 template <typename Result
>
32 struct void_function
{
33 typedef Result result_type
;
36 /// \brief \p Result f (\p Arg) function abstract interface.
37 /// \ingroup FunctorObjects
38 template <typename Arg
, typename Result
>
39 struct unary_function
{
40 typedef Arg argument_type
;
41 typedef Result result_type
;
44 /// \brief \p Result f (\p Arg1, \p Arg2) function abstract interface.
45 /// \ingroup FunctorObjects
46 template <typename Arg1
, typename Arg2
, typename Result
>
47 struct binary_function
{
48 typedef Arg1 first_argument_type
;
49 typedef Arg2 second_argument_type
;
50 typedef Result result_type
;
53 #ifndef DOXYGEN_SHOULD_SKIP_THIS
55 #define STD_BINARY_FUNCTOR(name, rv, func) \
56 template <class T> struct name : public binary_function<T,T,rv> \
57 { inline rv operator()(const T& a, const T& b) const { return func; } };
58 #define STD_UNARY_FUNCTOR(name, rv, func) \
59 template <class T> struct name : public unary_function<T,rv> \
60 { inline rv operator()(const T& a) const { return func; } };
61 #define STD_CONVERSION_FUNCTOR(name, func) \
62 template <class S, class D> struct name : public unary_function<S,D> \
63 { inline D operator()(const S& a) const { return func; } };
65 STD_BINARY_FUNCTOR (plus
, T
, (a
+ b
))
66 STD_BINARY_FUNCTOR (minus
, T
, (a
- b
))
67 STD_BINARY_FUNCTOR (divides
, T
, (a
/ b
))
68 STD_BINARY_FUNCTOR (modulus
, T
, (a
% b
))
69 STD_BINARY_FUNCTOR (multiplies
, T
, (a
* b
))
70 STD_BINARY_FUNCTOR (logical_and
, T
, (a
&& b
))
71 STD_BINARY_FUNCTOR (logical_or
, T
, (a
|| b
))
72 STD_UNARY_FUNCTOR (logical_not
, T
, (!a
))
73 STD_BINARY_FUNCTOR (bitwise_or
, T
, (a
| b
))
74 STD_BINARY_FUNCTOR (bitwise_and
, T
, (a
& b
))
75 STD_BINARY_FUNCTOR (bitwise_xor
, T
, (a
^ b
))
76 STD_UNARY_FUNCTOR (bitwise_not
, T
, (~a
))
77 STD_UNARY_FUNCTOR (negate
, T
, (-a
))
78 STD_BINARY_FUNCTOR (equal_to
, bool, (a
== b
))
79 STD_BINARY_FUNCTOR (not_equal_to
, bool, (!(a
== b
)))
80 STD_BINARY_FUNCTOR (greater
, bool, (b
< a
))
81 STD_BINARY_FUNCTOR (less
, bool, (a
< b
))
82 STD_BINARY_FUNCTOR (greater_equal
, bool, (!(a
< b
)))
83 STD_BINARY_FUNCTOR (less_equal
, bool, (!(b
< a
)))
84 STD_BINARY_FUNCTOR (compare
, int, (a
< b
? -1 : (b
< a
)))
85 STD_UNARY_FUNCTOR (identity
, T
, (a
))
87 #endif // DOXYGEN_SHOULD_SKIP_THIS
89 /// \brief Selects and returns the first argument.
90 /// \ingroup FunctorObjects
91 template <class T1
, class T2
> struct project1st
: public binary_function
<T1
,T2
,T1
> { inline const T1
& operator()(const T1
& a
, const T2
&) const { return (a
); } };
92 /// \brief Selects and returns the second argument.
93 /// \ingroup FunctorObjects
94 template <class T1
, class T2
> struct project2nd
: public binary_function
<T1
,T2
,T2
> { inline const T2
& operator()(const T1
&, const T2
& a
) const { return (a
); } };
96 //----------------------------------------------------------------------
97 // Generic function to functor converters.
98 //----------------------------------------------------------------------
100 /// \brief Wrapper object for unary function pointers.
101 /// Use the ptr_fun accessor to create this object.
102 /// \ingroup FunctorObjects
103 template <typename Arg
, typename Result
>
104 class pointer_to_unary_function
: public unary_function
<Arg
,Result
> {
106 typedef Arg argument_type
;
107 typedef Result result_type
;
108 typedef Result (*pfunc_t
)(Arg
);
110 explicit inline pointer_to_unary_function (pfunc_t pfn
) : m_pfn (pfn
) {}
111 inline result_type
operator() (argument_type v
) const { return (m_pfn(v
)); }
113 pfunc_t m_pfn
; ///< Pointer to the wrapped function.
116 /// \brief Wrapper object for binary function pointers.
117 /// Use the ptr_fun accessor to create this object.
118 /// \ingroup FunctorObjects
119 template <typename Arg1
, typename Arg2
, typename Result
>
120 class pointer_to_binary_function
: public binary_function
<Arg1
,Arg2
,Result
> {
122 typedef Arg1 first_argument_type
;
123 typedef Arg2 second_argument_type
;
124 typedef Result result_type
;
125 typedef Result (*pfunc_t
)(Arg1
, Arg2
);
127 explicit inline pointer_to_binary_function (pfunc_t pfn
) : m_pfn (pfn
) {}
128 inline result_type
operator() (first_argument_type v1
, second_argument_type v2
) const { return (m_pfn(v1
, v2
)); }
130 pfunc_t m_pfn
; ///< Pointer to the wrapped function.
133 /// ptr_fun(pfn) wraps function pointer pfn into a functor class that calls it.
134 /// \ingroup FunctorAccessors
135 template <typename Arg
, typename Result
>
136 inline pointer_to_unary_function
<Arg
,Result
> ptr_fun (Result (*pfn
)(Arg
))
138 return (pointer_to_unary_function
<Arg
,Result
> (pfn
));
141 /// ptr_fun(pfn) wraps function pointer pfn into a functor class that calls it.
142 /// \ingroup FunctorAccessors
143 template <typename Arg1
, typename Arg2
, typename Result
>
144 inline pointer_to_binary_function
<Arg1
,Arg2
,Result
> ptr_fun (Result (*pfn
)(Arg1
,Arg2
))
146 return (pointer_to_binary_function
<Arg1
,Arg2
,Result
> (pfn
));
149 //----------------------------------------------------------------------
151 //----------------------------------------------------------------------
153 /// \brief Wraps a unary function to return its logical negative.
154 /// Use the unary_negator accessor to create this object.
155 /// \ingroup FunctorObjects
156 template <class UnaryFunction
>
157 class unary_negate
: public unary_function
<typename
UnaryFunction::argument_type
,
158 typename
UnaryFunction::result_type
> {
160 typedef typename
UnaryFunction::argument_type argument_type
;
161 typedef typename
UnaryFunction::result_type result_type
;
163 explicit inline unary_negate (UnaryFunction pfn
) : m_pfn (pfn
) {}
164 inline result_type
operator() (argument_type v
) const { return (!m_pfn(v
)); }
169 /// Returns the functor that negates the result of *pfn().
170 /// \ingroup FunctorAccessors
171 template <class UnaryFunction
>
172 inline unary_negate
<UnaryFunction
> unary_negator (UnaryFunction pfn
)
174 return (unary_negate
<UnaryFunction
>(pfn
));
177 //----------------------------------------------------------------------
179 //----------------------------------------------------------------------
181 /// \brief Converts a binary function to a unary function
182 /// by binding a constant value to the first argument.
183 /// Use the bind1st accessor to create this object.
184 /// \ingroup FunctorObjects
185 template <class BinaryFunction
>
186 class binder1st
: public unary_function
<typename
BinaryFunction::second_argument_type
,
187 typename
BinaryFunction::result_type
> {
189 typedef typename
BinaryFunction::first_argument_type arg1_t
;
190 typedef typename
BinaryFunction::second_argument_type arg2_t
;
191 typedef typename
BinaryFunction::result_type result_t
;
193 inline binder1st (const BinaryFunction
& pfn
, const arg1_t
& v
) : m_pfn (pfn
), m_Value(v
) {}
194 inline result_t
operator()(arg2_t v2
) const { return (m_pfn (m_Value
, v2
)); }
196 BinaryFunction m_pfn
;
200 /// \brief Converts a binary function to a unary function
201 /// by binding a constant value to the second argument.
202 /// Use the bind2nd accessor to create this object.
203 /// \ingroup FunctorObjects
204 template <class BinaryFunction
>
205 class binder2nd
: public unary_function
<typename
BinaryFunction::first_argument_type
,
206 typename
BinaryFunction::result_type
> {
208 typedef typename
BinaryFunction::first_argument_type arg1_t
;
209 typedef typename
BinaryFunction::second_argument_type arg2_t
;
210 typedef typename
BinaryFunction::result_type result_t
;
212 inline binder2nd (const BinaryFunction
& pfn
, const arg2_t
& v
) : m_pfn (pfn
), m_Value(v
) {}
213 inline result_t
operator()(arg1_t v1
) const { return (m_pfn (v1
, m_Value
)); }
215 BinaryFunction m_pfn
;
219 /// Converts \p pfn into a unary function by binding the first argument to \p v.
220 /// \ingroup FunctorAccessors
221 template <typename BinaryFunction
>
222 inline binder1st
<BinaryFunction
>
223 bind1st (BinaryFunction pfn
, typename
BinaryFunction::first_argument_type v
)
225 return (binder1st
<BinaryFunction
> (pfn
, v
));
228 /// Converts \p pfn into a unary function by binding the second argument to \p v.
229 /// \ingroup FunctorAccessors
230 template <typename BinaryFunction
>
231 inline binder2nd
<BinaryFunction
>
232 bind2nd (BinaryFunction pfn
, typename
BinaryFunction::second_argument_type v
)
234 return (binder2nd
<BinaryFunction
> (pfn
, v
));
237 //----------------------------------------------------------------------
238 // Composition adapters
239 //----------------------------------------------------------------------
241 /// \brief Chains two unary functions together.
243 /// When f(x) and g(x) are composed, the result is function c(x)=f(g(x)).
244 /// Use the \ref compose1 accessor to create this object.
245 /// This template is an extension, implemented by SGI STL and uSTL.
246 /// \ingroup FunctorObjects
248 template <typename Operation1
, typename Operation2
>
249 class unary_compose
: public unary_function
<typename
Operation2::argument_type
,
250 typename
Operation1::result_type
> {
252 typedef typename
Operation2::argument_type arg_t
;
253 typedef const arg_t
& rcarg_t
;
254 typedef typename
Operation1::result_type result_t
;
256 inline unary_compose (const Operation1
& f
, const Operation2
& g
) : m_f(f
), m_g(g
) {}
257 inline result_t
operator() (rcarg_t x
) const { return m_f(m_g(x
)); }
259 Operation1 m_f
; ///< f(x), if c(x) = f(g(x))
260 Operation2 m_g
; ///< g(x), if c(x) = f(g(x))
263 /// Creates a \ref unary_compose object whose function c(x)=f(g(x))
264 /// \ingroup FunctorAccessors
265 template <typename Operation1
, typename Operation2
>
266 inline unary_compose
<Operation1
, Operation2
>
267 compose1 (const Operation1
& f
, const Operation2
& g
)
268 { return unary_compose
<Operation1
,Operation2
>(f
, g
); }
270 /// \brief Chains two unary functions through a binary function.
272 /// When f(x,y), g(x), and h(x) are composed, the result is function
273 /// c(x)=f(g(x),h(x)). Use the \ref compose2 accessor to create this
274 /// object. This template is an extension, implemented by SGI STL and uSTL.
275 /// \ingroup FunctorObjects
277 template <typename Operation1
, typename Operation2
, typename Operation3
>
278 class binary_compose
: public unary_function
<typename
Operation2::argument_type
,
279 typename
Operation1::result_type
> {
281 typedef typename
Operation2::argument_type arg_t
;
282 typedef const arg_t
& rcarg_t
;
283 typedef typename
Operation1::result_type result_t
;
285 inline binary_compose (const Operation1
& f
, const Operation2
& g
, const Operation3
& h
) : m_f(f
), m_g(g
), m_h(h
) {}
286 inline result_t
operator() (rcarg_t x
) const { return m_f(m_g(x
), m_h(x
)); }
288 Operation1 m_f
; ///< f(x,y), if c(x) = f(g(x),h(x))
289 Operation2 m_g
; ///< g(x), if c(x) = f(g(x),h(x))
290 Operation3 m_h
; ///< h(x), if c(x) = f(g(x),h(x))
293 /// Creates a \ref binary_compose object whose function c(x)=f(g(x),h(x))
294 /// \ingroup FunctorAccessors
295 template <typename Operation1
, typename Operation2
, typename Operation3
>
296 inline binary_compose
<Operation1
, Operation2
, Operation3
>
297 compose2 (const Operation1
& f
, const Operation2
& g
, const Operation3
& h
)
298 { return binary_compose
<Operation1
, Operation2
, Operation3
> (f
, g
, h
); }
300 //----------------------------------------------------------------------
301 // Member function adaptors
302 //----------------------------------------------------------------------
304 #ifndef DOXYGEN_SHOULD_SKIP_THIS
306 #define MEM_FUN_T(WrapperName, ClassName, ArgType, FuncType, CallType) \
307 template <typename Ret, class T> \
308 class ClassName : public unary_function<ArgType,Ret> { \
310 typedef Ret (T::*func_t) FuncType; \
312 explicit inline ClassName (func_t pf) : m_pf (pf) {} \
313 inline Ret operator() (ArgType p) const { return ((p CallType m_pf)()); } \
318 template <class Ret, typename T> \
319 inline ClassName<Ret,T> WrapperName (Ret (T::*pf) FuncType) \
321 return (ClassName<Ret,T> (pf)); \
324 MEM_FUN_T(mem_fun
, mem_fun_t
, T
*, (void), ->*)
325 MEM_FUN_T(mem_fun
, const_mem_fun_t
, const T
*, (void) const, ->*)
326 MEM_FUN_T(mem_fun_ref
, mem_fun_ref_t
, T
&, (void), .*)
327 MEM_FUN_T(mem_fun_ref
, const_mem_fun_ref_t
, const T
&, (void) const, .*)
329 #define EXT_MEM_FUN_T(ClassName, HostType, FuncType) \
330 template <class T, typename Ret, typename V> \
331 class ClassName : public unary_function<V,void> { \
333 typedef Ret (T::*func_t)(V) FuncType; \
335 inline ClassName (HostType t, func_t pf) : m_t (t), m_pf (pf) {} \
336 inline Ret operator() (V v) const { return ((m_t->*m_pf)(v)); } \
342 template <class T, typename Ret, typename V> \
343 inline ClassName<T,Ret,V> mem_fun (HostType p, Ret (T::*pf)(V) FuncType) \
345 return (ClassName<T,Ret,V> (p, pf)); \
348 EXT_MEM_FUN_T(ext_mem_fun_t
, T
*, )
349 EXT_MEM_FUN_T(const_ext_mem_fun_t
, const T
*, const)
351 #endif // DOXYGEN_SHOULD_SKIP_THIS
353 //----------------------------------------------------------------------
354 // Member variable adaptors (uSTL extension)
355 //----------------------------------------------------------------------
357 #ifndef DOXYGEN_SHOULD_SKIP_THIS
359 #define MEM_VAR_T(FunctorName, ArgType, VarType, BaseClass, CallImpl) \
360 template <typename Function, class T, typename VT> \
361 class FunctorName##_t : public BaseClass { \
363 typedef ArgType argument_type; \
364 typedef typename Function::result_type result_type; \
365 typedef VarType mem_var_ptr_t; \
367 inline FunctorName##_t (mem_var_ptr_t pv, Function pfn) : m_pv(pv), m_pfn(pfn) {} \
368 inline result_type operator() CallImpl \
370 mem_var_ptr_t m_pv; \
374 template <typename Function, class T, typename VT> \
375 inline FunctorName##_t<Function, T, VT> \
376 FunctorName (VT T::*mvp, Function pfn) \
378 return (FunctorName##_t<Function,T,VT> (mvp, pfn)); \
381 #define FUNCTOR_UNARY_BASE(ArgType) unary_function<ArgType, typename Function::result_type>
382 #define FUNCTOR_BINARY_BASE(ArgType) binary_function<ArgType, ArgType, typename Function::result_type>
384 #define MEM_VAR_UNARY_ARGS (argument_type p) const \
385 { return (m_pfn(p.*m_pv)); }
386 #define MEM_VAR_BINARY_ARGS (argument_type p1, argument_type p2) const \
387 { return (m_pfn(p1.*m_pv, p2.*m_pv)); }
389 MEM_VAR_T(mem_var1
, T
&, VT
T::*, FUNCTOR_UNARY_BASE(T
&), MEM_VAR_UNARY_ARGS
)
390 MEM_VAR_T(const_mem_var1
, const T
&, const VT
T::*, FUNCTOR_UNARY_BASE(T
&), MEM_VAR_UNARY_ARGS
)
391 MEM_VAR_T(mem_var2
, T
&, VT
T::*, FUNCTOR_BINARY_BASE(T
&), MEM_VAR_BINARY_ARGS
)
392 MEM_VAR_T(const_mem_var2
, const T
&, const VT
T::*, FUNCTOR_BINARY_BASE(T
&), MEM_VAR_BINARY_ARGS
)
394 #undef MEM_VAR_UNARY_ARGS
395 #undef MEM_VAR_BINARY_ARGS
397 #endif // DOXYGEN_SHOULD_SKIP_THIS
399 /// Returned functor passes member variable \p mvp reference of given object to equal\<VT\>.
400 /// \ingroup FunctorAccessors
401 template <class T
, typename VT
>
402 inline const_mem_var1_t
<binder2nd
<equal_to
<VT
> >, T
, VT
>
403 mem_var_equal_to (const VT
T::*mvp
, const VT
& v
)
405 return (const_mem_var1_t
<binder2nd
<equal_to
<VT
> >,T
,VT
> (mvp
, bind2nd(equal_to
<VT
>(), v
)));
408 /// Returned functor passes member variable \p mvp reference of given object to less\<VT\>.
409 /// \ingroup FunctorAccessors
410 template <class T
, typename VT
>
411 inline const_mem_var1_t
<binder2nd
<less
<VT
> >, T
, VT
>
412 mem_var_less (const VT
T::*mvp
, const VT
& v
)
414 return (const_mem_var1_t
<binder2nd
<less
<VT
> >,T
,VT
> (mvp
, bind2nd(less
<VT
>(), v
)));
417 /// Returned functor passes member variable \p mvp reference of given object to equal\<VT\>.
418 /// \ingroup FunctorAccessors
419 template <class T
, typename VT
>
420 inline const_mem_var2_t
<equal_to
<VT
>, T
, VT
>
421 mem_var_equal_to (const VT
T::*mvp
)
423 return (const_mem_var2_t
<equal_to
<VT
>,T
,VT
> (mvp
, equal_to
<VT
>()));
426 /// Returned functor passes member variable \p mvp reference of given object to less\<VT\>.
427 /// \ingroup FunctorAccessors
428 template <class T
, typename VT
>
429 inline const_mem_var2_t
<less
<VT
>, T
, VT
>
430 mem_var_less (const VT
T::*mvp
)
432 return (const_mem_var2_t
<less
<VT
>,T
,VT
> (mvp
, less
<VT
>()));
435 //----------------------------------------------------------------------
436 // Dereference adaptors (uSTL extension)
437 //----------------------------------------------------------------------
439 #ifndef DOXYGEN_SHOULD_SKIP_THIS
441 #define DEREFERENCER_T(ClassName, ArgType, BaseClass, CallImpl, FunctorKey) \
442 template <typename T, typename Function> \
443 class ClassName : public BaseClass { \
445 typedef ArgType* argument_type; \
446 typedef typename Function::result_type result_type; \
448 inline ClassName (Function pfn) : m_pfn (pfn) {} \
449 inline result_type operator() CallImpl \
454 template <typename T, typename Function> \
455 inline ClassName<T,Function> _dereference (Function pfn, FunctorKey) \
457 return (ClassName<T,Function> (pfn)); \
460 #define DEREF_UNARY_ARGS (argument_type p) const \
461 { return (m_pfn(*p)); }
462 #define DEREF_BINARY_ARGS (argument_type p1, argument_type p2) const \
463 { return (m_pfn(*p1, *p2)); }
465 DEREFERENCER_T(deref1_t
, T
, FUNCTOR_UNARY_BASE(T
*), DEREF_UNARY_ARGS
, FUNCTOR_UNARY_BASE(T
))
466 DEREFERENCER_T(const_deref1_t
, const T
, FUNCTOR_UNARY_BASE(const T
*), DEREF_UNARY_ARGS
, FUNCTOR_UNARY_BASE(const T
))
467 DEREFERENCER_T(deref2_t
, T
, FUNCTOR_BINARY_BASE(T
*), DEREF_BINARY_ARGS
, FUNCTOR_BINARY_BASE(T
))
468 DEREFERENCER_T(const_deref2_t
, const T
, FUNCTOR_BINARY_BASE(const T
*), DEREF_BINARY_ARGS
, FUNCTOR_BINARY_BASE(const T
))
470 #define dereference(f) _dereference(f,f)
472 #undef DEREF_UNARY_ARGS
473 #undef DEREF_BINARY_ARGS