Home | History | Annotate | Download | only in ustl-1.0
      1 // This file is part of the ustl library, an STL implementation.
      2 //
      3 // Copyright (C) 2005 by Mike Sharov <msharov (at) 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
     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); } };
     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:
    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.
    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:
    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.
    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>
    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>
    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:
    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;
    167 };
    168 
    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)
    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:
    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;
    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:
    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;
    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>
    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>
    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:
    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))
    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>
    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:
    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))
    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>
    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*,		)
    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>
    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>
    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>
    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