1 // 2 // Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis 3 // 4 // Permission to use, copy, modify, distribute and sell this software 5 // and its documentation for any purpose is granted without fee, 6 // provided that the above copyright notice and this permission notice 7 // appear in all source code copies and supporting documentation. The 8 // software is provided "as is" without any express or implied 9 // warranty. 10 11 #ifndef FCPP_FULL_DOT_H 12 #define FCPP_FULL_DOT_H 13 14 #include "smart.h" 15 #include "curry.h" 16 #include "pre_lambda.h" 17 18 namespace fcpp { 19 20 ////////////////////////////////////////////////////////////////////// 21 // Full functoids 22 ////////////////////////////////////////////////////////////////////// 23 // Just as Curryable2/Curryable3 serve as wrappers which decorate 24 // functoids to give them 'curryability', FullN are wrappers to give 25 // functoids _all_ the 'features' that functoids can have. The current 26 // "extra feature set" for functoids is 27 // - curryability (ability to call with fewer args) 28 // - lambda-awareness (operator[] for use inside lambda) 29 // - smartness (inherited typedefs to answer introspective questions) 30 // The FullN classes just combine all of the features into one 31 // uber-wrapper which does it all. 32 33 // Don't forget that any features added here need to be added to 34 // the indirect functoids in function.h, too. 35 // And also to the Uncurryable class in prelude.h. 36 // FIX THIS take a good look at Uncurry; it may have pre-dated smartness 37 // and can now be written more sanely...? 38 template <class F> 39 class Full0 40 : public SmartFunctoid0, public CFunType<typename RT<F>::ResultType> { 41 F f; 42 public: Full0()43 Full0() : f() {} Full0(const F & ff)44 Full0( const F& ff ) : f(ff) {} 45 #ifdef FCPP_ENABLE_LAMBDA 46 typedef Full0 This; 47 template <class A> typename fcpp_lambda::BracketCallable<This,A>::Result 48 operator[]( const A& a ) const 49 { return fcpp_lambda::BracketCallable<This,A>::go( *this, a ); } 50 #endif operator()51 inline typename RT<F>::ResultType operator()() const { 52 return f(); 53 } 54 }; 55 56 template <class F> 57 class Full1 : public SmartFunctoid1 { 58 F f; 59 public: Full1()60 Full1() : f() {} Full1(const F & ff)61 Full1( const F& ff ) : f(ff) {} 62 #ifdef FCPP_ENABLE_LAMBDA 63 typedef Full1 This; 64 template <class A> typename fcpp_lambda::BracketCallable<This,A>::Result 65 operator[]( const A& a ) const 66 { return fcpp_lambda::BracketCallable<This,A>::go( *this, a ); } 67 #endif 68 template <class T> struct Sig 69 : public FunType<typename RT<F,T>::Arg1Type, 70 typename RT<F,T>::ResultType> {}; 71 template <class T> operator()72 inline typename Sig<T>::ResultType operator()( const T& x ) const { 73 return f(x); 74 } 75 }; 76 77 template <class F> 78 class Full2 : public SmartFunctoid2 { 79 F f; 80 public: Full2()81 Full2() : f() {} Full2(const F & ff)82 Full2( const F& ff ) : f(ff) {} 83 #ifdef FCPP_ENABLE_LAMBDA 84 typedef Full2 This; 85 template <class A> typename fcpp_lambda::BracketCallable<This,A>::Result 86 operator[]( const A& a ) const 87 { return fcpp_lambda::BracketCallable<This,A>::go( *this, a ); } 88 #endif 89 ///////////// copied from Curryable2; added impl:: to binders ////// 90 template <class X, class Y=void> 91 struct Sig 92 : public FunType<typename F::template Sig<X,Y>::Arg1Type, 93 typename F::template Sig<X,Y>::Arg2Type, 94 typename RT<F,X,Y>::ResultType> {}; 95 96 template <class X> 97 struct Sig<X,void> : public FunType<X,Full1<impl::binder1of2<F,X> > > {}; 98 99 template <class Y> 100 struct Sig<AutoCurryType,Y> 101 : public FunType<AutoCurryType,Y,Full1<impl::binder2of2<F,Y> > > {}; 102 103 template <class X> 104 struct Sig<X,AutoCurryType> 105 : public FunType<X,AutoCurryType,Full1<impl::binder1of2<F,X> > > {}; 106 107 template <class X> 108 typename Sig<X>::ResultType operator()( const X& x ) const { 109 return makeFull1( impl::binder1of2<F,X>(f,x) ); 110 } 111 template <class X, class Y> 112 inline typename Sig<X,Y>::ResultType 113 operator()( const X& x, const Y& y ) const { 114 // need partial specialization, so defer to a class helper 115 return impl::Curryable2Helper<typename Sig<X,Y>::ResultType,F,X,Y>::go(f,x,y); 116 } 117 ////////////////////////////////////////////////////////////////////// 118 }; 119 120 template <class F> 121 class Full3 : public SmartFunctoid3 { 122 F f; 123 public: 124 Full3() : f() {} 125 Full3( const F& ff ) : f(ff) {} 126 #ifdef FCPP_ENABLE_LAMBDA 127 typedef Full3 This; 128 template <class A> typename fcpp_lambda::BracketCallable<This,A>::Result 129 operator[]( const A& a ) const 130 { return fcpp_lambda::BracketCallable<This,A>::go( *this, a ); } 131 #endif 132 ///////////// copied from Curryable3; added impl:: to all binders // 133 template <class X, class Y=void, class Z=void> 134 struct Sig 135 : public FunType<typename F::template Sig<X,Y,Z>::Arg1Type, 136 typename F::template Sig<X,Y,Z>::Arg2Type, 137 typename F::template Sig<X,Y,Z>::Arg3Type, 138 typename RT<F,X,Y,Z>::ResultType> {}; 139 140 template <class X,class Y> struct Sig<X,Y,void> 141 : public FunType<X,Y,Full1<impl::binder1and2of3<F,X,Y> > > {}; 142 143 template <class X> struct Sig<X,AutoCurryType,void> 144 : public FunType<X,AutoCurryType,Full2<impl::binder1of3<F,X> > > {}; 145 146 template <class Y> struct Sig<AutoCurryType,Y,void> 147 : public FunType<AutoCurryType,Y,Full2<impl::binder2of3<F,Y> > > {}; 148 149 template <class X> struct Sig<X,void,void> 150 : public FunType<X,Full2<impl::binder1of3<F,X> > > {}; 151 152 template <class X> struct Sig<X,AutoCurryType,AutoCurryType> 153 : public FunType<X,AutoCurryType,AutoCurryType, 154 Full2<impl::binder1of3<F,X> > > {}; 155 156 template <class Y> struct Sig<AutoCurryType,Y,AutoCurryType> 157 : public FunType<AutoCurryType,Y,AutoCurryType, 158 Full2<impl::binder2of3<F,Y> > > {}; 159 160 template <class Z> struct Sig<AutoCurryType,AutoCurryType,Z> 161 : public FunType<AutoCurryType,AutoCurryType,Z, 162 Full2<impl::binder3of3<F,Z> > > {}; 163 164 template <class X,class Z> struct Sig<X,AutoCurryType,Z> 165 : public FunType<X,AutoCurryType,Z,Full1<impl::binder1and3of3<F,X,Z> > > {}; 166 167 template <class Y,class Z> struct Sig<AutoCurryType,Y,Z> 168 : public FunType<AutoCurryType,Y,Z,Full1<impl::binder2and3of3<F,Y,Z> > > {}; 169 170 template <class X,class Y> struct Sig<X,Y,AutoCurryType> 171 : public FunType<X,Y,AutoCurryType,Full1<impl::binder1and2of3<F,X,Y> > > {}; 172 173 template <class X,class Y> 174 typename Sig<X,Y>::ResultType operator()( const X& x, const Y& y ) const { 175 // need partial specialization, so defer to a class helper 176 return impl::Curryable3Helper2<typename Sig<X,Y>::ResultType,F,X,Y>::go(f,x,y); 177 } 178 template <class X> 179 typename Sig<X>::ResultType operator()( const X& x ) const { 180 return makeFull2(impl::binder1of3<F,X>(f,x)); 181 } 182 183 template <class X, class Y, class Z> 184 inline typename Sig<X,Y,Z>::ResultType 185 operator()( const X& x, const Y& y, const Z& z ) const { 186 // need partial specialization, so defer to a class helper 187 return impl::Curryable3Helper<typename Sig<X,Y,Z>::ResultType,F,X,Y,Z> 188 ::go(f,x,y,z); 189 } 190 ////////////////////////////////////////////////////////////////////// 191 }; 192 193 template <class F> Full0<F> makeFull0( const F& f ) { return Full0<F>(f); } 194 template <class F> Full1<F> makeFull1( const F& f ) { return Full1<F>(f); } 195 template <class F> Full2<F> makeFull2( const F& f ) { return Full2<F>(f); } 196 template <class F> Full3<F> makeFull3( const F& f ) { return Full3<F>(f); } 197 198 ////////////////////////////////////////////////////////////////////// 199 // Definitions of stuff heretofore put-off... 200 ////////////////////////////////////////////////////////////////////// 201 // from curry.h: 202 typedef Full1<impl::Const> Const; 203 typedef Full2<impl::Bind1of1> Bind1of1; 204 205 typedef Full2<impl::Bind1of2> Bind1of2; 206 typedef Full2<impl::Bind2of2> Bind2of2; 207 typedef Full3<impl::Bind1and2of2> Bind1and2of2; 208 209 // FIX THIS? I never noticed: the only 4-arg functoid in the entire library 210 typedef impl::Bind1and2and3of3 Bind1and2and3of3; 211 212 typedef Full3<impl::Bind1and2of3> Bind1and2of3; 213 typedef Full3<impl::Bind2and3of3> Bind2and3of3; 214 typedef Full3<impl::Bind1and3of3> Bind1and3of3; 215 typedef Full2<impl::Bind1of3> Bind1of3; 216 typedef Full2<impl::Bind2of3> Bind2of3; 217 typedef Full2<impl::Bind3of3> Bind3of3; 218 219 FCPP_MAYBE_NAMESPACE_OPEN 220 FCPP_MAYBE_EXTERN Const const_; // C++ keyword, so add trailing underscore 221 FCPP_MAYBE_EXTERN Bind1of1 bind1of1; 222 223 FCPP_MAYBE_EXTERN Bind1of2 bind1of2; 224 FCPP_MAYBE_EXTERN Bind2of2 bind2of2; 225 FCPP_MAYBE_EXTERN Bind1and2of2 bind1and2of2; 226 227 FCPP_MAYBE_EXTERN Bind1and2and3of3 bind1and2and3of3; 228 FCPP_MAYBE_EXTERN Bind1and2of3 bind1and2of3; 229 FCPP_MAYBE_EXTERN Bind2and3of3 bind2and3of3; 230 FCPP_MAYBE_EXTERN Bind1and3of3 bind1and3of3; 231 FCPP_MAYBE_EXTERN Bind1of3 bind1of3; 232 FCPP_MAYBE_EXTERN Bind2of3 bind2of3; 233 FCPP_MAYBE_EXTERN Bind3of3 bind3of3; 234 FCPP_MAYBE_NAMESPACE_CLOSE 235 236 } // end namespace fcpp 237 238 #endif 239