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