00001 
00002 #ifndef INSTIGATE_STL_FUNCTIONAL_HPP
00003 #define INSTIGATE_STL_FUNCTIONAL_HPP
00004 
00052 
00053 #include "concept.hpp"
00054 
00055 
00056 #include <generic/base.hpp>
00057 
00058 
00059 
00060 
00061 namespace instigate {
00062         namespace stl {
00063 
00064                 template <typename UF> 
00065                 struct ubinder;
00066 
00067                 template <typename UF, typename Value>
00068                 ubinder<UF> bind( UF, const Value& );
00069 
00070                 template <typename BF> 
00071                 struct bbinder;
00072 
00073                 template <typename BF, typename Value1, typename Value2 > 
00074                 bbinder<BF> bind( BF f, const Value1& x, const Value2& y ); 
00075 
00076                 template <typename BF> 
00077                 struct bbinder1st;
00078 
00079                 template <typename BF, typename Value> 
00080                 bbinder1st<BF> bind1st( BF f, const Value& x );
00081 
00082                 template <typename BF> 
00083                 struct bbinder2nd;
00084 
00085                 template <typename BF, typename Value> 
00086                 bbinder2nd<BF> bind2nd( BF f, const Value& x );
00087 
00088                 template <typename TF> 
00089                 struct tbinder;
00090 
00091                 template <typename TF, typename Value1, typename Value2,
00092                          typename Value3> 
00093                 tbinder<TF> bind( TF f, const Value1& x, const Value2& y,
00094                                 const Value3& z);
00095 
00096                 template <typename TF> 
00097                         struct tbinder1st;
00098 
00099                 template <typename TF, typename Value> 
00100                 tbinder1st<TF> 
00101                 tbind1st( TF f, const Value& x);
00102 
00103                 template <typename TF> 
00104                 struct tbinder2nd;
00105 
00106                 template <typename TF, typename Value > 
00107                 tbinder2nd<TF> 
00108                 tbind2nd( TF f, const Value& y );
00109 
00110                 template <typename TF> 
00111                 struct tbinder3rd;
00112 
00113                 template <typename TF, typename Value> 
00114                 tbinder3rd<TF> 
00115                 tbind3rd( TF f, const Value& z );
00116 
00117                 template <typename BF, typename UF1, typename UF2>
00118                 class binary_compose;
00119 
00120                 template <typename BF, typename UF1, typename UF2>
00121                 binary_compose<BF, UF1, UF2> 
00122                 compose( BF b, UF1 f1, UF2 f2 );
00123 
00124                 template <typename UF1, typename UF2>
00125                 class unary_compose;
00126 
00127                 template <typename UF1, typename UF2>
00128                 unary_compose<UF1, UF2> 
00129                 compose( UF1 f1, UF2 f2 );
00130 
00131                 template <typename T>
00132                 class constant_generator;
00133 
00134                 template <typename BP> 
00135                 struct bnot2;
00136 
00137                 template <typename BP>
00138                 bnot2<BP>
00139                 not2(BP p);
00140 
00141                 template <typename UP> 
00142                 struct unot1;
00143 
00144                 template <typename UP>
00145                 unot1<UP>
00146                 not1(UP p);
00147         } 
00148 } 
00149 
00168 template <typename UF>
00169 struct instigate::stl::ubinder
00170 {
00171 private:
00172         typedef typename instigate::stl::unary_function::interface<UF> UFI;
00173         UF m_function;
00174         typename UFI::argument_type m_argument;
00175 
00176 public:
00178         typedef typename UFI::result_type result_type;
00179 
00185         result_type operator() () const
00186         {
00187                 return UFI::invoke(m_function, m_argument);
00188         }
00189 
00196         ubinder(UF f, typename UFI::argument_type x) throw()
00197                 : m_function(f)
00198                 , m_argument(x)
00199         {}
00200 
00201 }; 
00202 
00216 template <typename UF, typename Value>
00217 inline instigate::stl::ubinder<UF> 
00218 instigate::stl::bind(UF f, const Value& x)
00219 {
00220         CHECK(instigate::stl::unary_function::requirements<UF>);
00221         typedef instigate::stl::unary_function::interface<UF> UFI;
00222         CHECK_CONVERTIBILITY(Value, typename UFI::argument_type);
00223         return instigate::stl::ubinder<UF>(f, x);
00224 }
00225 
00243 template <typename BF>
00244 struct instigate::stl::bbinder
00245 {
00246 private:
00247         typedef typename instigate::stl::binary_function::interface<BF> BFI;
00248         BF m_function;
00249         typename BFI::first_argument_type m_argument1;
00250         typename BFI::second_argument_type m_argument2;
00251 public:
00253         typedef typename BFI::result_type result_type;
00254         
00260         result_type operator() ()
00261         {
00262                 return BFI::invoke(m_function, m_argument1, m_argument2);
00263         }
00264 
00272         bbinder(const BF& f, const typename BFI::first_argument_type& x, 
00273                         const typename BFI::second_argument_type& y)  throw()
00274                  : m_function(f)
00275                  , m_argument1(x)
00276                  , m_argument2(y)
00277         {}
00278 
00279 }; 
00280 
00296 template <typename BF, typename Value1, typename Value2>
00297 inline instigate::stl::bbinder<BF> 
00298 instigate::stl::bind(BF f, const Value1& x, const Value2& y) 
00299 {
00300         CHECK(instigate::stl::binary_function::requirements<BF>);
00301         typedef instigate::stl::binary_function::interface<BF> BFI;
00302         CHECK_CONVERTIBILITY(Value1, typename BFI::first_argument_type);
00303         CHECK_CONVERTIBILITY(Value2, typename BFI::second_argument_type);
00304         return instigate::stl::bbinder<BF>(f, x, y);
00305 }
00306 
00313 template <typename BF>
00314 struct instigate::stl::bbinder1st
00315 {
00316 private:
00317         typedef typename instigate::stl::binary_function::interface<BF> BFI;
00318         BF m_function;
00319         typename BFI::first_argument_type m_argument;
00320 public:
00322         typedef typename BFI::result_type result_type;
00323         
00325         typedef typename BFI::second_argument_type argument_type;
00326         
00333         result_type operator() (argument_type v) const
00334         {
00335                 return BFI::invoke(m_function, m_argument, v);
00336         }
00337         
00344         bbinder1st(BF f, typename BFI::first_argument_type x)  throw()
00345                  : m_function(f)
00346                  , m_argument(x)
00347         {}
00348 
00349 }; 
00350 
00364 template <typename BF, typename Value>
00365 inline instigate::stl::bbinder1st<BF> 
00366 instigate::stl::bind1st( BF f, const Value& x )
00367 {
00368         CHECK(instigate::stl::binary_function::requirements<BF>);
00369         typedef instigate::stl::binary_function::interface<BF> BFI;
00370         CHECK_CONVERTIBILITY(Value, typename BFI::first_argument_type);
00371         return instigate::stl::bbinder1st<BF>(f, x);
00372 }
00373 
00382 template <typename BF>
00383 class instigate::stl::bbinder2nd
00384 {
00385 private:
00386         typedef typename instigate::stl::binary_function::interface<BF> BFI;
00387         BF m_function;
00388         typename BFI::second_argument_type m_argument;
00389 public:
00391         typedef typename BFI::result_type result_type;
00392 
00394         typedef typename BFI::first_argument_type argument_type;
00395 
00402         result_type operator() (argument_type v) const
00403         {
00404                 return BFI::invoke(m_function, v, m_argument);
00405         }
00406 
00413         bbinder2nd(BF f, typename BFI::second_argument_type x)  throw()
00414                  : m_function(f)
00415                  , m_argument(x)
00416         {}
00417 
00418 }; 
00419 
00434 template <typename BF, typename Value>
00435 inline instigate::stl::bbinder2nd<BF> 
00436 instigate::stl::bind2nd(BF f, const Value& x)
00437 {
00438         CHECK(instigate::stl::binary_function::requirements<BF>);
00439         typedef instigate::stl::binary_function::interface<BF> BFI;
00440         CHECK_CONVERTIBILITY(Value, typename BFI::second_argument_type);
00441         return instigate::stl::bbinder2nd<BF>(f, x);
00442 }
00443 
00452 template <typename TF>
00453 struct instigate::stl::tbinder
00454 {
00455 private:
00456         typedef typename instigate::stl::ternary_function::interface<TF> TFI;
00457         TF m_function;
00458         typename TFI::first_argument_type m_argument1;
00459         typename TFI::second_argument_type m_argument2;
00460         typename TFI::third_argument_type m_argument3;
00461 
00462 public:
00464         typedef typename TFI::result_type result_type;
00465 
00472         result_type operator() ()
00473         {
00474                 return TFI::invoke(m_function, m_argument1, m_argument2,
00475                                         m_argument3);
00476         }
00477 
00486         tbinder(
00487                 TF f, 
00488                 const typename TFI::first_argument_type& x, 
00489                 const typename TFI::second_argument_type& y,
00490                 const typename TFI::third_argument_type& z)  throw()
00491                  : m_function(f)
00492                  , m_argument1(x)
00493                  , m_argument2(y)
00494                  , m_argument3(z)
00495         {}
00496 
00497 }; 
00498 
00516 template <typename TF, typename Value1, typename Value2, typename Value3>
00517 inline instigate::stl::tbinder<TF> 
00518 instigate::stl::bind(TF f, const Value1& x,const Value2& y, const Value3& z)
00519 {
00520         CHECK(instigate::stl::ternary_function::requirements<TF>);
00521         typedef instigate::stl::ternary_function::interface<TF> TFI;
00522         CHECK_CONVERTIBILITY(Value1, typename TFI::first_argument_type);
00523         CHECK_CONVERTIBILITY(Value2, typename TFI::second_argument_type);
00524         CHECK_CONVERTIBILITY(Value3, typename TFI::third_argument_type);
00525         return instigate::stl::tbinder<TF>(f, x, y, z);
00526 }
00527 
00536 template <typename TF>
00537 struct instigate::stl::tbinder1st
00538 {
00539 private:
00540         typedef typename instigate::stl::ternary_function::interface<TF> TFI;
00541         TF m_function;
00542         typename TFI::first_argument_type m_argument;
00543 
00544 public:
00546         typedef typename TFI::result_type result_type;
00547 
00549         typedef typename TFI::second_argument_type first_argument_type;
00550 
00552         typedef typename TFI::third_argument_type second_argument_type;
00553 
00560         result_type operator() (first_argument_type v, second_argument_type w) const
00561         {
00562                 return TFI::invoke(m_function, m_argument, v, w);
00563         }
00564 
00565 
00572         tbinder1st(TF f, typename TFI::first_argument_type x)  throw()
00573                  : m_function(f)
00574                  , m_argument(x)
00575         {}
00576 
00577 }; 
00578 
00593 template <typename TF, typename Value>
00594 inline instigate::stl::tbinder1st<TF> 
00595 instigate::stl::tbind1st( TF f, const Value& x )
00596 {
00597         CHECK(instigate::stl::ternary_function::requirements<TF>);
00598         typedef instigate::stl::ternary_function::interface<TF> TFI;
00599         CHECK_CONVERTIBILITY(Value, typename TFI::first_argument_type);
00600         return instigate::stl::tbinder1st<TF>(f, x);
00601 }
00602 
00612 template <typename TF>
00613 class instigate::stl::tbinder2nd
00614 {
00615 private:
00616         typedef typename instigate::stl::ternary_function::interface<TF> TFI;
00617         TF m_function;
00618         typename TFI::second_argument_type m_argument;
00619 
00620 public:
00622         typedef typename TFI::result_type result_type;
00623 
00625         typedef typename TFI::first_argument_type first_argument_type;
00626 
00628         typedef typename TFI::third_argument_type second_argument_type;
00629 
00636         result_type operator() (first_argument_type v, second_argument_type w)
00637         {
00638                 return TFI::invoke(m_function, v, m_argument, w);
00639         }
00640 
00647         tbinder2nd(TF f, typename TFI::second_argument_type x)  throw()
00648                 : m_function(f)
00649                 , m_argument(x)
00650         {}
00651 
00652 }; 
00653 
00668 template <typename TF, typename Value>
00669 inline instigate::stl::tbinder2nd<TF> 
00670 instigate::stl::tbind2nd( TF f, const Value& x )
00671 {
00672         CHECK(instigate::stl::ternary_function::requirements<TF>);
00673         typedef instigate::stl::ternary_function::interface<TF> TFI;
00674         CHECK_CONVERTIBILITY(Value, typename TFI::second_argument_type);
00675         return instigate::stl::tbinder2nd<TF>(f, x);
00676 }
00677 
00686 template <typename TF>
00687 class instigate::stl::tbinder3rd
00688 {
00689 private:
00690         typedef typename instigate::stl::ternary_function::interface<TF> TFI;
00691         TF m_function;
00692         typename TFI::third_argument_type m_argument;
00693 
00694 public:
00696         typedef typename TFI::result_type result_type;
00697 
00699         typedef typename TFI::first_argument_type first_argument_type;
00700 
00702         typedef typename TFI::second_argument_type second_argument_type;
00703 
00710         result_type operator() (first_argument_type v, second_argument_type w)
00711         {
00712                 return TFI::invoke(m_function, v, w, m_argument);
00713         }
00714 
00721         tbinder3rd(TF f, typename TFI::third_argument_type x)  throw()
00722                 : m_function(f)
00723                 , m_argument(x)
00724         {}
00725 
00726 }; 
00727 
00742 template <typename TF, typename Value>
00743 inline instigate::stl::tbinder3rd<TF> 
00744 instigate::stl::tbind3rd( TF f, const Value& x )
00745 {
00746         CHECK(instigate::stl::ternary_function::requirements<TF>);
00747         typedef instigate::stl::ternary_function::interface<TF> TFI;
00748         CHECK_CONVERTIBILITY(Value, typename TFI::third_argument_type);
00749         return instigate::stl::tbinder3rd<TF>(f, x);
00750 }
00751 
00758 template <typename UF1, typename UF2>
00759 class instigate::stl::unary_compose 
00760 {
00761 private:
00762         UF1 m_uf1;
00763         UF2 m_uf2;
00764 
00765         typedef typename instigate::stl::unary_function::interface<UF1> UF1I;
00766         typedef typename instigate::stl::unary_function::interface<UF2> UF2I;
00767 public:
00769         typedef typename UF1I::result_type result_type;
00770 
00772         typedef typename UF2I::argument_type argument_type;
00773 
00782         result_type operator() (argument_type a) const
00783         {
00784                 return UF1I::invoke(m_uf1, UF2I::invoke(m_uf2, a));
00785         }
00786         
00795         unary_compose(UF1 uf1, UF2 uf2) 
00796                 : m_uf1(uf1)
00797                 , m_uf2(uf2)
00798         {
00799         }
00800 };
00801 
00807 template <typename UF1, typename UF2>
00808 instigate::stl::unary_compose<UF1, UF2> 
00809 instigate::stl::compose(UF1 f1, UF2 f2)
00810 {
00811         CHECK(instigate::stl::unary_function::requirements<UF1>);
00812         CHECK(instigate::stl::unary_function::requirements<UF2>);
00813         typedef instigate::stl::unary_function::interface<UF1> UFI1;
00814         typedef instigate::stl::unary_function::interface<UF2> UFI2;
00815         CHECK_CONVERTIBILITY(typename UFI2::result_type, 
00816                         typename UFI1::argument_type);
00817         return instigate::stl::unary_compose<UF1, UF2>(f1, f2);
00818 }
00819 
00827 template <typename BF, typename UF1, typename UF2>
00828 class instigate::stl::binary_compose 
00829 {
00830 private:
00831         BF m_bf;
00832         UF1 m_uf1;
00833         UF2 m_uf2;
00834         typedef typename instigate::stl::binary_function::interface<BF> BFI;
00835         typedef typename instigate::stl::unary_function::interface<UF1> UF1I;
00836         typedef typename instigate::stl::unary_function::interface<UF2> UF2I;
00837 public:
00839         typedef typename BFI::result_type result_type;
00840 
00842         typedef typename UF1I::argument_type argument_type;
00843 
00852         result_type operator() (argument_type a)
00853         {
00854                 return BFI::invoke(m_bf, UF1I::invoke(m_uf1, a), 
00855                                 UF2I::invoke(m_uf2, a));
00856         }
00857 
00868         binary_compose(BF bf, UF1 uf1, UF2 uf2) 
00869                 : m_bf(bf)
00870                 , m_uf1(uf1)
00871                 , m_uf2(uf2)
00872         {
00873         }
00874 };
00875 
00876 
00882 template <typename BF, typename UF1, typename UF2>
00883 instigate::stl::binary_compose<BF, UF1, UF2> 
00884 instigate::stl::compose(BF b, UF1 f1, UF2 f2)
00885 {
00886         CHECK(instigate::stl::binary_function::requirements<BF>);
00887         CHECK(instigate::stl::unary_function::requirements<UF1>);
00888         CHECK(instigate::stl::unary_function::requirements<UF2>);
00889         typedef instigate::stl::binary_function::interface<BF> BFI;
00890         typedef instigate::stl::unary_function::interface<UF1> UFI1;
00891         typedef instigate::stl::unary_function::interface<UF2> UFI2;
00892         CHECK_CONVERTIBILITY(typename UFI1::result_type, 
00893                              typename BFI::first_argument_type);
00894         CHECK_CONVERTIBILITY(typename UFI2::result_type, 
00895                              typename BFI::second_argument_type);
00896         return instigate::stl::binary_compose<BF, UF1, UF2>(b, f1, f2);
00897 }
00898 
00903 template <typename T>
00904 class instigate::stl::constant_generator {
00905 private:
00906         T m_t;
00907         
00908 public:
00912         T operator()()        
00913         {
00914                 return m_t;
00915         }
00916 
00921         constant_generator(T t)
00922                 : m_t(t)
00923         {
00924         }
00925                 
00926 }; 
00927 
00944 template <typename BP>
00945 struct instigate::stl::bnot2
00946 {
00947 private:
00948         typedef typename instigate::stl::binary_predicate::interface<BP> BPI;
00949         BP m_predicate;
00950 
00951 public:
00953         typedef typename BPI::result_type result_type;
00954 
00956         typedef typename BPI::first_argument_type first_argument_type;
00957 
00959         typedef typename BPI::second_argument_type second_argument_type;
00960 
00969         result_type operator() (first_argument_type f,
00970                         second_argument_type s)
00971         {
00972                 return ! BPI::invoke(m_predicate, f, s);
00973         }
00974 
00980         bnot2(BP p) throw()
00981                 : m_predicate(p)
00982         {}
00983 
00984 }; 
00985 
00996 template <typename BP>
00997 inline instigate::stl::bnot2<BP> 
00998 instigate::stl::not2(BP p)
00999 {
01000         CHECK(instigate::stl::binary_predicate::requirements<BP>);
01001         return instigate::stl::bnot2<BP>(p);
01002 }
01003 
01020 template <typename UP>
01021 struct instigate::stl::unot1
01022 {
01023 private:
01024         typedef typename instigate::stl::unary_predicate::interface<UP> UPI;
01025         UP m_predicate;
01026 
01027 public:
01029         typedef typename UPI::result_type result_type;
01030 
01032         typedef typename UPI::argument_type argument_type;
01033 
01041         result_type operator() (argument_type a)
01042         {
01043                 return ! UPI::invoke(m_predicate, a);
01044         }
01045 
01051         unot1(UP p) throw()
01052                 : m_predicate(p)
01053         {}
01054 
01055 }; 
01056 
01067 template <typename UP>
01068 inline instigate::stl::unot1<UP> 
01069 instigate::stl::not1(UP p)
01070 {
01071         CHECK(instigate::stl::unary_predicate::requirements<UP>);
01072         return instigate::stl::unot1<UP>(p);
01073 }
01074 
01075 
01076 
01077 
01078 #endif // INSTIGATE_STL_FUNCTIONAL_HPP