@@ -20,15 +20,18 @@
20#if defined(DEBUG)
20#if defined(DEBUG)
21 #include <cassert>
21 #include <cassert>
22 #include <climits>
22 #include <climits>
23+ #define IF_DEBUG(x) x
24 #define NDEBUG
25 #define NDEBUG
25 #undef assert
26 #undef assert
26 #define assert(x)
27 #define assert(x)
29#include <functional>
31#include <functional>
30#include <string>
32#include <string>
31#include <vector>
33#include <vector>
32#include <deque>
35#include <deque>
33#include <utility>
36#include <utility>
34#include <stdexcept>
37#include <stdexcept>
@@ -83,7 +86,10 @@ class any {
84 using map_pair = std::pair<const char * const, const any>;
87 using map_pair = std::pair<const char * const, const any>;
85 using map = std::vector<map_pair WITH_ALLOCATOR(map_pair)>;
88 using map = std::vector<map_pair WITH_ALLOCATOR(map_pair)>;
86− using data = std::vector<any WITH_ALLOCATOR(any)>;
91+ using data = std::array<any, N>;
87 using array = std::deque<any WITH_ALLOCATOR(any)>;
93 using array = std::deque<any WITH_ALLOCATOR(any)>;
88 using fn = auto (*)(const any&) -> any;
94 using fn = auto (*)(const any&) -> any;
89 using eff_fn = auto (*)() -> any;
95 using eff_fn = auto (*)() -> any;
@@ -135,7 +141,6 @@ class any {
135 mutable void * u;
141 mutable void * u;
136 mutable managed<std::string> s;
142 mutable managed<std::string> s;
137 mutable managed<map> m;
143 mutable managed<map> m;
138− mutable managed<data> v;
139 mutable managed<array> a;
144 mutable managed<array> a;
140 mutable managed<closure> l;
145 mutable managed<closure> l;
141 mutable managed<eff_closure> k;
146 mutable managed<eff_closure> k;
@@ -168,8 +173,8 @@ class any {
168 any(const map& val) : type(Type::Map), m(make_managed<map>(val)) {}
173 any(const map& val) : type(Type::Map), m(make_managed<map>(val)) {}
169 any(map&& val) noexcept : type(Type::Map), m(make_managed<map>(std::move(val))) {}
174 any(map&& val) noexcept : type(Type::Map), m(make_managed<map>(std::move(val))) {}
171− any(const data& val) : type(Type::Data), v(make_managed<data>(val)) {}
176+ template <size_t N>
172− any(data&& val) noexcept : type(Type::Data), v(make_managed<data>(std::move(val))) {}
177+ any(data<N>&& val) noexcept : type(Type::Data), p(make_managed<data<N>>(std::move(val))) {}
174 any(const array& val) : type(Type::Array), a(make_managed<array>(val)) {}
179 any(const array& val) : type(Type::Array), a(make_managed<array>(val)) {}
175 any(array&& val) noexcept : type(Type::Array), a(make_managed<array>(std::move(val))) {}
180 any(array&& val) noexcept : type(Type::Array), a(make_managed<array>(std::move(val))) {}
@@ -245,10 +250,10 @@ class any {
246 case Type::String: new (&s) managed<std::string>(move_if_rvalue<T>(other.s)); break;
251 case Type::String: new (&s) managed<std::string>(move_if_rvalue<T>(other.s)); break;
247 case Type::Map: new (&m) managed<map>(move_if_rvalue<T>(other.m)); break;
252 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;
249 case Type::Array: new (&a) managed<array>(move_if_rvalue<T>(other.a)); break;
253 case Type::Array: new (&a) managed<array>(move_if_rvalue<T>(other.a)); break;
250 case Type::Closure: new (&l) managed<closure>(move_if_rvalue<T>(other.l)); break;
254 case Type::Closure: new (&l) managed<closure>(move_if_rvalue<T>(other.l)); break;
251 case Type::EffClosure: new (&k) managed<eff_closure>(move_if_rvalue<T>(other.k)); break;
255 case Type::EffClosure: new (&k) managed<eff_closure>(move_if_rvalue<T>(other.k)); break;
252 case Type::Pointer: new (&p) managed<void>(move_if_rvalue<T>(other.p)); break;
257 case Type::Pointer: new (&p) managed<void>(move_if_rvalue<T>(other.p)); break;
254 default: assert(false && "Bad 'any' type"); break;
259 default: assert(false && "Bad 'any' type"); break;
@@ -259,10 +264,10 @@ class any {
259 switch (type) {
264 switch (type) {
260 case Type::String: s.~managed<std::string>(); break;
265 case Type::String: s.~managed<std::string>(); break;
261 case Type::Map: m.~managed<map>(); break;
266 case Type::Map: m.~managed<map>(); break;
262− case Type::Data: v.~managed<data>(); break;
263 case Type::Array: a.~managed<array>(); break;
267 case Type::Array: a.~managed<array>(); break;
264 case Type::Closure: l.~managed<closure>(); break;
268 case Type::Closure: l.~managed<closure>(); break;
265 case Type::EffClosure: k.~managed<eff_closure>(); break;
269 case Type::EffClosure: k.~managed<eff_closure>(); break;
266 case Type::Pointer: p.~managed<void>(); break;
271 case Type::Pointer: p.~managed<void>(); break;
268 default: break;
273 default: break;
@@ -310,7 +315,6 @@ class any {
310 operator char() const;
315 operator char() const;
311 operator cstring() const;
316 operator cstring() const;
312 operator const map&() const;
317 operator const map&() const;
313− operator const data&() const;
314 operator const array&() const;
318 operator const array&() const;
316 auto operator[](const char[]) const -> const any&;
320 auto operator[](const char[]) const -> const any&;
@@ -319,7 +323,7 @@ class any {
320 auto contains(const char[]) const -> bool;
324 auto contains(const char[]) const -> bool;
322− auto extractPointer() const -> void*;
326+ auto extractPointer(IF_DEBUG(const Type)) const -> void*;
324 auto rawPointer() const -> void* {
328 auto rawPointer() const -> void* {
325 const any& variant = unthunkVariant(*this);
329 const any& variant = unthunkVariant(*this);
@@ -387,6 +391,19 @@ class any {
387 friend auto operator-(const any&) -> any; // unary negate
391 friend auto operator-(const any&) -> any; // unary negate
394+template <typename T, typename U=void>
398+struct TypeTag<any::data<N>> {
399+ static constexpr any::Type TypeId = any::Type::Data;
402+template <typename T>
404+ static constexpr any::Type TypeId = any::Type::Pointer;
390template <typename T>
407template <typename T>
391inline auto cast(const any& a) ->
408inline auto cast(const any& a) ->
392 typename std::enable_if<std::is_arithmetic<T>::value ||
409 typename std::enable_if<std::is_arithmetic<T>::value ||
@@ -397,17 +414,15 @@ inline auto cast(const any& a) ->
397template <typename T>
414template <typename T>
398inline auto cast(const any& a) ->
415inline auto cast(const any& a) ->
399 typename std::enable_if<std::is_same<T, any::map>::value ||
416 typename std::enable_if<std::is_same<T, any::map>::value ||
400− std::is_same<T, any::data>::value ||
401 std::is_same<T, any::array>::value, const T&>::type {
417 std::is_same<T, any::array>::value, const T&>::type {
402 return a;
418 return a;
405template <typename T, typename = typename std::enable_if<std::is_class<T>::value>::type>
421template <typename T, typename = typename std::enable_if<std::is_class<T>::value>::type>
406inline auto cast(const any& a) ->
422inline auto cast(const any& a) ->
407− typename std::enable_if<!std::is_same<T, any::map>::value &&
423+ typename std::enable_if<!std::is_same<T, any::map>::value &&
408− !std::is_same<T, any::data>::value &&
409 !std::is_same<T, any::array>::value, T&>::type {
424 !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)));
413template <typename T>
428template <typename T>