@@ -20,15 +20,18 @@
2020#if defined(DEBUG)
2121 #include <cassert>
2222 #include <climits>
23+ #define IF_DEBUG(x) x
2324#else
2425 #define NDEBUG
2526 #undef assert
2627 #define assert(x)
28+ #define IF_DEBUG(_)
2729#endif
2830
2931#include <functional>
3032#include <string>
3133#include <vector>
34+#include <array>
3235#include <deque>
3336#include <utility>
3437#include <stdexcept>
@@ -83,7 +86,10 @@ class any {
8386
8487 using map_pair = std::pair<const char * const, const any>;
8588 using map = std::vector<map_pair WITH_ALLOCATOR(map_pair)>;
86− using data = std::vector<any WITH_ALLOCATOR(any)>;
89+
90+ template <size_t N>
91+ using data = std::array<any, N>;
92+
8793 using array = std::deque<any WITH_ALLOCATOR(any)>;
8894 using fn = auto (*)(const any&) -> any;
8995 using eff_fn = auto (*)() -> any;
@@ -135,7 +141,6 @@ class any {
135141 mutable void * u;
136142 mutable managed<std::string> s;
137143 mutable managed<map> m;
138− mutable managed<data> v;
139144 mutable managed<array> a;
140145 mutable managed<closure> l;
141146 mutable managed<eff_closure> k;
@@ -168,8 +173,8 @@ class any {
168173 any(const map& val) : type(Type::Map), m(make_managed<map>(val)) {}
169174 any(map&& val) noexcept : type(Type::Map), m(make_managed<map>(std::move(val))) {}
170175
171− any(const data& val) : type(Type::Data), v(make_managed<data>(val)) {}
172− any(data&& val) noexcept : type(Type::Data), v(make_managed<data>(std::move(val))) {}
176+ template <size_t N>
177+ any(data<N>&& val) noexcept : type(Type::Data), p(make_managed<data<N>>(std::move(val))) {}
173178
174179 any(const array& val) : type(Type::Array), a(make_managed<array>(val)) {}
175180 any(array&& val) noexcept : type(Type::Array), a(make_managed<array>(std::move(val))) {}
@@ -245,10 +250,10 @@ class any {
245250
246251 case Type::String: new (&s) managed<std::string>(move_if_rvalue<T>(other.s)); break;
247252 case Type::Map: new (&m) managed<map>(move_if_rvalue<T>(other.m)); break;
248− case Type::Data: new (&v) managed<data>(move_if_rvalue<T>(other.v)); break;
249253 case Type::Array: new (&a) managed<array>(move_if_rvalue<T>(other.a)); break;
250254 case Type::Closure: new (&l) managed<closure>(move_if_rvalue<T>(other.l)); break;
251255 case Type::EffClosure: new (&k) managed<eff_closure>(move_if_rvalue<T>(other.k)); break;
256+ case Type::Data:
252257 case Type::Pointer: new (&p) managed<void>(move_if_rvalue<T>(other.p)); break;
253258
254259 default: assert(false && "Bad 'any' type"); break;
@@ -259,10 +264,10 @@ class any {
259264 switch (type) {
260265 case Type::String: s.~managed<std::string>(); break;
261266 case Type::Map: m.~managed<map>(); break;
262− case Type::Data: v.~managed<data>(); break;
263267 case Type::Array: a.~managed<array>(); break;
264268 case Type::Closure: l.~managed<closure>(); break;
265269 case Type::EffClosure: k.~managed<eff_closure>(); break;
270+ case Type::Data:
266271 case Type::Pointer: p.~managed<void>(); break;
267272
268273 default: break;
@@ -310,7 +315,6 @@ class any {
310315 operator char() const;
311316 operator cstring() const;
312317 operator const map&() const;
313− operator const data&() const;
314318 operator const array&() const;
315319
316320 auto operator[](const char[]) const -> const any&;
@@ -319,7 +323,7 @@ class any {
319323
320324 auto contains(const char[]) const -> bool;
321325
322− auto extractPointer() const -> void*;
326+ auto extractPointer(IF_DEBUG(const Type)) const -> void*;
323327
324328 auto rawPointer() const -> void* {
325329 const any& variant = unthunkVariant(*this);
@@ -387,6 +391,19 @@ class any {
387391 friend auto operator-(const any&) -> any; // unary negate
388392};
389393
394+template <typename T, typename U=void>
395+struct TypeTag {};
396+
397+template <size_t N>
398+struct TypeTag<any::data<N>> {
399+ static constexpr any::Type TypeId = any::Type::Data;
400+};
401+
402+template <typename T>
403+struct TypeTag<T> {
404+ static constexpr any::Type TypeId = any::Type::Pointer;
405+};
406+
390407template <typename T>
391408inline auto cast(const any& a) ->
392409 typename std::enable_if<std::is_arithmetic<T>::value ||
@@ -397,17 +414,15 @@ inline auto cast(const any& a) ->
397414template <typename T>
398415inline auto cast(const any& a) ->
399416 typename std::enable_if<std::is_same<T, any::map>::value ||
400− std::is_same<T, any::data>::value ||
401417 std::is_same<T, any::array>::value, const T&>::type {
402418 return a;
403419}
404420
405421template <typename T, typename = typename std::enable_if<std::is_class<T>::value>::type>
406422inline auto cast(const any& a) ->
407− typename std::enable_if<!std::is_same<T, any::map>::value &&
408− !std::is_same<T, any::data>::value &&
423+ typename std::enable_if<!std::is_same<T, any::map>::value &&
409424 !std::is_same<T, any::array>::value, T&>::type {
410− return *static_cast<T*>(a.extractPointer());
425+ return *static_cast<T*>(a.extractPointer(IF_DEBUG(TypeTag<T>::TypeId)));
411426}
412427
413428template <typename T>