• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
18 //
19 
20 #ifndef UFUNCTION_H_221ABA8551801799263C927234C085F3
21 #define UFUNCTION_H_221ABA8551801799263C927234C085F3
22 
23 namespace ustl {
24 
25 //----------------------------------------------------------------------
26 // Standard functors
27 //----------------------------------------------------------------------
28 
29 /// \brief void-returning function abstract interface.
30 /// \ingroup FunctorObjects
31 template <typename Result>
32 struct void_function {
33     typedef Result	result_type;
34 };
35 
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;
42 };
43 
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;
51 };
52 
53 #ifndef DOXYGEN_SHOULD_SKIP_THIS
54 
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; } };
64 
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))
86 
87 #endif // DOXYGEN_SHOULD_SKIP_THIS
88 
89 /// \brief Selects and returns the first argument.
90 /// \ingroup FunctorObjects
operatorproject1st91 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
operatorproject2nd94 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); } };
95 
96 //----------------------------------------------------------------------
97 // Generic function to functor converters.
98 //----------------------------------------------------------------------
99 
100 /// \brief Wrapper object for unary function pointers.
101 /// Use the \ref 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:
pointer_to_unary_function(pfunc_t pfn)110     explicit inline	pointer_to_unary_function (pfunc_t pfn) : m_pfn (pfn) {}
operator()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.
114 };
115 
116 /// \brief Wrapper object for binary function pointers.
117 /// Use the \ref 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:
pointer_to_binary_function(pfunc_t pfn)127     explicit inline	pointer_to_binary_function (pfunc_t pfn) : m_pfn (pfn) {}
operator()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.
131 };
132 
133 /// ptr_fun(pfn) wraps function pointer pfn into a functor class that calls it.
134 /// \ingroup FunctorAccessors
135 template <typename Arg, typename Result>
ptr_fun(Result (* pfn)(Arg))136 inline pointer_to_unary_function<Arg,Result> ptr_fun (Result (*pfn)(Arg))
137 {
138     return (pointer_to_unary_function<Arg,Result> (pfn));
139 }
140 
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>
ptr_fun(Result (* pfn)(Arg1,Arg2))144 inline pointer_to_binary_function<Arg1,Arg2,Result> ptr_fun (Result (*pfn)(Arg1,Arg2))
145 {
146     return (pointer_to_binary_function<Arg1,Arg2,Result> (pfn));
147 }
148 
149 //----------------------------------------------------------------------
150 // Negators.
151 //----------------------------------------------------------------------
152 
153 /// \brief Wraps a unary function to return its logical negative.
154 /// Use the \ref 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:
unary_negate(UnaryFunction pfn)163     explicit inline unary_negate (UnaryFunction pfn) : m_pfn (pfn) {}
operator()164     inline result_type operator() (argument_type v) const { return (!m_pfn(v)); }
165 private:
166     UnaryFunction	m_pfn;
167 };
168 
169 /// Returns the functor that negates the result of *pfn().
170 /// \ingroup FunctorAccessors
171 template <class UnaryFunction>
unary_negator(UnaryFunction pfn)172 inline unary_negate<UnaryFunction> unary_negator (UnaryFunction pfn)
173 {
174     return (unary_negate<UnaryFunction>(pfn));
175 }
176 
177 //----------------------------------------------------------------------
178 // Argument binders
179 //----------------------------------------------------------------------
180 
181 /// \brief Converts a binary function to a unary function
182 /// by binding a constant value to the first argument.
183 /// Use the \ref 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:
binder1st(const BinaryFunction & pfn,const arg1_t & v)193     inline binder1st (const BinaryFunction& pfn, const arg1_t& v) : m_pfn (pfn), m_Value(v) {}
operator()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;
198 };
199 
200 /// \brief Converts a binary function to a unary function
201 /// by binding a constant value to the second argument.
202 /// Use the \ref 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:
binder2nd(const BinaryFunction & pfn,const arg2_t & v)212     inline binder2nd (const BinaryFunction& pfn, const arg2_t& v) : m_pfn (pfn), m_Value(v) {}
operator()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;
217 };
218 
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>
bind1st(BinaryFunction pfn,typename BinaryFunction::first_argument_type v)223 bind1st (BinaryFunction pfn, typename BinaryFunction::first_argument_type v)
224 {
225     return (binder1st<BinaryFunction> (pfn, v));
226 }
227 
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>
bind2nd(BinaryFunction pfn,typename BinaryFunction::second_argument_type v)232 bind2nd (BinaryFunction pfn, typename BinaryFunction::second_argument_type v)
233 {
234     return (binder2nd<BinaryFunction> (pfn, v));
235 }
236 
237 //----------------------------------------------------------------------
238 // Composition adapters
239 //----------------------------------------------------------------------
240 
241 /// \brief Chains two unary functions together.
242 ///
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
247 ///
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:
unary_compose(const Operation1 & f,const Operation2 & g)256     inline unary_compose (const Operation1& f, const Operation2& g) : m_f(f), m_g(g) {}
operator()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))
261 };
262 
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>
compose1(const Operation1 & f,const Operation2 & g)267 compose1 (const Operation1& f, const Operation2& g)
268 { return unary_compose<Operation1,Operation2>(f, g); }
269 
270 /// \brief Chains two unary functions through a binary function.
271 ///
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
276 ///
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:
binary_compose(const Operation1 & f,const Operation2 & g,const Operation3 & h)285     inline binary_compose (const Operation1& f, const Operation2& g, const Operation3& h) : m_f(f), m_g(g), m_h(h) {}
operator()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))
291 };
292 
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>
compose2(const Operation1 & f,const Operation2 & g,const Operation3 & h)297 compose2 (const Operation1& f, const Operation2& g, const Operation3& h)
298 { return binary_compose<Operation1, Operation2, Operation3> (f, g, h); }
299 
300 //----------------------------------------------------------------------
301 // Member function adaptors
302 //----------------------------------------------------------------------
303 
304 #ifndef DOXYGEN_SHOULD_SKIP_THIS
305 
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     };	\
317 	\
318     template <class Ret, typename T>		\
319     inline ClassName<Ret,T> WrapperName (Ret (T::*pf) FuncType)	\
320     {						\
321 	return (ClassName<Ret,T> (pf));		\
322     }
323 
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,	.*)
328 
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     };	\
341 	\
342     template <class T, typename Ret, typename V>					\
343     inline ClassName<T,Ret,V> mem_fun (HostType p, Ret (T::*pf)(V) FuncType)	\
344     {											\
345 	return (ClassName<T,Ret,V> (p, pf));						\
346     }
347 
348 EXT_MEM_FUN_T(ext_mem_fun_t,		T*,		)
EXT_MEM_FUN_T(const_ext_mem_fun_t,const T *,const)349 EXT_MEM_FUN_T(const_ext_mem_fun_t,	const T*,	const)
350 
351 #endif // DOXYGEN_SHOULD_SKIP_THIS
352 
353 //----------------------------------------------------------------------
354 // Member variable adaptors (uSTL extension)
355 //----------------------------------------------------------------------
356 
357 #ifndef DOXYGEN_SHOULD_SKIP_THIS
358 
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     };											\
373 											\
374     template <typename Function, class T, typename VT>					\
375     inline FunctorName##_t<Function, T, VT>						\
376     FunctorName (VT T::*mvp, Function pfn)						\
377     {											\
378 	return (FunctorName##_t<Function,T,VT> (mvp, pfn));				\
379     }
380 
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>
383 
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)); }
388 
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)
393 
394 #undef MEM_VAR_UNARY_ARGS
395 #undef MEM_VAR_BINARY_ARGS
396 
397 #endif // DOXYGEN_SHOULD_SKIP_THIS
398 
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)
404 {
405     return (const_mem_var1_t<binder2nd<equal_to<VT> >,T,VT> (mvp, bind2nd(equal_to<VT>(), v)));
406 }
407 
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>
mem_var_less(const VT T::* mvp,const VT & v)412 mem_var_less (const VT T::*mvp, const VT& v)
413 {
414     return (const_mem_var1_t<binder2nd<less<VT> >,T,VT> (mvp, bind2nd(less<VT>(), v)));
415 }
416 
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>
mem_var_equal_to(const VT T::* mvp)421 mem_var_equal_to (const VT T::*mvp)
422 {
423     return (const_mem_var2_t<equal_to<VT>,T,VT> (mvp, equal_to<VT>()));
424 }
425 
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>
mem_var_less(const VT T::* mvp)430 mem_var_less (const VT T::*mvp)
431 {
432     return (const_mem_var2_t<less<VT>,T,VT> (mvp, less<VT>()));
433 }
434 
435 //----------------------------------------------------------------------
436 // Dereference adaptors (uSTL extension)
437 //----------------------------------------------------------------------
438 
439 #ifndef DOXYGEN_SHOULD_SKIP_THIS
440 
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     };										\
453 										\
454     template <typename T, typename Function>					\
455     inline ClassName<T,Function> _dereference (Function pfn, FunctorKey)	\
456     {										\
457 	return (ClassName<T,Function> (pfn));					\
458     }
459 
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)); }
464 
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))
469 
470 #define dereference(f) _dereference(f,f)
471 
472 #undef DEREF_UNARY_ARGS
473 #undef DEREF_BINARY_ARGS
474 
475 #endif
476 
477 } // namespace ustl
478 
479 #endif
480 
481