#include "prelude.h" #include using std::cout; using std::endl; using namespace fcpp; // This file shows how to use syntax tricks to make // f _o_ g // be the same as // compose(f,g) // // Futhermore, f and g don't even have to be functoids; they could be // plain function pointers. ////////////////////////////////////////////////////////////////////// // ptr_to_fun clever cheat ////////////////////////////////////////////////////////////////////// struct PtrToFun { template struct Sig : public FunType {}; template struct Sig : public FunType > {}; template struct Sig : public FunType > {}; template struct Sig : public FunType > > {}; template struct Sig : public FunType > > {}; template struct Sig : public FunType > > {}; template struct Sig : public FunType > > {}; template struct Sig : public FunType > {}; template inline F operator()( F f ) const { return f; } template inline ptr_to_nullary_function operator()(Result (*x)()) const { return ptr_to_nullary_function(x); } template inline ptr_to_unary_function operator()(Result (*x)(Arg)) const { return ptr_to_unary_function(x); } template inline Curryable2 > operator()(Result (*x)(Arg1, Arg2)) const { return makeCurryable2( ptr_to_binary_function(x) ); } template inline Curryable3 > operator()(Result (*x)(Arg1, Arg2, Arg3)) const { return makeCurryable3( ptr_to_ternary_function(x) ); } template inline Curryable3 > operator()(Result (Arg1::*x)(Arg2,Arg3)) const { return makeCurryable3( ptr_to_mem_binary_function(x) ); } template inline Curryable2 > operator()(Result (Arg1::*x)(Arg2)) const { return makeCurryable2( ptr_to_mem_unary_function(x) ); } template inline ptr_to_mem_nullary_function operator()(Result (Arg1::*x)()) const { return ptr_to_mem_nullary_function(x); } } xptr_to_fun; ////////////////////////////////////////////////////////////////////// // _o_ compose 'operator' ////////////////////////////////////////////////////////////////////// class Dummy {} compose_dummy; template class Dummy2 { F f; Dummy2( const F& ff ) : f(ff) {} template friend Dummy2 operator%( FF f, Dummy ); template friend typename Compose1::Sig::ResultType, typename PtrToFun::Sig::ResultType>::ResultType operator%( const Dummy2& f, G g ); }; template Dummy2 operator%( F f, Dummy ) { return Dummy2(f); } template typename Compose1::Sig::ResultType, typename PtrToFun::Sig::ResultType>::ResultType operator%( const Dummy2& f, G g ) { return compose( xptr_to_fun(f.f), xptr_to_fun(g) ); } #define _o_ % compose_dummy % ////////////////////////////////////////////////////////////////////// // main program ////////////////////////////////////////////////////////////////////// int f(int x) { return 2*x + 1; } int g(int x) { return 3*x + 1; } int h(int x) { return 5*x + 1; } int main() { cout << f(g(h(1))) << endl; cout << f(g(h(2))) << endl; cout << compose( ptr_to_fun(f), compose( ptr_to_fun(g), ptr_to_fun(h) ) )(1) << endl; cout << compose( ptr_to_fun(f), compose( ptr_to_fun(g), ptr_to_fun(h) ) )(2) << endl; cout << compose( compose( ptr_to_fun(f), ptr_to_fun(g)), ptr_to_fun(h) )(2) << endl; cout << (ptr_to_fun(f) _o_ ptr_to_fun(g) _o_ ptr_to_fun(h)) (1) << endl; cout << (ptr_to_fun(f) _o_ ptr_to_fun(g) _o_ ptr_to_fun(h)) (2) << endl; cout << (f _o_ g _o_ h) (1) << endl; cout << (f _o_ g _o_ h) (2) << endl; cout << (equal(69) _o_ f _o_ g _o_ ptr_to_fun(h)) (2) << endl; }