@@ -80,9 +80,13 @@ static constexpr size_t unknown_size = 64;
8080//
8181class any {
8282
83+ private:
84+ static constexpr auto _managed_ = 0x10;
85+
8386 public:
8487 enum class Tag {
85− Thunk = 0x10,
88+ Unknown,
89+ Thunk,
8690 Integer,
8791 Double,
8892 Character,
@@ -90,19 +94,25 @@ class any {
9094 Function,
9195 EffFunction,
9296 RawPointer,
93− String,
94− Map,
97+ String = _managed_,
98+ Dictionary,
9599 Data,
96100 Array,
97101 Record,
98102 Closure,
99103 EffClosure,
100− Pointer
104+ Pointer,
105+ Invalid
101106 };
102107
103108 private:
104109 mutable Tag tag;
105110
111+ inline static auto isManaged(const Tag tag) -> decltype(_managed_) {
112+ return static_cast<decltype(_managed_)>(tag) & _managed_;
113+ }
114+ static_assert(static_cast<decltype(_managed_)>(Tag::Invalid) & _managed_, "outside of range");
115+
106116 public:
107117 struct as_thunk {
108118 };
@@ -158,20 +168,16 @@ class any {
158168
159169 private:
160170 union {
161− mutable thunk t;
162− mutable int i;
163− mutable double d;
164− mutable char32_t c;
165− mutable bool b;
166− mutable fn f;
167− mutable eff_fn e;
168− mutable void * v;
169− mutable managed<string> s;
170− mutable managed<array> a;
171− mutable managed<record> r;
172− mutable managed<Closure> l;
173− mutable managed<EffClosure> k;
174− mutable managed<void> p;
171+ mutable thunk t;
172+ mutable int i;
173+ mutable double d;
174+ mutable char32_t c;
175+ mutable bool b;
176+ mutable fn f;
177+ mutable eff_fn e;
178+ mutable void * v;
179+ mutable uint64_t u;
180+ mutable managed<void> p;
175181 };
176182
177183 public:
@@ -188,24 +194,24 @@ class any {
188194 template <typename T, typename = typename std::enable_if<std::is_same<bool,T>::value>::type>
189195 any(const T val) noexcept : tag(Tag::Boolean), b(val) {}
190196
191− any(const char * val) : tag(Tag::String), s(make_managed_and_finalized<string>(val)) {}
192− any(const string& val) : tag(Tag::String), s(make_managed_and_finalized<string>(val)) {}
193− any(string&& val) noexcept : tag(Tag::String), s(make_managed_and_finalized<string>(std::move(val))) {}
197+ any(const char * val) : tag(Tag::String), p(make_managed_and_finalized<string>(val)) {}
198+ any(const string& val) : tag(Tag::String), p(make_managed_and_finalized<string>(val)) {}
199+ any(string&& val) noexcept : tag(Tag::String), p(make_managed_and_finalized<string>(std::move(val))) {}
194200
195− any(const managed<string>& val) noexcept : tag(Tag::String), s(val) {}
196− any(managed<string>&& val) noexcept : tag(Tag::String), s(std::move(val)) {}
201+ any(const managed<string>& val) noexcept : tag(Tag::String), p(val) {}
202+ any(managed<string>&& val) noexcept : tag(Tag::String), p(std::move(val)) {}
197203
198204 template <size_t N>
199− any(dict<N>&& val) noexcept : tag(Tag::Map), p(make_managed<dict<N>>(std::move(val))) {}
205+ any(dict<N>&& val) noexcept : tag(Tag::Dictionary), p(make_managed<dict<N>>(std::move(val))) {}
200206
201207 template <size_t N>
202208 any(data<N>&& val) noexcept : tag(Tag::Data), p(make_managed<data<N>>(std::move(val))) {}
203209
204− any(const array& val) : tag(Tag::Array), a(make_managed<array>(val)) {}
205− any(array&& val) noexcept : tag(Tag::Array), a(make_managed<array>(std::move(val))) {}
210+ any(const array& val) : tag(Tag::Array), p(make_managed<array>(val)) {}
211+ any(array&& val) noexcept : tag(Tag::Array), p(make_managed<array>(std::move(val))) {}
206212
207− any(const record& val) : tag(Tag::Record), r(make_managed<record>(val)) {}
208− any(record&& val) noexcept : tag(Tag::Record), r(make_managed<record>(std::move(val))) {}
213+ any(const record& val) : tag(Tag::Record), p(make_managed<record>(val)) {}
214+ any(record&& val) noexcept : tag(Tag::Record), p(make_managed<record>(std::move(val))) {}
209215
210216 template <typename T>
211217 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0) noexcept
@@ -214,7 +220,7 @@ class any {
214220 template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value &&
215221 !std::is_convertible<T,fn>::value>::type>
216222 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any(const any&)>,T>::value>::type* = 0)
217− : tag(Tag::Closure), l(make_managed<Closure_<T>>(val)) {}
223+ : tag(Tag::Closure), p(make_managed<Closure_<T>>(val)) {}
218224
219225 template <typename T>
220226 any(const T& val, typename std::enable_if<std::is_convertible<T,eff_fn>::value>::type* = 0) noexcept
@@ -224,7 +230,7 @@ class any {
224230 typename = typename std::enable_if<!std::is_same<any,T>::value &&
225231 !std::is_convertible<T,eff_fn>::value>::type>
226232 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any()>,T>::value>::type* = 0)
227− : tag(Tag::EffClosure), k(make_managed<EffClosure_<T>>(val)) {}
233+ : tag(Tag::EffClosure), p(make_managed<EffClosure_<T>>(val)) {}
228234
229235 template <typename T>
230236 any(const T& val, typename std::enable_if<std::is_convertible<T,thunk>::value>::type* = 0) noexcept
@@ -249,80 +255,56 @@ class any {
249255
250256#if !defined(USE_GC)
251257 private:
252− template <typename T,
253− typename U,
254− typename = typename std::enable_if<!std::is_reference<T>::value>::type>
255− static constexpr auto move_if_rvalue(U&& u) noexcept -> U&& {
256− return static_cast<U&&>(u);
257− }
258−
259− template <typename T,
260− typename U,
261− typename = typename std::enable_if<std::is_reference<T>::value>::type>
262− static constexpr auto move_if_rvalue(U& u) noexcept -> U& {
263− return static_cast<U&>(u);
258+ auto destruct() const noexcept -> void {
259+ if (isManaged(tag)) {
260+ p.~managed<void>();
261+ }
264262 }
265263
266− template <typename T>
267− auto assign(T&& other) const noexcept -> void {
268− switch (other.tag) {
269− case Tag::Thunk: t = other.t; break;
270− case Tag::Integer: i = other.i; break;
271− case Tag::Double: d = other.d; break;
272− case Tag::Character: c = other.c; break;
273− case Tag::Boolean: b = other.b; break;
274− case Tag::Function: f = other.f; break;
275− case Tag::EffFunction: e = other.e; break;
276− case Tag::RawPointer: v = other.v; break;
277−
278− case Tag::String: new (&s) managed<string>(move_if_rvalue<T>(other.s)); break;
279− case Tag::Array: new (&a) managed<array>(move_if_rvalue<T>(other.a)); break;
280− case Tag::Record: new (&r) managed<record>(move_if_rvalue<T>(other.r)); break;
281− case Tag::Closure: new (&l) managed<Closure>(move_if_rvalue<T>(other.l)); break;
282− case Tag::EffClosure: new (&k) managed<EffClosure>(move_if_rvalue<T>(other.k)); break;
283− case Tag::Map:
284− case Tag::Data:
285− case Tag::Pointer: new (&p) managed<void>(move_if_rvalue<T>(other.p)); break;
286−
287− default: assert(false && "Bad 'any' tag"); break;
264+ static_assert(sizeof(u) >= sizeof(t), "size assumption");
265+ static_assert(sizeof(u) >= sizeof(i), "size assumption");
266+ static_assert(sizeof(u) >= sizeof(d), "size assumption");
267+ static_assert(sizeof(u) >= sizeof(c), "size assumption");
268+ static_assert(sizeof(u) >= sizeof(b), "size assumption");
269+ static_assert(sizeof(u) >= sizeof(f), "size assumption");
270+ static_assert(sizeof(u) >= sizeof(e), "size assumption");
271+ static_assert(sizeof(u) >= sizeof(v), "size assumption");
272+
273+ auto copyAssign(const any& other) const noexcept -> void {
274+ if (isManaged(other.tag)) {
275+ new (&p) managed<void>(other.p);
276+ } else {
277+ u = other.u;
288278 }
289279 }
290−
291− auto destruct() -> void {
292− switch (tag) {
293− case Tag::String: s.~managed<string>(); break;
294− case Tag::Array: a.~managed<array>(); break;
295− case Tag::Record: r.~managed<record>(); break;
296− case Tag::Closure: l.~managed<Closure>(); break;
297− case Tag::EffClosure: k.~managed<EffClosure>(); break;
298− case Tag::Map:
299− case Tag::Data:
300− case Tag::Pointer: p.~managed<void>(); break;
301−
302− default: break;
280+ auto moveAssign(any& other) const noexcept -> void {
281+ if (isManaged(other.tag)) {
282+ new (&p) managed<void>(std::move(other.p));
283+ } else {
284+ u = other.u;
303285 }
304286 }
305287
306288 public:
307289 any(const any& other) noexcept : tag(other.tag) {
308− assign(other);
290+ copyAssign(other);
309291 }
310292
311293 any(any&& other) noexcept : tag(other.tag) {
312− assign(std::move(other));
294+ moveAssign(other);
313295 }
314296
315297 auto operator=(const any& rhs) noexcept -> any& {
316298 destruct();
317299 tag = rhs.tag;
318− assign(rhs);
300+ copyAssign(rhs);
319301 return *this;
320302 }
321303
322304 auto operator=(any&& rhs) noexcept -> any& {
323305 destruct();
324306 tag = rhs.tag;
325− assign(std::move(rhs));
307+ moveAssign(rhs);
326308 return *this;
327309 }
328310
@@ -431,7 +413,7 @@ namespace Private {
431413
432414 template <size_t N>
433415 struct TagHelper<any::dict<N>> {
434− static constexpr any::Tag tag = any::Tag::Map;
416+ static constexpr any::Tag tag = any::Tag::Dictionary;
435417 };
436418
437419 template <size_t N>
@@ -458,19 +440,8 @@ inline auto cast(const any& a) ->
458440 return a;
459441}
460442
461−template <typename T>
462−inline auto cast(const any& a) ->
463− typename std::enable_if<std::is_same<T, string>::value ||
464− std::is_same<T, any::array>::value ||
465− std::is_same<T, any::record>::value, const T&>::type {
466− return a;
467−}
468−
469443template <typename T,
470− typename = typename std::enable_if<std::is_class<T>::value &&
471− !std::is_same<T,string>::value &&
472− !std::is_same<T,any::array>::value &&
473− !std::is_same<T,any::record>::value>::type>
444+ typename = typename std::enable_if<std::is_class<T>::value>::type>
474445inline auto cast(const any& a) -> T& {
475446 return *static_cast<T*>(a.extractPointer(IF_DEBUG(Private::TagHelper<T>::tag)));
476447}