Streamtools: Rescaler to change the vertical/horizontal stacking
[jpcrr.git] / streamtools / bound-method.hpp
blob53d0f22ef24d1f7d875dc7bbfa27195810f67926
1 #ifndef _bound_method__hpp__included__
2 #define _bound_method__hpp__included__
4 #include <stdexcept>
6 template<typename ret, typename... args>
7 class bound_method_base;
9 template<typename ret, typename... args>
10 class bound_method
12 public:
13 bound_method()
15 target = NULL;
17 bound_method(bound_method_base<ret, args...>& method)
19 target = &method;
20 method.refcnt = 1;
22 ~bound_method()
24 if(target) {
25 target->refcnt--;
26 if(!target->refcnt)
27 delete target;
30 bound_method& operator=(const bound_method& m)
32 if(target == m.target)
33 return *this;
34 if(target) {
35 target->refcnt--;
36 if(!target->refcnt)
37 delete target;
39 target = m.target;
40 if(target)
41 target->refcnt++;
42 return *this;
44 bool operator==(const bound_method& m)
46 return (target == m.target);
48 bool operator!=(const bound_method& m)
50 return (target != m.target);
52 void clear()
54 if(target) {
55 target->refcnt--;
56 if(!target->refcnt)
57 delete target;
59 target = NULL;
61 operator bool()
63 return (target != NULL);
65 bool operator!()
67 return (target == NULL);
69 bound_method(const bound_method& m)
71 target = m.target;
72 if(target)
73 target->refcnt++;
75 ret operator()(args... arg)
77 if(!target)
78 throw std::runtime_error("Attempted to call null pointer");
79 return (*target)(arg...);
81 private:
82 bound_method_base<ret, args...>* target;
85 template<typename ret, typename... args>
86 class bound_method_base
88 public:
89 virtual ~bound_method_base()
92 virtual ret operator()(args... arg) = 0;
93 private:
94 size_t refcnt;
95 friend class bound_method<ret, args...>;
98 template<class T, typename ret, typename... args>
99 class bound_method_deriv_class : public bound_method_base<ret, args...>
101 public:
102 bound_method_deriv_class(T& _object, ret (T::*_fun)(args... arg))
103 : object(_object), fun(_fun)
106 ret operator()(args... arg)
108 return (object.*fun)(arg...);
110 private:
111 T& object;
112 ret (T::*fun)(args... arg);
115 template<typename ret, typename... args>
116 class bound_method_deriv_fun : public bound_method_base<ret, args...>
118 public:
119 bound_method_deriv_fun(ret (*_fun)(args... arg))
120 : fun(_fun)
123 ret operator()(args... arg)
125 return fun(arg...);
127 private:
128 ret (*fun)(args... arg);
131 template<typename ret, typename tail, typename... args>
132 class bound_method_bind_tail : public bound_method_base<ret, args...>
134 public:
135 bound_method_bind_tail(bound_method<ret, args..., tail> _fn, tail _t)
137 fn = _fn;
138 t = _t;
141 ret operator()(args... arg)
143 return fn(arg..., t);
145 private:
146 bound_method<ret, args..., tail> fn;
147 tail t;
150 template<class T, typename ret, typename... args>
151 bound_method<ret, args...> make_bound_method(T& _object, ret (T::*_fun)(args... arg))
153 return bound_method<ret, args...>(*new bound_method_deriv_class<T, ret, args...>(_object, _fun));
156 template<typename ret, typename... args>
157 bound_method<ret, args...> make_bound_method(ret (*_fun)(args... arg))
159 return bound_method<ret, args...>(*new bound_method_deriv_fun<ret, args...>(_fun));
162 template<typename ret, typename tail, typename... args>
163 bound_method<ret, args...> bind_last(bound_method<ret, args..., tail> fn, tail t)
165 return bound_method<ret, args...>(*new bound_method_bind_tail<ret, tail, args...>(fn, t));
168 #endif