git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
C++: streamline 'any' ctors, dtors, etc.
e655652Andy Arvanitis
pcc/include/purescript.cc−87
@@ -17,93 +17,6 @@
17
17
18namespace PureScript {
18namespace PureScript {
19
19
20−#define COPY_DATA(src) \
21− switch (type) { \
22− case Type::Integer: i = src.i; break; \
23− case Type::Double: d = src.d; break; \
24− case Type::Character: c = src.c; break; \
25− case Type::Boolean: b = src.b; break; \
26− case Type::StringLiteral: r = src.r; break; \
27− case Type::String: new (&s) shared<std::string>(src.s); break; \
28− case Type::Map: new (&m) shared<map>(src.m); break; \
29− case Type::Data: new (&v) shared<data>(src.v); break; \
30− case Type::Array: new (&a) shared<array>(src.a); break; \
31− case Type::Function: f = src.f; break; \
32− case Type::Closure: new (&l) shared<closure>(src.l); break; \
33− case Type::EffFunction: new (&e) shared<eff_fn>(src.e); break; \
34− case Type::Thunk: t = src.t; break; \
35− case Type::Pointer: new (&p) shared<void>(src.p); break; \
36− \
37− default: assert(false && "Unsupported type in copy"); \
38− }
39−
40−#define MOVE_DATA(src) \
41− switch (type) { \
42− case Type::Integer: i = src.i; break; \
43− case Type::Double: d = src.d; break; \
44− case Type::Character: c = src.c; break; \
45− case Type::Boolean: b = src.b; break; \
46− case Type::StringLiteral: r = src.r; break; \
47− case Type::String: new (&s) shared<std::string>(std::move(src.s)); break; \
48− case Type::Map: new (&m) shared<map>(std::move(src.m)); break; \
49− case Type::Data: new (&v) shared<data>(std::move(src.v)); break; \
50− case Type::Array: new (&a) shared<array>(std::move(src.a)); break; \
51− case Type::Function: f = src.f; break; \
52− case Type::Closure: new (&l) shared<closure>(std::move(src.l)); break; \
53− case Type::EffFunction: new (&e) shared<eff_fn>(std::move(src.e)); break; \
54− case Type::Thunk: t = src.t; break; \
55− case Type::Pointer: new (&p) shared<void>(std::move(src.p)); break; \
56− \
57− default: assert(false && "Unsupported type in move"); \
58− }
59−
60−any::any(const any& other) : type(other.type) {
61− COPY_DATA(other);
62−}
63−
64−any::any(any&& other) noexcept : type(other.type) {
65− MOVE_DATA(other);
66−}
67−
68−auto any::operator=(const any& rhs) -> any& {
69− type = rhs.type;
70− COPY_DATA(rhs);
71− return *this;
72−}
73−
74−auto any::operator=(any& rhs) noexcept -> any& {
75− type = rhs.type;
76− COPY_DATA(rhs);
77− return *this;
78−}
79−
80−auto any::operator=(any&& rhs) noexcept -> any& {
81− type = rhs.type;
82− MOVE_DATA(rhs);
83− return *this;
84−}
85−
86−any::~any() {
87− switch (type) {
88− case Type::Integer: ; break;
89− case Type::Double: ; break;
90− case Type::Character: ; break;
91− case Type::Boolean: ; break;
92− case Type::StringLiteral: ; break;
93− case Type::String: s.~shared<std::string>(); break;
94− case Type::Map: m.~shared<map>(); break;
95− case Type::Data: v.~shared<data>(); break;
96− case Type::Array: a.~shared<array>(); break;
97− case Type::Function: ; break;
98− case Type::Closure: l.~shared<closure>(); break;
99− case Type::EffFunction: e.~shared<eff_fn>(); break;
100− case Type::Thunk: ; break;
101− case Type::Pointer: p.~shared<void>(); break;
102−
103− default: assert(false && "Unsupported type in destructor");
104− }
105−};
106−
107#define RETURN_VALUE(TYPE, ACCESSOR, INDIRECTION) \
20#define RETURN_VALUE(TYPE, ACCESSOR, INDIRECTION) \
108 const any& variant = unthunkVariant(*this); \
21 const any& variant = unthunkVariant(*this); \
109 assert(variant.type == TYPE); \
22 assert(variant.type == TYPE); \
pcc/include/purescript.hh+82−34
@@ -83,7 +83,8 @@ class any {
83 };
83 };
84
84
85 private:
85 private:
86− mutable Type type = Type::Unknown;
86+ mutable Type type;
87+ mutable bool is_shared;
87
88
88 public:
89 public:
89 struct as_thunk {
90 struct as_thunk {
@@ -102,6 +103,7 @@ class any {
102 virtual auto operator()(const any&) const -> any = 0;
103 virtual auto operator()(const any&) const -> any = 0;
103 virtual auto operator()(const any&, const any&) const -> any = 0;
104 virtual auto operator()(const any&, const any&) const -> any = 0;
104 virtual auto operator()(const any&, const any&, const any&) const -> any = 0;
105 virtual auto operator()(const any&, const any&, const any&) const -> any = 0;
106+ virtual ~closure() {}
105 };
107 };
106
108
107 template <typename T>
109 template <typename T>
@@ -204,83 +206,129 @@ class any {
204
206
205 public:
207 public:
206
208
207− any(const long val) : type(Type::Integer), i(val) {}
209+ any(const long val) : type(Type::Integer), is_shared(false), i(val) {}
208− any(const int val) : type(Type::Integer), i(val) {}
210+ any(const int val) : type(Type::Integer), is_shared(false), i(val) {}
209− any(const unsigned int val) : type(Type::Integer), i(val) {}
211+ any(const unsigned int val) : type(Type::Integer), is_shared(false), i(val) {}
210− any(const double val) : type(Type::Double), d(val) {}
212+ any(const double val) : type(Type::Double), is_shared(false), d(val) {}
211− any(const char val) : type(Type::Character), c(val) {}
213+ any(const char val) : type(Type::Character), is_shared(false), c(val) {}
212
214
213 template <typename T, typename = typename std::enable_if<std::is_same<bool,T>::value>::type>
215 template <typename T, typename = typename std::enable_if<std::is_same<bool,T>::value>::type>
214− any(const T val) : type(Type::Boolean), b(val) {}
216+ any(const T val) : type(Type::Boolean), is_shared(false), b(val) {}
215
217
216 template <size_t N>
218 template <size_t N>
217− any(const char (&val)[N]) : type(Type::StringLiteral), r(val) {}
219+ any(const char (&val)[N]) : type(Type::StringLiteral), is_shared(false), r(val) {}
218− any(char * val) : type(Type::String), s(make_shared<std::string>(val)) {}
220+ any(char * val) : type(Type::String), is_shared(true), s(make_shared<std::string>(val)) {}
219
221
220− any(const std::string& val) : type(Type::String), s(make_shared<std::string>(val)) {}
222+ any(const std::string& val) : type(Type::String), is_shared(true), s(make_shared<std::string>(val)) {}
221− any(std::string&& val) : type(Type::String), s(make_shared<std::string>(std::move(val))) {}
223+ any(std::string&& val) : type(Type::String), is_shared(true), s(make_shared<std::string>(std::move(val))) {}
222
224
223− any(const shared<std::string>& val) : type(Type::String), s(val) {}
225+ any(const shared<std::string>& val) : type(Type::String), is_shared(true), s(val) {}
224− any(shared<std::string>&& val) noexcept : type(Type::String), s(std::move(val)) {}
226+ any(shared<std::string>&& val) noexcept : type(Type::String), is_shared(true), s(std::move(val)) {}
225
227
226− any(const map& val) : type(Type::Map), m(make_shared<map>(val)) {}
228+ any(const map& val) : type(Type::Map), is_shared(true), m(make_shared<map>(val)) {}
227− any(map&& val) noexcept : type(Type::Map), m(make_shared<map>(std::move(val))) {}
229+ any(map&& val) noexcept : type(Type::Map), is_shared(true), m(make_shared<map>(std::move(val))) {}
228
230
229− any(const data& val) : type(Type::Data), v(make_shared<data>(val)) {}
231+ any(const data& val) : type(Type::Data), is_shared(true), v(make_shared<data>(val)) {}
230− any(data&& val) noexcept : type(Type::Data), v(make_shared<data>(std::move(val))) {}
232+ any(data&& val) noexcept : type(Type::Data), is_shared(true), v(make_shared<data>(std::move(val))) {}
231
233
232− any(const array& val) : type(Type::Array), a(make_shared<array>(val)) {}
234+ any(const array& val) : type(Type::Array), is_shared(true), a(make_shared<array>(val)) {}
233− any(array&& val) noexcept : type(Type::Array), a(make_shared<array>(std::move(val))) {}
235+ any(array&& val) noexcept : type(Type::Array), is_shared(true), a(make_shared<array>(std::move(val))) {}
234
236
235 template <typename T>
237 template <typename T>
236 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0)
238 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0)
237− : type(Type::Function), f(val) {}
239+ : type(Type::Function), is_shared(false), f(val) {}
238
240
239 template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value &&
241 template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value &&
240 !std::is_convertible<T,fn>::value>::type>
242 !std::is_convertible<T,fn>::value>::type>
241 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any(const any&)>,T>::value>::type* = 0)
243 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any(const any&)>,T>::value>::type* = 0)
242− : type(Type::Closure), l(make_shared<_closure<T>>(val)) {}
244+ : type(Type::Closure), is_shared(true), l(make_shared<_closure<T>>(val)) {}
243
245
244 template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value &&
246 template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value &&
245 !std::is_convertible<T,fn>::value>::type>
247 !std::is_convertible<T,fn>::value>::type>
246 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any(const any&,
248 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any(const any&,
247 const any&)>,T>::value>::type* = 0)
249 const any&)>,T>::value>::type* = 0)
248− : type(Type::Closure), l(make_shared<_closure2<T>>(val)) {}
250+ : type(Type::Closure), is_shared(true), l(make_shared<_closure2<T>>(val)) {}
249
251
250 template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value &&
252 template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value &&
251 !std::is_convertible<T,fn>::value>::type>
253 !std::is_convertible<T,fn>::value>::type>
252 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any(const any&,
254 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any(const any&,
253 const any&,
255 const any&,
254 const any&)>,T>::value>::type* = 0)
256 const any&)>,T>::value>::type* = 0)
255− : type(Type::Closure), l(make_shared<_closure3<T>>(val)) {}
257+ : type(Type::Closure), is_shared(true), l(make_shared<_closure3<T>>(val)) {}
256
258
257 template <typename T>
259 template <typename T>
258 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any()>,T>::value>::type* = 0)
260 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any()>,T>::value>::type* = 0)
259− : type(Type::EffFunction), e(make_shared<_eff_fn<T>>(val)) {}
261+ : type(Type::EffFunction), is_shared(true), e(make_shared<_eff_fn<T>>(val)) {}
260
262
261 template <typename T>
263 template <typename T>
262 any(const T& val, typename std::enable_if<std::is_convertible<T,thunk>::value>::type* = 0)
264 any(const T& val, typename std::enable_if<std::is_convertible<T,thunk>::value>::type* = 0)
263− : type(Type::Thunk), t(val) {}
265+ : type(Type::Thunk), is_shared(false), t(val) {}
264
266
265 template <typename T>
267 template <typename T>
266 any(const T& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0)
268 any(const T& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0)
267− : type(Type::Pointer), p(val) {}
269+ : type(Type::Pointer), is_shared(true), p(val) {}
268
270
269 template <typename T>
271 template <typename T>
270 any(T&& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0) noexcept
272 any(T&& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0) noexcept
271− : type(Type::Pointer), p(std::move(val)) {}
273+ : type(Type::Pointer), is_shared(true), p(std::move(val)) {}
272
274
273− any(std::nullptr_t) : type(Type::Pointer), p(nullptr) {}
275+ any(std::nullptr_t) : type(Type::Pointer), is_shared(true), p(nullptr) {}
274
276
275− any(const any&);
277+ private:
276− any(any&&) noexcept;
278+
279+ auto copy(const any& other) const -> void {
280+ if (is_shared) {
281+ new (&p) shared<void>(other.p);
282+ } else {
283+ f = other.f;
284+ }
285+ }
277
286
278− auto operator=(const any&) -> any&;
287+ auto move(any& other) const noexcept -> void {
288+ if (is_shared) {
289+ new (&p) shared<void>(std::move(other.p));
290+ } else {
291+ f = other.f;
292+ }
293+ }
294+
295+ auto del() noexcept -> void {
296+ if (is_shared) {
297+ p.~shared<void>();
298+ }
299+ }
300+
301+ public:
302+
303+ any(const any& other) : type(other.type), is_shared(other.is_shared) {
304+ copy(other);
305+ }
306+
307+ any(any&& other) noexcept : type(other.type), is_shared(other.is_shared) {
308+ move(other);
309+ }
310+
279− auto operator=(any&) noexcept -> any&;
311+ auto operator=(const any& rhs) -> any& {
312+ del();
313+ type = rhs.type;
314+ is_shared = rhs.is_shared;
315+ copy(rhs);
316+ return *this;
317+ }
318+
280− auto operator=(any&&) noexcept -> any&;
319+ auto operator=(any&& rhs) noexcept -> any& {
320+ del();
321+ type = rhs.type;
322+ is_shared = rhs.is_shared;
323+ move(rhs);
324+ return *this;
325+ }
281
326
282 any() = delete;
327 any() = delete;
328+
283− ~any();
329+ ~any() {
330+ del();
331+ }
284
332
285 template <typename T>
333 template <typename T>
286 auto cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type;
334 auto cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type;