]> git.saurik.com Git - cydia.git/blob - Menes/Function.h
Objective-C seriously didn't notice my mistake :/.
[cydia.git] / Menes / Function.h
1 /* Cydia - iPhone UIKit Front-End for Debian APT
2 * Copyright (C) 2008-2015 Jay Freeman (saurik)
3 */
4
5 /* GNU General Public License, Version 3 {{{ */
6 /*
7 * Cydia is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation, either version 3 of the License,
10 * or (at your option) any later version.
11 *
12 * Cydia is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Cydia. If not, see <http://www.gnu.org/licenses/>.
19 **/
20 /* }}} */
21
22 #ifndef Menes_Function_H
23 #define Menes_Function_H
24
25 template <typename Result_, typename... Args_>
26 class Function {
27 private:
28 class Abstract {
29 private:
30 unsigned references_;
31
32 public:
33 Abstract() :
34 references_(0)
35 {
36 }
37
38 Abstract(const Abstract &) = delete;
39 Abstract &operator =(const Abstract &) = delete;
40
41 virtual ~Abstract() {
42 }
43
44 void Retain() {
45 ++references_;
46 }
47
48 void Release() {
49 if (--references_ == 0)
50 delete this;
51 }
52
53 virtual Result_ operator()(Args_... args) const = 0;
54 };
55
56 template <typename Callable_>
57 class Concrete :
58 public Abstract
59 {
60 private:
61 Callable_ callable_;
62
63 public:
64 Concrete(const Callable_ &callable) :
65 callable_(callable)
66 {
67 }
68
69 virtual Result_ operator()(Args_... args) const {
70 return callable_(args...);
71 }
72 };
73
74 private:
75 Abstract *abstract_;
76
77 void Release() {
78 if (abstract_ != NULL)
79 abstract_->Release();
80 }
81
82 void Copy(Abstract *abstract) {
83 if (abstract != NULL)
84 abstract->Retain();
85 Release();
86 abstract_ = abstract;
87 }
88
89 template <typename Callable_>
90 void Assign(const Callable_ &callable) {
91 Copy(new Concrete<Callable_>(callable));
92 }
93
94 public:
95 Function() :
96 abstract_(NULL)
97 {
98 }
99
100 Function(decltype(nullptr)) :
101 Function()
102 {
103 }
104
105 Function(const Function &function) :
106 abstract_(function.abstract_)
107 {
108 abstract_->Retain();
109 }
110
111 template <typename Callable_>
112 Function(const Callable_ &callable) :
113 Function()
114 {
115 Assign(callable);
116 }
117
118 ~Function() {
119 Release();
120 }
121
122 Function &operator =(decltype(nullptr)) {
123 Clear();
124 return *this;
125 }
126
127 Function &operator =(const Function &function) {
128 Copy(function.abstract_);
129 return *this;
130 }
131
132 Result_ operator()(Args_... args) const {
133 return (*abstract_)(args...);
134 }
135
136 void Clear() {
137 Release();
138 abstract_ = NULL;
139 }
140
141 template <typename Callable_>
142 Function &operator =(const Callable_ &callable) {
143 Assign(callable);
144 return *this;
145 }
146
147 operator bool() const {
148 return abstract_ != NULL;
149 }
150 };
151
152 #endif//Menes_Function_H