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