|
8 | 8 | #ifndef ADOBE_FUNCTION_HPP |
9 | 9 | #define ADOBE_FUNCTION_HPP |
10 | 10 |
|
11 | | -#include <algorithm> |
12 | | -#include <exception> |
13 | 11 | #include <functional> |
14 | | -#include <type_traits> |
15 | | - |
16 | | -#include <adobe/string.hpp> |
17 | 12 |
|
18 | 13 | /**************************************************************************************************/ |
19 | 14 |
|
20 | 15 | namespace adobe { |
21 | 16 |
|
22 | 17 | /**************************************************************************************************/ |
23 | 18 |
|
24 | | -class marshaled_exception : public std::exception { |
25 | | -public: |
26 | | - explicit marshaled_exception(string_t message) : message_m(move(message)) {} |
27 | | - ~marshaled_exception() throw() {} |
28 | | - const char* what() const throw() { return message_m.c_str(); } |
29 | | - |
30 | | -private: |
31 | | - string_t message_m; |
32 | | -}; |
33 | | - |
34 | | -const char* current_exception_what() { |
35 | | - const char* result = "unknown_exception"; |
36 | | - |
37 | | - try { |
38 | | - throw; |
39 | | - } catch (const std::exception& error) { |
40 | | - if (error.what()) |
41 | | - result = error.what(); |
42 | | - } catch (...) { |
43 | | - } |
44 | | - |
45 | | - return result; |
46 | | -} |
47 | | - |
48 | | -struct void_; |
49 | | -typedef void_* null_ptr_t; |
50 | | - |
51 | | -/**************************************************************************************************/ |
52 | | - |
53 | | -namespace implementation { |
54 | | - |
55 | | -template <typename T> |
56 | | -class function_base { |
57 | | -public: |
58 | | - // [3.7.2.2] function modifiers |
59 | | - void swap(T& x) { std::swap(self()->object_m, x.object_m); } |
60 | | - |
61 | | - // [3.7.2.3] function capacity |
62 | | - operator bool() const { return self()->object_m; } |
63 | | - |
64 | | - // [3.7.2.5] function target access |
65 | | - /* Not provided: |
66 | | - const std::type_info& target_type() const; |
67 | | - template <typename T> T* target(); |
68 | | - template <typename T> const T* target() const; |
69 | | - */ |
70 | | - |
71 | | - friend inline void swap(T& x, T& y) { x.swap(y); } |
72 | | - |
73 | | -private: |
74 | | - operator int() const; // for safe bool cast |
75 | | - |
76 | | - T* self() { return static_cast<T*>(this); } |
77 | | - const T* self() const { return static_cast<const T*>(this); } |
78 | | -}; |
79 | | - |
80 | | -template <typename Concept, typename Apply> |
81 | | -struct vtable { |
82 | | - void (*destroy)(Concept*); |
83 | | - Concept* (*copy)(const Concept*, string_t& message); |
84 | | - Apply apply; |
85 | | -}; |
86 | | - |
87 | | -template <typename Concept, typename V> |
88 | | -struct concept_base_t { |
89 | | - explicit concept_base_t(const V* x) : vtable_m(x) {} |
90 | | - |
91 | | - Concept* copy() const { |
92 | | - string_t message; |
93 | | - Concept* result = vtable_m->copy(self(), message); |
94 | | - if (message) |
95 | | - throw marshaled_exception(move(message)); |
96 | | - return result; |
97 | | - } |
98 | | - |
99 | | - void destroy() { vtable_m->destroy(self()); } |
100 | | - |
101 | | - Concept* self() { return static_cast<Concept*>(this); } |
102 | | - const Concept* self() const { return static_cast<const Concept*>(this); } |
103 | | - |
104 | | - const V* vtable_m; |
105 | | -}; |
106 | | - |
107 | | -template <typename Model, typename Concept> |
108 | | -struct model_base : Concept { |
109 | | - template <typename T> |
110 | | - explicit model_base(T x) : Concept(x) {} |
111 | | - |
112 | | - static Model* self(Concept* x) { return static_cast<Model*>(x); } |
113 | | - static const Model* self(const Concept* x) { return static_cast<const Model*>(x); } |
114 | | - |
115 | | - static void destroy(Concept* x) { delete self(x); } |
116 | | - |
117 | | - static Concept* copy(const Concept* x, string_t& message) { |
118 | | - Concept* result = 0; |
119 | | - |
120 | | - try { |
121 | | - result = new Model(*self(x)); |
122 | | - } catch (...) { |
123 | | - message = current_exception_what(); |
124 | | - } |
125 | | - |
126 | | - return result; |
127 | | - } |
128 | | -}; |
129 | | - |
130 | | -template <typename F, typename T> |
131 | | -typename F::concept_t* make_model(const T& x) { |
132 | | - return new typename F::template model<T>(x); |
133 | | -} |
134 | | - |
135 | | -template <typename F, typename T> |
136 | | -typename F::concept_t* create_model(const T& x, std::true_type) { |
137 | | - return x ? make_model<F>(std::bind<typename F::result_type>(x)) : 0; |
138 | | -} |
139 | | - |
140 | | -template <typename F, typename T> |
141 | | -typename F::concept_t* create_model(const T& x, std::false_type) { |
142 | | - return make_model<F>(std::bind<typename F::result_type>(x)); |
143 | | -} |
144 | | - |
145 | | -template <typename F, typename T> |
146 | | -typename F::concept_t* create_model(const T& x) { |
147 | | - return create_model<F>(x, std::is_pointer<T>()); |
148 | | -} |
149 | | - |
150 | | -} // namespace implementation |
151 | | - |
152 | | -/**************************************************************************************************/ |
153 | | - |
154 | | -inline namespace version_1 { |
155 | | - |
156 | | -/**************************************************************************************************/ |
157 | | - |
158 | | - |
159 | | -template <typename F> |
160 | | -class function; |
161 | | - |
162 | | -/**************************************************************************************************/ |
163 | | - |
164 | | -// [3.7.2.7] null pointer comparisons |
165 | | -template <typename F> |
166 | | -bool operator==(const function<F>& x, null_ptr_t) { |
167 | | - return !x; |
168 | | -} |
169 | | -template <typename F> |
170 | | -bool operator==(null_ptr_t, const function<F>& x) { |
171 | | - return !x; |
172 | | -} |
173 | | -template <typename F> |
174 | | -bool operator!=(const function<F>& x, null_ptr_t) { |
175 | | - return x; |
176 | | -} |
177 | | -template <typename F> |
178 | | -bool operator!=(null_ptr_t, const function<F>& x) { |
179 | | - return x; |
180 | | -} |
181 | | - |
182 | | -/**************************************************************************************************/ |
183 | | - |
184 | | -template <typename R> |
185 | | -class function<R()> : public implementation::function_base<function<R()>> { |
186 | | -public: |
187 | | - typedef R result_type; |
188 | | - |
189 | | - // [3.7.2.1] construction/copy/destroy |
190 | | - function() : object_m(0) {} |
191 | | - function(null_ptr_t) : object_m(0) {} |
192 | | - function(const function& x) : object_m(x.object_m ? x.object_m->copy() : 0) {} |
193 | | - template <typename T> |
194 | | - function(T x) : object_m(implementation::create_model<function>(x)) {} |
195 | | - |
196 | | - function& operator=(function x) { |
197 | | - swap(*this, x); |
198 | | - return *this; |
199 | | - } |
200 | | - function& operator=(null_ptr_t) { |
201 | | - if (object_m) |
202 | | - object_m->destroy(); |
203 | | - object_m = 0; |
204 | | - } |
205 | | - template <typename T> |
206 | | - function& operator=(T x) { |
207 | | - return *this = function(x); |
208 | | - } |
209 | | - // template<class F> function& operator=(reference_wrapper<F>); |
210 | | - |
211 | | - ~function() { |
212 | | - if (object_m) |
213 | | - object_m->destroy(); |
214 | | - } |
215 | | - |
216 | | - // [3.7.2.4] function invocation |
217 | | - R operator()() const { |
218 | | - if (!object_m) |
219 | | - throw std::bad_function_call(); |
220 | | - return object_m->apply(); |
221 | | - } |
222 | | - |
223 | | - struct concept_t; // implementation |
224 | | - |
225 | | -private: |
226 | | - friend class implementation::function_base<function<R()>>; |
227 | | - |
228 | | - typedef implementation::vtable<concept_t, R (*)(concept_t*, string_t&)> vtable_type; |
229 | | - |
230 | | - /* |
231 | | - REVISIT (sparent) : This section is an implementation detail - made public until I can |
232 | | - figure |
233 | | - out how to make template friends. |
234 | | - */ |
235 | | - |
236 | | -public: |
237 | | - struct concept_t : implementation::concept_base_t<concept_t, vtable_type> { |
238 | | - typedef implementation::concept_base_t<concept_t, vtable_type> base_type; |
239 | | - |
240 | | - explicit concept_t(const vtable_type* x) : base_type(x) {} |
241 | | - R apply() { return apply(typename std::is_void<R>()); } |
242 | | - |
243 | | - void apply(std::true_type) { |
244 | | - string_t message; |
245 | | - this->vtable_m->apply(this, message); |
246 | | - if (message) |
247 | | - throw marshaled_exception(move(message)); |
248 | | - } |
249 | | - |
250 | | - R apply(std::false_type) { |
251 | | - string_t message; |
252 | | - R result = this->vtable_m->apply(this, message); |
253 | | - if (message) |
254 | | - throw marshaled_exception(move(message)); |
255 | | - return result; |
256 | | - } |
257 | | - }; |
258 | | - |
259 | | - template <typename T> |
260 | | - struct model : implementation::model_base<model<T>, concept_t> { |
261 | | - typedef implementation::model_base<model<T>, concept_t> base_type; |
262 | | - |
263 | | - explicit model(T x) : base_type(&vtable_s), function_m(x) {} |
264 | | - |
265 | | - static R apply(concept_t* x, string_t& message) { |
266 | | - return apply(x, message, typename std::is_void<R>()); |
267 | | - } |
268 | | - |
269 | | - static void apply(concept_t* x, string_t& message, std::true_type) { |
270 | | - try { |
271 | | - static_cast<model*>(x)->function_m(); |
272 | | - } catch (...) { |
273 | | - message = current_exception_what(); |
274 | | - } |
275 | | - } |
276 | | - |
277 | | - static R apply(concept_t* x, string_t& message, std::false_type) { |
278 | | - R result; |
279 | | - try { |
280 | | - result = static_cast<model*>(x)->function_m(); |
281 | | - } catch (...) { |
282 | | - message = current_exception_what(); |
283 | | - } |
284 | | - return result; |
285 | | - } |
286 | | - |
287 | | - static const vtable_type vtable_s; |
288 | | - T function_m; |
289 | | - }; |
290 | | - |
291 | | -private: |
292 | | - concept_t* object_m; |
293 | | -}; |
294 | | - |
295 | | -template <typename R> |
296 | | -template <typename T> |
297 | | -const typename function<R()>::vtable_type function<R()>::model<T>::vtable_s = { |
298 | | - &model::destroy, &model::copy, &model::apply}; |
| 19 | +/// \deprecated Use std::function instead. |
| 20 | +template <class Signature> |
| 21 | +using function = std::function<Signature>; |
299 | 22 |
|
300 | 23 | /**************************************************************************************************/ |
301 | 24 |
|
302 | | -} // namespace version_1 |
303 | 25 | } // namespace adobe |
304 | 26 |
|
305 | 27 | /**************************************************************************************************/ |
|
0 commit comments