Build system improvements
[ustl.git] / ufunction.h
blobf0af596dfca5bd86096688a35a90a911629f975a
1 // This file is part of the ustl library, an STL implementation.
2 //
3 // Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
4 // This file is free software, distributed under the MIT License.
5 //
6 // \file ufunction.h
7 //
8 // \brief Implements STL standard functors.
9 //
10 // See STL specification and bvts for usage of these. The only
11 // extension is the mem_var functors for member variable access:
12 // \code
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));
15 // \endcode
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
23 namespace ustl {
25 //----------------------------------------------------------------------
26 // Standard functors
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> {
105 public:
106 typedef Arg argument_type;
107 typedef Result result_type;
108 typedef Result (*pfunc_t)(Arg);
109 public:
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)); }
112 private:
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> {
121 public:
122 typedef Arg1 first_argument_type;
123 typedef Arg2 second_argument_type;
124 typedef Result result_type;
125 typedef Result (*pfunc_t)(Arg1, Arg2);
126 public:
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)); }
129 private:
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 //----------------------------------------------------------------------
150 // Negators.
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> {
159 public:
160 typedef typename UnaryFunction::argument_type argument_type;
161 typedef typename UnaryFunction::result_type result_type;
162 public:
163 explicit inline unary_negate (UnaryFunction pfn) : m_pfn (pfn) {}
164 inline result_type operator() (argument_type v) const { return (!m_pfn(v)); }
165 private:
166 UnaryFunction m_pfn;
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 //----------------------------------------------------------------------
178 // Argument binders
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> {
188 public:
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;
192 public:
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)); }
195 protected:
196 BinaryFunction m_pfn;
197 arg1_t m_Value;
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> {
207 public:
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;
211 public:
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)); }
214 protected:
215 BinaryFunction m_pfn;
216 arg2_t m_Value;
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> {
251 public:
252 typedef typename Operation2::argument_type arg_t;
253 typedef const arg_t& rcarg_t;
254 typedef typename Operation1::result_type result_t;
255 public:
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)); }
258 protected:
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> {
280 public:
281 typedef typename Operation2::argument_type arg_t;
282 typedef const arg_t& rcarg_t;
283 typedef typename Operation1::result_type result_t;
284 public:
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)); }
287 protected:
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> { \
309 public: \
310 typedef Ret (T::*func_t) FuncType; \
311 public: \
312 explicit inline ClassName (func_t pf) : m_pf (pf) {} \
313 inline Ret operator() (ArgType p) const { return ((p CallType m_pf)()); } \
314 private: \
315 func_t m_pf; \
316 }; \
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> { \
332 public: \
333 typedef Ret (T::*func_t)(V) FuncType; \
334 public: \
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)); } \
337 private: \
338 HostType m_t; \
339 func_t m_pf; \
340 }; \
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 { \
362 public: \
363 typedef ArgType argument_type; \
364 typedef typename Function::result_type result_type; \
365 typedef VarType mem_var_ptr_t; \
366 public: \
367 inline FunctorName##_t (mem_var_ptr_t pv, Function pfn) : m_pv(pv), m_pfn(pfn) {} \
368 inline result_type operator() CallImpl \
369 private: \
370 mem_var_ptr_t m_pv; \
371 Function m_pfn; \
372 }; \
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 { \
444 public: \
445 typedef ArgType* argument_type; \
446 typedef typename Function::result_type result_type; \
447 public: \
448 inline ClassName (Function pfn) : m_pfn (pfn) {} \
449 inline result_type operator() CallImpl \
450 private: \
451 Function m_pfn; \
452 }; \
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
475 #endif
477 } // namespace ustl
479 #endif