Christopher Haster / funcptr

Dependents:   SimpleHTTPExample

Revision:
5:5c91c61f50b6
Child:
8:71037a47492d
diff -r 627e19790dd9 -r 5c91c61f50b6 Composer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Composer.h	Sun Apr 17 14:54:18 2016 -0500
@@ -0,0 +1,496 @@
+/*  Composer
+ *  Static function composition
+ */
+#ifndef COMPOSER_H
+#define COMPOSER_H
+
+#include "FuncPtr.h"
+
+
+/** Static function composition
+ */
+template <typename F, typename G>
+class Composer;
+
+/** Static function composition
+ */
+template <typename R, typename B0, typename A0, typename A1, typename A2, typename A3>
+class Composer<R(B0), B0(A0, A1, A2, A3)> {
+public:
+    /** Create an uncomposed Composer
+     */
+    Composer() {}
+
+    /** Create a Composer, composing two functions
+     */
+    Composer(FuncPtr<R(B0)> f, FuncPtr<B0(A0, A1, A2, A3)> g) {
+        attach(f, g);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename FT, typename FM>
+    Composer(FT *fobj, FM fmethod, FuncPtr<B0(A0, A1, A2, A3)> g) {
+        attach(fobj, fmethod, g);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename GT, typename GM>
+    Composer(FuncPtr<B0(A0, A1, A2, A3)> f, GT *gobj, GM gmethod) {
+        attach(f, gobj, gmethod);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename FT, typename FM, typename GT, typename GM>
+    Composer(FT *fobj, FM fmethod, GT *gobj, GM gmethod) {
+        attach(fobj, fmethod, gobj, gmethod);
+    }
+
+    /** Compose two functions
+     */
+    void attach(FuncPtr<R(B0)> f, FuncPtr<B0(A0, A1, A2, A3)> g) {
+        _f.attach(f);
+        _g.attach(g);
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename FT, typename FM>
+    void attach(FT *fobj, FM fmethod, FuncPtr<B0(A0, A1, A2, A3)> g) {
+        attach(FuncPtr<R(B0)>(fobj, fmethod), g);
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename GT, typename GM>
+    void attach(FuncPtr<R(B0)> f, GT *gobj, GM gmethod) {
+        attach(f, FuncPtr<B0(A0, A1, A2, A3)>(gobj, gmethod));
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename FT, typename FM, typename GT, typename GM>
+    void attach(FT *fobj, FM fmethod, GT *gobj, GM gmethod) {
+        attach(FuncPtr<R(B0)>(fobj, fmethod),
+               FuncPtr<B0(A0, A1, A2, A3)>(gobj, gmethod));
+    }
+
+    /** Call the composed functions
+     */
+    R call(A0 a0, A1 a1, A2 a2, A3 a3) {
+        return _f(_g(a0, a1, a2, a3));
+    }
+
+    /** Call the composed functions
+     */
+    R operator()(A0 a0, A1 a1, A2 a2, A3 a3) {
+        return call(a0, a1, a2, a3);
+    }
+
+    /** Test if functions have been composed
+     */
+    operator bool(void) const {
+        return _f && _g;
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param func Composer to call passed as void pointer
+     */
+    static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
+        return static_cast<Composer<R(B0), B0(A0, A1, A2, A3)>*>(func)
+                ->call(a0, a1, a2, a3);
+    }
+
+private:
+    FuncPtr<R(B0)> _f;
+    FuncPtr<B0(A0, A1, A2, A3)> _g;
+};
+
+/** Static function composition
+ */
+template <typename R, typename B0, typename A0, typename A1, typename A2>
+class Composer<R(B0), B0(A0, A1, A2)> {
+public:
+    /** Create an uncomposed Composer
+     */
+    Composer() {}
+
+    /** Create a Composer, composing two functions
+     */
+    Composer(FuncPtr<R(B0)> f, FuncPtr<B0(A0, A1, A2)> g) {
+        attach(f, g);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename FT, typename FM>
+    Composer(FT *fobj, FM fmethod, FuncPtr<B0(A0, A1, A2)> g) {
+        attach(fobj, fmethod, g);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename GT, typename GM>
+    Composer(FuncPtr<B0(A0, A1, A2)> f, GT *gobj, GM gmethod) {
+        attach(f, gobj, gmethod);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename FT, typename FM, typename GT, typename GM>
+    Composer(FT *fobj, FM fmethod, GT *gobj, GM gmethod) {
+        attach(fobj, fmethod, gobj, gmethod);
+    }
+
+    /** Compose two functions
+     */
+    void attach(FuncPtr<R(B0)> f, FuncPtr<B0(A0, A1, A2)> g) {
+        _f.attach(f);
+        _g.attach(g);
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename FT, typename FM>
+    void attach(FT *fobj, FM fmethod, FuncPtr<B0(A0, A1, A2)> g) {
+        attach(FuncPtr<R(B0)>(fobj, fmethod), g);
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename GT, typename GM>
+    void attach(FuncPtr<R(B0)> f, GT *gobj, GM gmethod) {
+        attach(f, FuncPtr<B0(A0, A1, A2)>(gobj, gmethod));
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename FT, typename FM, typename GT, typename GM>
+    void attach(FT *fobj, FM fmethod, GT *gobj, GM gmethod) {
+        attach(FuncPtr<R(B0)>(fobj, fmethod),
+               FuncPtr<B0(A0, A1, A2)>(gobj, gmethod));
+    }
+
+    /** Call the composed functions
+     */
+    R call(A0 a0, A1 a1, A2 a2) {
+        return _f(_g(a0, a1, a2));
+    }
+
+    /** Call the composed functions
+     */
+    R operator()(A0 a0, A1 a1, A2 a2) {
+        return call(a0, a1, a2);
+    }
+
+    /** Test if functions have been composed
+     */
+    operator bool(void) const {
+        return _f && _g;
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param func Composer to call passed as void pointer
+     */
+    static R thunk(void *func, A0 a0, A1 a1, A2 a2) {
+        return static_cast<Composer<R(B0), B0(A0, A1, A2)>*>(func)
+                ->call(a0, a1, a2);
+    }
+
+private:
+    FuncPtr<R(B0)> _f;
+    FuncPtr<B0(A0, A1, A2)> _g;
+};
+
+/** Static function composition
+ */
+template <typename R, typename B0, typename A0, typename A1>
+class Composer<R(B0), B0(A0, A1)> {
+public:
+    /** Create an uncomposed Composer
+     */
+    Composer() {}
+
+    /** Create a Composer, composing two functions
+     */
+    Composer(FuncPtr<R(B0)> f, FuncPtr<B0(A0, A1)> g) {
+        attach(f, g);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename FT, typename FM>
+    Composer(FT *fobj, FM fmethod, FuncPtr<B0(A0, A1)> g) {
+        attach(fobj, fmethod, g);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename GT, typename GM>
+    Composer(FuncPtr<B0(A0, A1)> f, GT *gobj, GM gmethod) {
+        attach(f, gobj, gmethod);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename FT, typename FM, typename GT, typename GM>
+    Composer(FT *fobj, FM fmethod, GT *gobj, GM gmethod) {
+        attach(fobj, fmethod, gobj, gmethod);
+    }
+
+    /** Compose two functions
+     */
+    void attach(FuncPtr<R(B0)> f, FuncPtr<B0(A0, A1)> g) {
+        _f.attach(f);
+        _g.attach(g);
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename FT, typename FM>
+    void attach(FT *fobj, FM fmethod, FuncPtr<B0(A0, A1)> g) {
+        attach(FuncPtr<R(B0)>(fobj, fmethod), g);
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename GT, typename GM>
+    void attach(FuncPtr<R(B0)> f, GT *gobj, GM gmethod) {
+        attach(f, FuncPtr<B0(A0, A1)>(gobj, gmethod));
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename FT, typename FM, typename GT, typename GM>
+    void attach(FT *fobj, FM fmethod, GT *gobj, GM gmethod) {
+        attach(FuncPtr<R(B0)>(fobj, fmethod),
+               FuncPtr<B0(A0, A1)>(gobj, gmethod));
+    }
+
+    /** Call the composed functions
+     */
+    R call(A0 a0, A1 a1) {
+        return _f(_g(a0, a1));
+    }
+
+    /** Call the composed functions
+     */
+    R operator()(A0 a0, A1 a1) {
+        return call(a0, a1);
+    }
+
+    /** Test if functions have been composed
+     */
+    operator bool(void) const {
+        return _f && _g;
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param func Composer to call passed as void pointer
+     */
+    static R thunk(void *func, A0 a0, A1 a1) {
+        return static_cast<Composer<R(B0), B0(A0, A1)>*>(func)
+                ->call(a0, a1);
+    }
+
+private:
+    FuncPtr<R(B0)> _f;
+    FuncPtr<B0(A0, A1)> _g;
+};
+
+/** Static function composition
+ */
+template <typename R, typename B0, typename A0>
+class Composer<R(B0), B0(A0)> {
+public:
+    /** Create an uncomposed Composer
+     */
+    Composer() {}
+
+    /** Create a Composer, composing two functions
+     */
+    Composer(FuncPtr<R(B0)> f, FuncPtr<B0(A0)> g) {
+        attach(f, g);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename FT, typename FM>
+    Composer(FT *fobj, FM fmethod, FuncPtr<B0(A0)> g) {
+        attach(fobj, fmethod, g);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename GT, typename GM>
+    Composer(FuncPtr<B0(A0)> f, GT *gobj, GM gmethod) {
+        attach(f, gobj, gmethod);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename FT, typename FM, typename GT, typename GM>
+    Composer(FT *fobj, FM fmethod, GT *gobj, GM gmethod) {
+        attach(fobj, fmethod, gobj, gmethod);
+    }
+
+    /** Compose two functions
+     */
+    void attach(FuncPtr<R(B0)> f, FuncPtr<B0(A0)> g) {
+        _f.attach(f);
+        _g.attach(g);
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename FT, typename FM>
+    void attach(FT *fobj, FM fmethod, FuncPtr<B0(A0)> g) {
+        attach(FuncPtr<R(B0)>(fobj, fmethod), g);
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename GT, typename GM>
+    void attach(FuncPtr<R(B0)> f, GT *gobj, GM gmethod) {
+        attach(f, FuncPtr<B0(A0)>(gobj, gmethod));
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename FT, typename FM, typename GT, typename GM>
+    void attach(FT *fobj, FM fmethod, GT *gobj, GM gmethod) {
+        attach(FuncPtr<R(B0)>(fobj, fmethod),
+               FuncPtr<B0(A0)>(gobj, gmethod));
+    }
+
+    /** Call the composed functions
+     */
+    R call(A0 a0) {
+        return _f(_g(a0));
+    }
+
+    /** Call the composed functions
+     */
+    R operator()(A0 a0) {
+        return call(a0);
+    }
+
+    /** Test if functions have been composed
+     */
+    operator bool(void) const {
+        return _f && _g;
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param func Composer to call passed as void pointer
+     */
+    static R thunk(void *func, A0 a0) {
+        return static_cast<Composer<R(B0), B0(A0)>*>(func)
+                ->call(a0);
+    }
+
+private:
+    FuncPtr<R(B0)> _f;
+    FuncPtr<B0(A0)> _g;
+};
+
+/** Static function composition
+ */
+template <typename R, typename B0>
+class Composer<R(B0), B0()> {
+public:
+    /** Create an uncomposed Composer
+     */
+    Composer() {}
+
+    /** Create a Composer, composing two functions
+     */
+    Composer(FuncPtr<R(B0)> f, FuncPtr<B0()> g) {
+        attach(f, g);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename FT, typename FM>
+    Composer(FT *fobj, FM fmethod, FuncPtr<B0()> g) {
+        attach(fobj, fmethod, g);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename GT, typename GM>
+    Composer(FuncPtr<B0()> f, GT *gobj, GM gmethod) {
+        attach(f, gobj, gmethod);
+    }
+
+    /** Create a Composer, composing functions and methods
+     */
+    template <typename FT, typename FM, typename GT, typename GM>
+    Composer(FT *fobj, FM fmethod, GT *gobj, GM gmethod) {
+        attach(fobj, fmethod, gobj, gmethod);
+    }
+
+    /** Compose two functions
+     */
+    void attach(FuncPtr<R(B0)> f, FuncPtr<B0()> g) {
+        _f.attach(f);
+        _g.attach(g);
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename FT, typename FM>
+    void attach(FT *fobj, FM fmethod, FuncPtr<B0()> g) {
+        attach(FuncPtr<R(B0)>(fobj, fmethod), g);
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename GT, typename GM>
+    void attach(FuncPtr<R(B0)> f, GT *gobj, GM gmethod) {
+        attach(f, FuncPtr<B0()>(gobj, gmethod));
+    }
+
+    /** Compose functions and methods
+     */
+    template <typename FT, typename FM, typename GT, typename GM>
+    void attach(FT *fobj, FM fmethod, GT *gobj, GM gmethod) {
+        attach(FuncPtr<R(B0)>(fobj, fmethod),
+               FuncPtr<B0()>(gobj, gmethod));
+    }
+
+    /** Call the composed functions
+     */
+    R call() {
+        return _f(_g());
+    }
+
+    /** Call the composed functions
+     */
+    R operator()() {
+        return call();
+    }
+
+    /** Test if functions have been composed
+     */
+    operator bool(void) const {
+        return _f && _g;
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param func Composer to call passed as void pointer
+     */
+    static R thunk(void *func) {
+        return static_cast<Composer<R(B0), B0()>*>(func)
+                ->call();
+    }
+
+private:
+    FuncPtr<R(B0)> _f;
+    FuncPtr<B0()> _g;
+};
+
+
+#endif