Mercurial > hg > sv-dependency-builds
comparison osx/include/kj/function.h @ 134:41e769c91eca
Add Capnp and KJ builds for OSX
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Tue, 25 Oct 2016 14:48:23 +0100 |
parents | |
children | 0994c39f1e94 |
comparison
equal
deleted
inserted
replaced
133:1ac99bfc383d | 134:41e769c91eca |
---|---|
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors | |
2 // Licensed under the MIT License: | |
3 // | |
4 // Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 // of this software and associated documentation files (the "Software"), to deal | |
6 // in the Software without restriction, including without limitation the rights | |
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
8 // copies of the Software, and to permit persons to whom the Software is | |
9 // furnished to do so, subject to the following conditions: | |
10 // | |
11 // The above copyright notice and this permission notice shall be included in | |
12 // all copies or substantial portions of the Software. | |
13 // | |
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
20 // THE SOFTWARE. | |
21 | |
22 #ifndef KJ_FUNCTION_H_ | |
23 #define KJ_FUNCTION_H_ | |
24 | |
25 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | |
26 #pragma GCC system_header | |
27 #endif | |
28 | |
29 #include "memory.h" | |
30 | |
31 namespace kj { | |
32 | |
33 template <typename Signature> | |
34 class Function; | |
35 // Function wrapper using virtual-based polymorphism. Use this when template polymorphism is | |
36 // not possible. You can, for example, accept a Function as a parameter: | |
37 // | |
38 // void setFilter(Function<bool(const Widget&)> filter); | |
39 // | |
40 // The caller of `setFilter()` may then pass any callable object as the parameter. The callable | |
41 // object does not have to have the exact signature specified, just one that is "compatible" -- | |
42 // i.e. the return type is covariant and the parameters are contravariant. | |
43 // | |
44 // Unlike `std::function`, `kj::Function`s are movable but not copyable, just like `kj::Own`. This | |
45 // is to avoid unexpected heap allocation or slow atomic reference counting. | |
46 // | |
47 // When a `Function` is constructed from an lvalue, it captures only a reference to the value. | |
48 // When constructed from an rvalue, it invokes the value's move constructor. So, for example: | |
49 // | |
50 // struct AddN { | |
51 // int n; | |
52 // int operator(int i) { return i + n; } | |
53 // } | |
54 // | |
55 // Function<int(int, int)> f1 = AddN{2}; | |
56 // // f1 owns an instance of AddN. It may safely be moved out | |
57 // // of the local scope. | |
58 // | |
59 // AddN adder(2); | |
60 // Function<int(int, int)> f2 = adder; | |
61 // // f2 contains a reference to `adder`. Thus, it becomes invalid | |
62 // // when `adder` goes out-of-scope. | |
63 // | |
64 // AddN adder2(2); | |
65 // Function<int(int, int)> f3 = kj::mv(adder2); | |
66 // // f3 owns an insatnce of AddN moved from `adder2`. f3 may safely | |
67 // // be moved out of the local scope. | |
68 // | |
69 // Additionally, a Function may be bound to a class method using KJ_BIND_METHOD(object, methodName). | |
70 // For example: | |
71 // | |
72 // class Printer { | |
73 // public: | |
74 // void print(int i); | |
75 // void print(kj::StringPtr s); | |
76 // }; | |
77 // | |
78 // Printer p; | |
79 // | |
80 // Function<void(uint)> intPrinter = KJ_BIND_METHOD(p, print); | |
81 // // Will call Printer::print(int). | |
82 // | |
83 // Function<void(const char*)> strPrinter = KJ_BIND_METHOD(p, print); | |
84 // // Will call Printer::print(kj::StringPtr). | |
85 // | |
86 // Notice how KJ_BIND_METHOD is able to figure out which overload to use depending on the kind of | |
87 // Function it is binding to. | |
88 | |
89 template <typename Signature> | |
90 class ConstFunction; | |
91 // Like Function, but wraps a "const" (i.e. thread-safe) call. | |
92 | |
93 template <typename Return, typename... Params> | |
94 class Function<Return(Params...)> { | |
95 public: | |
96 template <typename F> | |
97 inline Function(F&& f): impl(heap<Impl<F>>(kj::fwd<F>(f))) {} | |
98 Function() = default; | |
99 | |
100 // Make sure people don't accidentally end up wrapping a reference when they meant to return | |
101 // a function. | |
102 KJ_DISALLOW_COPY(Function); | |
103 Function(Function&) = delete; | |
104 Function& operator=(Function&) = delete; | |
105 template <typename T> Function(const Function<T>&) = delete; | |
106 template <typename T> Function& operator=(const Function<T>&) = delete; | |
107 template <typename T> Function(const ConstFunction<T>&) = delete; | |
108 template <typename T> Function& operator=(const ConstFunction<T>&) = delete; | |
109 Function(Function&&) = default; | |
110 Function& operator=(Function&&) = default; | |
111 | |
112 inline Return operator()(Params... params) { | |
113 return (*impl)(kj::fwd<Params>(params)...); | |
114 } | |
115 | |
116 Function reference() { | |
117 // Forms a new Function of the same type that delegates to this Function by reference. | |
118 // Therefore, this Function must outlive the returned Function, but otherwise they behave | |
119 // exactly the same. | |
120 | |
121 return *impl; | |
122 } | |
123 | |
124 private: | |
125 class Iface { | |
126 public: | |
127 virtual Return operator()(Params... params) = 0; | |
128 }; | |
129 | |
130 template <typename F> | |
131 class Impl final: public Iface { | |
132 public: | |
133 explicit Impl(F&& f): f(kj::fwd<F>(f)) {} | |
134 | |
135 Return operator()(Params... params) override { | |
136 return f(kj::fwd<Params>(params)...); | |
137 } | |
138 | |
139 private: | |
140 F f; | |
141 }; | |
142 | |
143 Own<Iface> impl; | |
144 }; | |
145 | |
146 template <typename Return, typename... Params> | |
147 class ConstFunction<Return(Params...)> { | |
148 public: | |
149 template <typename F> | |
150 inline ConstFunction(F&& f): impl(heap<Impl<F>>(kj::fwd<F>(f))) {} | |
151 ConstFunction() = default; | |
152 | |
153 // Make sure people don't accidentally end up wrapping a reference when they meant to return | |
154 // a function. | |
155 KJ_DISALLOW_COPY(ConstFunction); | |
156 ConstFunction(ConstFunction&) = delete; | |
157 ConstFunction& operator=(ConstFunction&) = delete; | |
158 template <typename T> ConstFunction(const ConstFunction<T>&) = delete; | |
159 template <typename T> ConstFunction& operator=(const ConstFunction<T>&) = delete; | |
160 template <typename T> ConstFunction(const Function<T>&) = delete; | |
161 template <typename T> ConstFunction& operator=(const Function<T>&) = delete; | |
162 ConstFunction(ConstFunction&&) = default; | |
163 ConstFunction& operator=(ConstFunction&&) = default; | |
164 | |
165 inline Return operator()(Params... params) const { | |
166 return (*impl)(kj::fwd<Params>(params)...); | |
167 } | |
168 | |
169 ConstFunction reference() const { | |
170 // Forms a new ConstFunction of the same type that delegates to this ConstFunction by reference. | |
171 // Therefore, this ConstFunction must outlive the returned ConstFunction, but otherwise they | |
172 // behave exactly the same. | |
173 | |
174 return *impl; | |
175 } | |
176 | |
177 private: | |
178 class Iface { | |
179 public: | |
180 virtual Return operator()(Params... params) const = 0; | |
181 }; | |
182 | |
183 template <typename F> | |
184 class Impl final: public Iface { | |
185 public: | |
186 explicit Impl(F&& f): f(kj::fwd<F>(f)) {} | |
187 | |
188 Return operator()(Params... params) const override { | |
189 return f(kj::fwd<Params>(params)...); | |
190 } | |
191 | |
192 private: | |
193 F f; | |
194 }; | |
195 | |
196 Own<Iface> impl; | |
197 }; | |
198 | |
199 #if 1 | |
200 | |
201 namespace _ { // private | |
202 | |
203 template <typename T, typename Signature, Signature method> | |
204 class BoundMethod; | |
205 | |
206 template <typename T, typename Return, typename... Params, Return (Decay<T>::*method)(Params...)> | |
207 class BoundMethod<T, Return (Decay<T>::*)(Params...), method> { | |
208 public: | |
209 BoundMethod(T&& t): t(kj::fwd<T>(t)) {} | |
210 | |
211 Return operator()(Params&&... params) { | |
212 return (t.*method)(kj::fwd<Params>(params)...); | |
213 } | |
214 | |
215 private: | |
216 T t; | |
217 }; | |
218 | |
219 template <typename T, typename Return, typename... Params, | |
220 Return (Decay<T>::*method)(Params...) const> | |
221 class BoundMethod<T, Return (Decay<T>::*)(Params...) const, method> { | |
222 public: | |
223 BoundMethod(T&& t): t(kj::fwd<T>(t)) {} | |
224 | |
225 Return operator()(Params&&... params) const { | |
226 return (t.*method)(kj::fwd<Params>(params)...); | |
227 } | |
228 | |
229 private: | |
230 T t; | |
231 }; | |
232 | |
233 } // namespace _ (private) | |
234 | |
235 #define KJ_BIND_METHOD(obj, method) \ | |
236 ::kj::_::BoundMethod<KJ_DECLTYPE_REF(obj), \ | |
237 decltype(&::kj::Decay<decltype(obj)>::method), \ | |
238 &::kj::Decay<decltype(obj)>::method>(obj) | |
239 // Macro that produces a functor object which forwards to the method `obj.name`. If `obj` is an | |
240 // lvalue, the functor will hold a reference to it. If `obj` is an rvalue, the functor will | |
241 // contain a copy (by move) of it. | |
242 // | |
243 // The current implementation requires that the method is not overloaded. | |
244 // | |
245 // TODO(someday): C++14's generic lambdas may be able to simplify this code considerably, and | |
246 // probably make it work with overloaded methods. | |
247 | |
248 #else | |
249 // Here's a better implementation of the above that doesn't work with GCC (but does with Clang) | |
250 // because it uses a local class with a template method. Sigh. This implementation supports | |
251 // overloaded methods. | |
252 | |
253 #define KJ_BIND_METHOD(obj, method) \ | |
254 ({ \ | |
255 typedef KJ_DECLTYPE_REF(obj) T; \ | |
256 class F { \ | |
257 public: \ | |
258 inline F(T&& t): t(::kj::fwd<T>(t)) {} \ | |
259 template <typename... Params> \ | |
260 auto operator()(Params&&... params) \ | |
261 -> decltype(::kj::instance<T>().method(::kj::fwd<Params>(params)...)) { \ | |
262 return t.method(::kj::fwd<Params>(params)...); \ | |
263 } \ | |
264 private: \ | |
265 T t; \ | |
266 }; \ | |
267 (F(obj)); \ | |
268 }) | |
269 // Macro that produces a functor object which forwards to the method `obj.name`. If `obj` is an | |
270 // lvalue, the functor will hold a reference to it. If `obj` is an rvalue, the functor will | |
271 // contain a copy (by move) of it. | |
272 | |
273 #endif | |
274 | |
275 } // namespace kj | |
276 | |
277 #endif // KJ_FUNCTION_H_ |