/* * Copyright (c) 2009 Sebastian Nibisz * published under NCSA License * * variant.hpp */ #ifndef VARIANT_HPP_INCLUDED #define VARIANT_HPP_INCLUDED #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif #if defined(_MSC_VER) #ifdef min #undef min #endif #ifdef max #undef max #endif #endif #include #include #include #include #include #include #include #include #include #include #include #include class variant_exception : public std::exception { public: variant_exception() : std::exception() {} }; namespace detail { template class iterator_base { public: iterator_base() {} virtual ~iterator_base() {} virtual iterator_base* clone(void* p) const = 0; virtual bool operator ==(const iterator_base&) const = 0; virtual bool operator !=(const iterator_base&) const = 0; virtual iterator_base& operator ++() { throw variant_exception(); } virtual iterator_base& operator ++(int) { throw variant_exception(); } virtual iterator_base& operator --() { throw variant_exception(); } virtual iterator_base& operator --(int) { throw variant_exception(); } virtual V& operator *() { throw variant_exception(); } virtual const V& operator *() const { throw variant_exception(); } virtual V* operator ->() { throw variant_exception(); } virtual const V* operator ->() const { throw variant_exception(); } }; template class iterator : public iterator_base { public: iterator(const T& i) : _iterator(i) {} iterator_base* clone(void* p) const { return new(p) iterator(*this); } bool operator ==(const iterator_base& i) const { return _iterator == dynamic_cast(i)._iterator; } bool operator !=(const iterator_base& i) const { return _iterator != dynamic_cast(i)._iterator; } iterator_base& operator ++() { ++_iterator; return *this; } iterator_base& operator ++(int) { _iterator++; return *this; } iterator_base& operator --() { --_iterator; return *this; } iterator_base& operator --(int) { _iterator--; return *this; } V& operator *() { return const_cast(*_iterator); } const V& operator *() const { return *_iterator; } V* operator ->() { return const_cast(&*_iterator); } const V* operator ->() const { return &*_iterator; } T _iterator; }; template class iterator_tmp : public iterator_base { public: iterator_tmp(const T& i) : _iterator(i) {} private: T _iterator; }; template class converter_base { typedef typename V::iterator viterator; typedef typename V::const_iterator vconst_iterator; public: virtual ~converter_base() {} virtual converter_base* clone(void* p) const = 0; virtual void constructor(void*, const void*) = 0; virtual void constructor(void**, const void*) { throw variant_exception(); } virtual void destructor(void*) = 0; virtual void destructor(void**) { throw variant_exception(); } virtual const std::type_info& type() const = 0; virtual bool to_bool(const void* p) const = 0; virtual char to_char(const void* p) const = 0; virtual unsigned char to_uchar(const void* p) const = 0; virtual short to_short(const void* p) const = 0; virtual unsigned short to_ushort(const void* p) const = 0; virtual int to_int(const void* p) const = 0; virtual unsigned int to_uint(const void* p) const = 0; virtual long to_long(const void* p) const = 0; virtual unsigned long to_ulong(const void* p) const = 0; virtual long long to_long_long(const void* p) const = 0; virtual float to_float(const void* p) const = 0; virtual double to_double(const void* p) const = 0; virtual std::string to_string(const void* p) const = 0; virtual int specjalization_id() const = 0; virtual bool is_character() const = 0; virtual bool is_numeric() const = 0; virtual bool is_real() const = 0; virtual bool is_string() const = 0; virtual bool is_pointer() const = 0; virtual bool is_container() const = 0; virtual bool is_object() const = 0; virtual V& back(void*) { throw variant_exception(); } virtual const V& back(const void*) const { throw variant_exception(); } virtual iterator_base* begin(void*, void*) { throw variant_exception(); } virtual const iterator_base* begin(const void*, void*) const { throw variant_exception(); } virtual iterator_base* end(void*, void*) { throw variant_exception(); } virtual const iterator_base* end(const void*, void*) const { throw variant_exception(); } virtual void clear(void*) { throw variant_exception(); } virtual bool empty(const void*) const { throw variant_exception(); } virtual void erase(void*, const V&) { throw variant_exception(); } virtual void erase(void*, vconst_iterator) { throw variant_exception(); } virtual void erase(void*, vconst_iterator, vconst_iterator) { throw variant_exception(); } virtual iterator_base* find(void*, const V&, void*) { throw variant_exception(); } virtual const iterator_base* find(const void*, const V&, void*) const { throw variant_exception(); } virtual V& front(void*) { throw variant_exception(); } virtual const V& front(const void*) const { throw variant_exception(); } virtual void insert(void*, const V&) { throw variant_exception(); } virtual void insert(void*, vconst_iterator, const V&) { throw variant_exception(); } virtual void insert(void*, vconst_iterator, vconst_iterator) { throw variant_exception(); } virtual void insert(void*, vconst_iterator, vconst_iterator, vconst_iterator) { throw variant_exception(); } virtual size_t max_size(const void*) const { throw variant_exception(); } virtual void pop_back(void*) { throw variant_exception(); } virtual void pop_front(void*) { throw variant_exception(); } virtual void push_back(void*, const V&) { throw variant_exception(); } virtual void push_front(void*, const V&) { throw variant_exception(); } virtual iterator_base* rbegin(void*, void*) { throw variant_exception(); } virtual const iterator_base* rbegin(const void*, void*) const { throw variant_exception(); } virtual iterator_base* rend(void*, void*) { throw variant_exception(); } virtual const iterator_base* rend(const void*, void*) const { throw variant_exception(); } virtual size_t size(const void*) const { throw variant_exception(); } virtual void sort_asc(void*, converter_base*&, void*) { throw variant_exception(); } virtual void sort_desc(void*, converter_base*&, void*) { throw variant_exception(); } }; template class converter; template class converter_numeric { template class is_real { typedef char one; typedef struct { char c[2]; } two; static two test(bool) ; static two test(char) ; static two test(unsigned char) ; static two test(short) ; static two test(unsigned short) ; static two test(int) ; static two test(unsigned int) ; static two test(long) ; static two test(unsigned long) ; static two test(long long) ; static one test(float) ; static one test(double) ; static one test(long double) ; static U makeT(); public: enum { yes = sizeof(test(makeT())) == sizeof(one) }; }; public: enum { specjalization_id = is_real::yes + 1 }; bool to_bool(const void* p) const { return static_cast(*static_cast(p)) != 0; } char to_char(const void* p) const { return static_cast(*static_cast(p)); } unsigned char to_uchar(const void* p) const { return static_cast(*static_cast(p)); } short to_short(const void* p) const { return static_cast(*static_cast(p)); } unsigned short to_ushort(const void* p) const { return static_cast(*static_cast(p)); } int to_int(const void* p) const { return static_cast(*static_cast(p)); } unsigned int to_uint(const void* p) const { return static_cast(*static_cast(p)); } long to_long(const void* p) const { return static_cast(*static_cast(p)); } unsigned long to_ulong(const void* p) const { return static_cast(*static_cast(p)); } long long to_long_long(const void* p) const { return static_cast(*static_cast(p)); } float to_float(const void* p) const { return static_cast(*static_cast(p)); } double to_double(const void* p) const { return static_cast(*static_cast(p)); } std::string to_string(const void* p) const { return static_cast(std::stringstream() << *static_cast(p)).str(); } }; template class converter_numeric { public: enum { specjalization_id = 4 }; bool to_bool(const void*) const { throw variant_exception(); } char to_char(const void*) const { throw variant_exception(); } unsigned char to_uchar(const void*) const { throw variant_exception(); } short to_short(const void*) const { throw variant_exception(); } unsigned short to_ushort(const void*) const { throw variant_exception(); } int to_int(const void*) const { throw variant_exception(); } unsigned int to_uint(const void*) const { throw variant_exception(); } long to_long(const void*) const { throw variant_exception(); } unsigned long to_ulong(const void*) const { throw variant_exception(); } long long to_long_long(const void*) const { throw variant_exception(); } float to_float(const void*) const { throw variant_exception(); } double to_double(const void*) const { throw variant_exception(); } std::string to_string(const void* p) const { typedef typename T::const_iterator iter; std::stringstream s; s << "{"; if (static_cast(p)->begin() != static_cast(p)->end()) { iter end = --static_cast(p)->end(); for (iter i = static_cast(p)->begin(); i != static_cast(p)->end(); ++i) { if (i->is_string()) s << "\"" << *i << "\""; else if (i->is_character()) s << "'" << *i << "'"; else s << *i; if (i != end) s << ", "; } s << "}"; } else s << "}"; return s.str(); } }; template iterator_base* create_iterator(void* p, const T& i) { return new(p) iterator(i); } template struct container { typedef typename V::iterator viterator; typedef typename V::const_iterator vconst_iterator; V& back(void*) { throw variant_exception(); } const V& back(const void*) const { throw variant_exception(); } iterator_base* begin(void*, void*) { throw variant_exception(); } const iterator_base* begin(const void*, void*) const { throw variant_exception(); } iterator_base* end(void*, void*) { throw variant_exception(); } const iterator_base* end(const void*, void*) const { throw variant_exception(); } void clear(void*) { throw variant_exception(); } bool empty(const void*) const { throw variant_exception(); } void erase(void*, const V&) { throw variant_exception(); } void erase(void*, vconst_iterator) { throw variant_exception(); } void erase(void*, vconst_iterator, vconst_iterator) { throw variant_exception(); } iterator_base* find(void*, const V&, void*) { throw variant_exception(); } const iterator_base* find(const void*, const V&, void*) const { throw variant_exception(); } V& front(void*) { throw variant_exception(); } const V& front(const void*) const { throw variant_exception(); } void insert(void*, const V&) { throw variant_exception(); } void insert(void*, vconst_iterator, const V&) { throw variant_exception(); } void insert(void*, vconst_iterator, vconst_iterator) { throw variant_exception(); } void insert(void*, vconst_iterator, vconst_iterator, vconst_iterator) { throw variant_exception(); } size_t max_size(const void*) const { throw variant_exception(); } void pop_back(void*) { throw variant_exception(); } void pop_front(void*) { throw variant_exception(); } void push_back(void*, const V&) { throw variant_exception(); } void push_front(void*, const V&) { throw variant_exception(); } iterator_base* rbegin(void*, void*) { throw variant_exception(); } const iterator_base* rbegin(const void*, void*) const { throw variant_exception(); } iterator_base* rend(void*, void*) { throw variant_exception(); } const iterator_base* rend(const void*, void*) const { throw variant_exception(); } size_t size(const void*) const { throw variant_exception(); } void sort_asc(void*, converter_base*&, void*) { throw variant_exception(); } void sort_desc(void*, converter_base*&, void*) { throw variant_exception(); } }; template struct container_base { typedef typename V::iterator viterator; typedef typename V::const_iterator vconst_iterator; iterator_base* begin(void* p, void* i) { return create_iterator(i, static_cast(p)->begin()); } const iterator_base* begin(const void* p, void* i) const { return create_iterator(i, const_cast(static_cast(p))->begin()); } iterator_base* end(void* p, void* i) { return create_iterator(i, static_cast(p)->end()); } const iterator_base* end(const void* p, void* i) const { return create_iterator(i, const_cast(static_cast(p))->end()); } void clear(void* p) { static_cast(p)->clear(); } bool empty(const void* p) const { return static_cast(p)->empty(); } void erase(void* p, vconst_iterator w) { static_cast(p)->erase(w._stl_iterator((T*)0)); } void erase(void* p, vconst_iterator f, vconst_iterator l) { static_cast(p)->erase(f._stl_iterator((T*)0), l._stl_iterator((T*)0)); } void insert(void* p, vconst_iterator w, const V& v) { static_cast(p)->insert(w._stl_iterator((T*)0), v); } size_t max_size(const void* p) const { return static_cast(p)->max_size(); } iterator_base* rbegin(void* p, void* i) { return create_iterator(i, static_cast(p)->rbegin()); } const iterator_base* rbegin(const void* p, void* i) const { return create_iterator(i, const_cast(static_cast(p))->rbegin()); } iterator_base* rend(void* p, void* i) { return create_iterator(i, static_cast(p)->rend()); } const iterator_base* rend(const void* p, void* i) const { return create_iterator(i, const_cast(static_cast(p))->rend()); } size_t size(const void* p) const { return static_cast(p)->size(); } }; template struct container, false> : container_base, false> { typedef std::vector T; typedef typename V::iterator viterator; typedef typename V::const_iterator vconst_iterator; V& back(void* p) { return static_cast(p)->back(); } const V& back(const void* p) const { return static_cast(p)->back(); } using container_base, false>::erase; void erase(void* p, const V& v) { static_cast(p)->erase(std::find(static_cast(p)->begin(), static_cast(p)->end(), v)); } iterator_base* find(void* p, const V& v, void* i) { return create_iterator(i, std::find(static_cast(p)->begin(), static_cast(p)->end(), v)); } const iterator_base* find(const void* p, const V& v, void* i) const { return create_iterator(i, std::find(const_cast(static_cast(p))->begin(), const_cast(static_cast(p))->end(), v)); } V& front(void* p) { return static_cast(p)->front(); } const V& front(const void* p) const { return static_cast(p)->front(); } using container_base, false>::insert; void insert(void* p, const V& v) { static_cast(p)->push_back(v); } void insert(void* p, vconst_iterator f, vconst_iterator l) { static_cast(p)->insert(static_cast(p)->end(), f, l); } void insert(void* p, vconst_iterator w, vconst_iterator f, vconst_iterator l) { static_cast(p)->insert(w._stl_iterator((T*)0), f, l); } void pop_back(void* p) { static_cast(p)->pop_back(); } void pop_front(void* p) { static_cast(p)->erase(static_cast(p)->begin()); } void push_back(void* p, const V& v) { static_cast(p)->push_back(v); } void push_front(void* p, const V& v) { static_cast(p)->insert(static_cast(p)->begin(), v); } void sort_asc(void* p, converter_base*&, void*) { std::sort(static_cast(p)->begin(), static_cast(p)->end(), std::less()); } void sort_desc(void* p, converter_base*&, void*) { std::sort(static_cast(p)->begin(), static_cast(p)->end(), std::greater()); } }; template struct container, false> : container_base, false> { typedef std::deque T; typedef typename V::iterator viterator; typedef typename V::const_iterator vconst_iterator; V& back(void* p) { return static_cast(p)->back(); } const V& back(const void* p) const { return static_cast(p)->back(); } using container_base, false>::erase; void erase(void* p, const V& v) { static_cast(p)->erase(std::find(static_cast(p)->begin(), static_cast(p)->end(), v)); } iterator_base* find(void* p, const V& v, void* i) { return create_iterator(i, std::find(static_cast(p)->begin(), static_cast(p)->end(), v)); } const iterator_base* find(const void* p, const V& v, void* i) const { return create_iterator(i, std::find(const_cast(static_cast(p))->begin(), const_cast(static_cast(p))->end(), v)); } V& front(void* p) { return static_cast(p)->front(); } const V& front(const void* p) const { return static_cast(p)->front(); } using container_base, false>::insert; void insert(void* p, const V& v) { static_cast(p)->push_back(v); } void insert(void* p, vconst_iterator f, vconst_iterator l) { static_cast(p)->insert(static_cast(p)->end(), f, l); } void insert(void* p, vconst_iterator w, vconst_iterator f, vconst_iterator l) { static_cast(p)->insert(w._stl_iterator((T*)0), f, l); } void pop_back(void* p) { static_cast(p)->pop_back(); } void pop_front(void* p) { static_cast(p)->erase(static_cast(p)->begin()); } void push_back(void* p, const V& v) { static_cast(p)->push_back(v); } void push_front(void* p, const V& v) { static_cast(p)->insert(static_cast(p)->begin(), v); } void sort_asc(void* p, converter_base*&, void*) { std::sort(static_cast(p)->begin(), static_cast(p)->end(), std::less()); } void sort_desc(void* p, converter_base*&, void*) { std::sort(static_cast(p)->begin(), static_cast(p)->end(), std::greater()); } }; template struct container, false> : container_base, false> { typedef std::list T; typedef typename V::iterator viterator; typedef typename V::const_iterator vconst_iterator; V& back(void* p) { return static_cast(p)->back(); } const V& back(const void* p) const { return static_cast(p)->back(); } using container_base, false>::erase; void erase(void* p, const V& v) { static_cast(p)->erase(std::find(static_cast(p)->begin(), static_cast(p)->end(), v)); } iterator_base* find(void* p, const V& v, void* i) { return create_iterator(i, std::find(static_cast(p)->begin(), static_cast(p)->end(), v)); } const iterator_base* find(const void* p, const V& v, void* i) const { return create_iterator(i, std::find(const_cast(static_cast(p))->begin(), const_cast(static_cast(p))->end(), v)); } V& front(void* p) { return static_cast(p)->front(); } const V& front(const void* p) const { return static_cast(p)->front(); } using container_base, false>::insert; void insert(void* p, const V& v) { static_cast(p)->push_back(v); } void insert(void* p, vconst_iterator f, vconst_iterator l) { static_cast(p)->insert(static_cast(p)->end(), f, l); } void insert(void* p, vconst_iterator w, vconst_iterator f, vconst_iterator l) { static_cast(p)->insert(w._stl_iterator((T*)0), f, l); } void pop_back(void* p) { static_cast(p)->pop_back(); } void pop_front(void* p) { static_cast(p)->erase(static_cast(p)->begin()); } void push_back(void* p, const V& v) { static_cast(p)->push_back(v); } void push_front(void* p, const V& v) { static_cast(p)->insert(static_cast(p)->begin(), v); } void sort_asc(void* p, converter_base*&, void*) { static_cast(p)->sort(std::less()); } void sort_desc(void* p, converter_base*&, void*) { static_cast(p)->sort(std::greater()); } }; template struct container, false> : container_base, false> { typedef std::set T; typedef typename V::iterator viterator; typedef typename V::const_iterator vconst_iterator; V& back(void* p) { return const_cast(*static_cast(p)->rbegin()); } const V& back(const void* p) const { return *static_cast(p)->rbegin(); } using container_base, false>::erase; void erase(void* p, const V& v) { static_cast(p)->erase(v); } iterator_base* find(void* p, const V& v, void* i) { return create_iterator(i, static_cast(p)->find(v)); } const iterator_base* find(const void* p, const V& v, void* i) const { return create_iterator(i, const_cast(static_cast(p))->find(v)); } V& front(void* p) { return const_cast(*static_cast(p)->begin()); } const V& front(const void* p) const { return *static_cast(p)->begin(); } using container_base, false>::insert; void insert(void* p, const V& v) { static_cast(p)->insert(v); } void insert(void* p, vconst_iterator f, vconst_iterator l) { static_cast(p)->insert(f, l); } void insert(void* p, vconst_iterator, vconst_iterator f, vconst_iterator l) { static_cast(p)->insert(f, l); } void pop_back(void* p) { static_cast(p)->erase(--static_cast(p)->end()); } void pop_front(void* p) { static_cast(p)->erase(static_cast(p)->begin()); } void push_back(void* p, const V& v) { static_cast(p)->insert(static_cast(p)->end(), v); } void push_front(void* p, const V& v) { static_cast(p)->insert(static_cast(p)->begin(), v); } void sort_asc(void* p, converter_base*& c, void* d) { typedef std::set, typename T::allocator_type> type; type t(static_cast(p)->begin(), static_cast(p)->end(), std::less(), static_cast(p)->get_allocator()); c->destructor(p); type* s = new (p) type(); std::swap(t, *s); c->~converter_base(); c = new (d) converter(); } void sort_desc(void* p, converter_base*& c, void* d) { typedef std::set, typename T::allocator_type> type; type t(static_cast(p)->begin(), static_cast(p)->end(), std::greater(), static_cast(p)->get_allocator()); c->destructor(p); type* s = new (p) type(); std::swap(t, *s); c->~converter_base(); c = new (d) converter(); } }; template struct container, false> : container_base, false> { typedef std::multiset T; typedef typename V::iterator viterator; typedef typename V::const_iterator vconst_iterator; V& back(void* p) { return const_cast(*static_cast(p)->rbegin()); } const V& back(const void* p) const { return *static_cast(p)->rbegin(); } using container_base, false>::erase; void erase(void* p, const V& v) { static_cast(p)->erase(v); } iterator_base* find(void* p, const V& v, void* i) { return create_iterator(i, static_cast(p)->find(v)); } const iterator_base* find(const void* p, const V& v, void* i) const { return create_iterator(i, static_cast(p)->find(v)); } V& front(void* p) { return const_cast(*static_cast(p)->begin()); } const V& front(const void* p) const { return *static_cast(p)->begin(); } using container_base, false>::insert; void insert(void* p, const V& v) { static_cast(p)->insert(v); } void insert(void* p, vconst_iterator f, vconst_iterator l) { static_cast(p)->insert(f, l); } void insert(void* p, vconst_iterator, vconst_iterator f, vconst_iterator l) { static_cast(p)->insert(f, l); } void pop_back(void* p) { static_cast(p)->erase(--static_cast(p)->end()); } void pop_front(void* p) { static_cast(p)->erase(static_cast(p)->begin()); } void push_back(void* p, const V& v) { static_cast(p)->insert(static_cast(p)->end(), v); } void push_front(void* p, const V& v) { static_cast(p)->insert(static_cast(p)->begin(), v); } void sort_asc(void* p, converter_base*& c, void* d) { typedef std::multiset, typename T::allocator_type> type; type t(static_cast(p)->begin(), static_cast(p)->end(), std::less(), static_cast(p)->get_allocator()); c->destructor(p); type* s = new (p) type(); std::swap(t, *s); c->~converter_base(); c = new (d) converter(); } void sort_desc(void* p, converter_base*& c, void* d) { typedef std::multiset, typename T::allocator_type> type; type t(static_cast(p)->begin(), static_cast(p)->end(), std::greater(), static_cast(p)->get_allocator()); c->destructor(p); type* s = new (p) type(); std::swap(t, *s); c->~converter_base(); c = new (d) converter(); } }; template class converter : public converter_base { template class _is_numeric { typedef char one; typedef struct { char c[2]; } two; static one test(bool) ; static one test(char) ; static one test(unsigned char) ; static one test(short) ; static one test(unsigned short) ; static one test(int) ; static one test(unsigned int) ; static one test(long) ; static one test(unsigned long) ; static one test(long long) ; static one test(float) ; static one test(double) ; static one test(long double) ; static two test(...); static U makeT(); public: enum { yes = sizeof(test(makeT())) == sizeof(one) }; }; int _value(int v) const { return v; } public: typedef typename V::iterator viterator; typedef typename V::const_iterator vconst_iterator; int specjalization_id() const { return converter_numeric::yes>::specjalization_id; } bool is_character() const { return _value(converter_numeric::yes>::specjalization_id) == 0; } bool is_numeric() const { return _value(converter_numeric::yes>::specjalization_id) < 3; } bool is_real() const { return _value(converter_numeric::yes>::specjalization_id) == 2; } bool is_string() const { return _value(converter_numeric::yes>::specjalization_id) == 3; } bool is_pointer() const { return _value(converter_numeric::yes>::specjalization_id) == 5; } bool is_container() const { return _value(converter_numeric::yes>::specjalization_id) == 4; } bool is_object() const { return false; } converter_base* clone(void* p) const { return new(p) converter(*this); } void constructor(void* data, const void* p) { new (data) T(*reinterpret_cast(p)); } void destructor(void* data) { reinterpret_cast(data)->~T(); } const std::type_info& type() const { return typeid(T); } bool to_bool(const void* p) const { return converter_numeric::yes>().to_bool(p); } char to_char(const void* p) const { return converter_numeric::yes>().to_char(p); } unsigned char to_uchar(const void* p) const { return converter_numeric::yes>().to_uchar(p); } short to_short(const void* p) const { return converter_numeric::yes>().to_short(p); } unsigned short to_ushort(const void* p) const { return converter_numeric::yes>().to_ushort(p); } int to_int(const void* p) const { return converter_numeric::yes>().to_int(p); } unsigned int to_uint(const void* p) const { return converter_numeric::yes>().to_uint(p); } long to_long(const void* p) const { return converter_numeric::yes>().to_long(p); } unsigned long to_ulong(const void* p) const { return converter_numeric::yes>().to_ulong(p); } long long to_long_long(const void* p) const { return converter_numeric::yes>().to_long_long(p); } float to_float(const void* p) const { return converter_numeric::yes>().to_float(p); } double to_double(const void* p) const { return converter_numeric::yes>().to_double(p); } std::string to_string(const void* p) const { return converter_numeric::yes>().to_string(p); } V& back(void* p) { return const_cast(container::yes>().back(p)); } const V& back(const void* p) const { return container::yes>().back(p); } iterator_base* begin(void* p, void* i) { return container::yes>().begin(p, i); } const iterator_base* begin(const void* p, void* i) const { return container::yes>().begin(p, i); } iterator_base* end(void* p, void* i) { return container::yes>().end(p, i); } const iterator_base* end(const void* p, void* i) const { return container::yes>().end(p, i); } void clear(void* p) { container::yes>().clear(p); } bool empty(const void* p) const { return container::yes>().empty(p); } void erase(void* p, const V& v) { container::yes>().erase(p, v); } void erase(void* p, vconst_iterator w) { container::yes>().erase(p, w); } void erase(void* p, vconst_iterator f, vconst_iterator l) { container::yes>().erase(p, f, l); } iterator_base* find(void* p, const V& v, void* i) { return container::yes>().find(p, v, i); } const iterator_base* find(const void* p, const V& v, void* i) const { return container::yes>().find(p, v, i); } V& front(void* p) { return const_cast(container::yes>().front(p)); } const V& front(const void* p) const { return container::yes>().front(p); } void insert(void* p, const V& v) { container::yes>().insert(p, v); } void insert(void* p, vconst_iterator w, const V& v) { container::yes>().insert(p, w, v); } void insert(void* p, vconst_iterator f, vconst_iterator l) { container::yes>().insert(p, f, l); } void insert(void* p, vconst_iterator w, vconst_iterator f, vconst_iterator l) { container::yes>().insert(p, w, f, l); } size_t max_size(const void* p) const { return container::yes>().max_size(p); } void pop_back(void* p) { container::yes>().pop_back(p); } void pop_front(void* p) { container::yes>().pop_front(p); } void push_back(void* p, const V& v) { container::yes>().push_back(p, v); } void push_front(void* p, const V& v) { container::yes>().push_front(p, v); } iterator_base* rbegin(void* p, void* i) { return container::yes>().rbegin(p, i); } const iterator_base* rbegin(const void* p, void* i) const { return container::yes>().rbegin(p, i); } iterator_base* rend(void* p, void* i) { return container::yes>().rend(p, i); } const iterator_base* rend(const void* p, void* i) const { return container::yes>().rend(p, i); } size_t size(const void* p) const { return container::yes>().size(p); } void sort_asc(void* p, converter_base*& c, void* d) { container::yes>().sort_asc(p, c, d); } void sort_desc(void* p, converter_base*& c, void* d) { container::yes>().sort_desc(p, c, d); } }; template class converter : public converter_base { typedef char Type; public: int specjalization_id() const { return 0; } bool is_character() const { return true; } bool is_numeric() const { return true; } bool is_real() const { return false; } bool is_string() const { return false; } bool is_pointer() const { return false; } bool is_container() const { return false; } bool is_object() const { return false; } converter_base* clone(void* p) const { return new(p) converter(*this); } void constructor(void* data, const void* p) { new (data) Type(*reinterpret_cast(p)); } void destructor(void* data) { reinterpret_cast(data)->~Type(); } const std::type_info& type() const { return typeid(Type); } bool to_bool(const void* p) const { return *static_cast(p) != 0; } char to_char(const void* p) const { return *static_cast(p); } unsigned char to_uchar(const void* p) const { return static_cast(*static_cast(p)); } short to_short(const void* p) const { return static_cast(*static_cast(p)); } unsigned short to_ushort(const void* p) const { return static_cast(*static_cast(p)); } int to_int(const void* p) const { return static_cast(*static_cast(p)); } unsigned int to_uint(const void* p) const { return static_cast(*static_cast(p)); } long to_long(const void* p) const { return static_cast(*static_cast(p)); } unsigned long to_ulong(const void* p) const { return static_cast(*static_cast(p)); } long long to_long_long(const void* p) const { return static_cast(*static_cast(p)); } float to_float(const void* p) const { return static_cast(*static_cast(p)); } double to_double(const void* p) const { return static_cast(*static_cast(p)); } std::string to_string(const void* p) const { return std::string() + *static_cast(p); } }; template class converter : public converter_base { typedef unsigned char Type; public: int specjalization_id() const { return 0; } bool is_character() const { return true; } bool is_numeric() const { return true; } bool is_real() const { return false; } bool is_string() const { return false; } bool is_pointer() const { return false; } bool is_container() const { return false; } bool is_object() const { return false; } converter_base* clone(void* p) const { return new(p) converter(*this); } void constructor(void* data, const void* p) { new (data) Type(*reinterpret_cast(p)); } void destructor(void* data) { reinterpret_cast(data)->~Type(); } const std::type_info& type() const { return typeid(Type); } bool to_bool(const void* p) const { return *static_cast(p) != 0; } char to_char(const void* p) const { return *static_cast(p); } unsigned char to_uchar(const void* p) const { return static_cast(*static_cast(p)); } short to_short(const void* p) const { return static_cast(*static_cast(p)); } unsigned short to_ushort(const void* p) const { return static_cast(*static_cast(p)); } int to_int(const void* p) const { return static_cast(*static_cast(p)); } unsigned int to_uint(const void* p) const { return static_cast(*static_cast(p)); } long to_long(const void* p) const { return static_cast(*static_cast(p)); } unsigned long to_ulong(const void* p) const { return static_cast(*static_cast(p)); } long long to_long_long(const void* p) const { return static_cast(*static_cast(p)); } float to_float(const void* p) const { return static_cast(*static_cast(p)); } double to_double(const void* p) const { return static_cast(*static_cast(p)); } std::string to_string(const void* p) const { return std::string() + *static_cast(p); } }; template class converter : public converter_base { typedef std::string Type; public: int specjalization_id() const { return 3; } bool is_character() const { return false; } bool is_numeric() const { return false; } bool is_real() const { return false; } bool is_string() const { return true; } bool is_pointer() const { return false; } bool is_container() const { return false; } bool is_object() const { return false; } converter_base* clone(void* p) const { return new(p) converter(*this); } void constructor(void* data, const void* p) { new (data) Type(*reinterpret_cast(p)); } void destructor(void* data) { reinterpret_cast(data)->~Type(); } const std::type_info& type() const { return typeid(Type); } bool to_bool(const void* p) const { std::istringstream iss(*static_cast(p)); bool i; iss >> i; return !iss.fail() ? i : throw variant_exception(); } char to_char(const void* p) const { std::istringstream iss(*static_cast(p)); char i; iss >> i; return !iss.fail() ? i : throw variant_exception(); } unsigned char to_uchar(const void* p) const { std::istringstream iss(*static_cast(p)); unsigned char i; iss >> i; return !iss.fail() ? i : throw variant_exception(); } short to_short(const void* p) const { std::istringstream iss(*static_cast(p)); short i; iss >> i; return !iss.fail() ? i : throw variant_exception(); } unsigned short to_ushort(const void* p) const { std::istringstream iss(*static_cast(p)); unsigned short i; iss >> i; return !iss.fail() ? i : throw variant_exception(); } int to_int(const void* p) const { std::istringstream iss(*static_cast(p)); int i; iss >> i; return !iss.fail() ? i : throw variant_exception(); } unsigned int to_uint(const void* p) const { std::istringstream iss(*static_cast(p)); unsigned int i; iss >> i; return !iss.fail() ? i : throw variant_exception(); } long to_long(const void* p) const { std::istringstream iss(*static_cast(p)); long i; iss >> i; return !iss.fail() ? i : throw variant_exception(); } unsigned long to_ulong(const void* p) const { std::istringstream iss(*static_cast(p)); unsigned long i; iss >> i; return !iss.fail() ? i : throw variant_exception(); } long long to_long_long(const void* p) const { std::istringstream iss(*static_cast(p)); long long i; iss >> i; return !iss.fail() ? i : throw variant_exception(); } float to_float(const void* p) const { std::istringstream iss(*static_cast(p)); float i; iss >> i; return !iss.fail() ? i : throw variant_exception(); } double to_double(const void* p) const { std::istringstream iss(*static_cast(p)); double i; iss >> i; return !iss.fail() ? i : throw variant_exception(); } Type to_string(const void* p) const { return *static_cast(p); } }; template class converter : public converter_base { typedef T* Type; public: int specjalization_id() const { return 5; } bool is_character() const { return false; } bool is_numeric() const { return false; } bool is_real() const { return false; } bool is_string() const { return false; } bool is_pointer() const { return true; } bool is_container() const { return false; } bool is_object() const { return false; } converter_base* clone(void* p) const { return new(p) converter(*this); } void constructor(void* data, const void* p) { new (data) Type(*reinterpret_cast(p)); } void destructor(void* data) { /*reinterpret_cast(data)->~Type();*/ } const std::type_info& type() const { return typeid(Type); } bool to_bool(const void* p) const { return *reinterpret_cast(p) != 0; } char to_char(const void* p) const { throw variant_exception(); } unsigned char to_uchar(const void* p) const { throw variant_exception(); } short to_short(const void* p) const { throw variant_exception(); } unsigned short to_ushort(const void* p) const { throw variant_exception(); } int to_int(const void* p) const { throw variant_exception(); } unsigned int to_uint(const void* p) const { throw variant_exception(); } long to_long(const void* p) const { throw variant_exception(); } unsigned long to_ulong(const void* p) const { throw variant_exception(); } long long to_long_long(const void* p) const { throw variant_exception(); } float to_float(const void* p) const { throw variant_exception(); } double to_double(const void* p) const { throw variant_exception(); } std::string to_string(const void* p) const { return static_cast(std::stringstream() << reinterpret_cast(*reinterpret_cast(p))).str(); } }; template struct converter_string { std::string to_string(const void* p) const { return static_cast(*static_cast(p)); } }; template struct converter_string { std::string to_string(const void* p) const { std::stringstream stream; stream << "["; stream << typeid(T).name(); stream << "]"; return stream.str(); } }; template class converter : public converter_base { template class _is_numeric { typedef char one; typedef struct { char c[2]; } two; static one test(bool) ; static one test(char) ; static one test(unsigned char) ; static one test(short) ; static one test(unsigned short) ; static one test(int) ; static one test(unsigned int) ; static one test(long) ; static one test(unsigned long) ; static one test(long long) ; static one test(float) ; static one test(double) ; static one test(long double) ; static two test(...); static U makeT(); public: enum { yes = sizeof(test(makeT())) == sizeof(one) }; }; template class _covertible_to_string { typedef char one; typedef struct {char c[2];} two; static one test(std::string) ; static two test(...); static U makeU(); public: enum { yes = sizeof(test(makeU())) == sizeof(one) }; }; int _value(int v) const { return v; } public: typedef typename V::iterator viterator; typedef typename V::const_iterator vconst_iterator; int specjalization_id() const { return 6; } bool is_character() const { return false; } bool is_numeric() const { return false; } bool is_real() const { return false; } bool is_string() const { return false; } bool is_pointer() const { return false; } bool is_container() const { return false; } bool is_object() const { return true; } converter_base* clone(void* p) const { return new(p) converter(*this); } void constructor(void* data, const void* p) { new (data) T(*reinterpret_cast(p)); } void constructor(void** data, const void* p) { *data = new T(*reinterpret_cast(p)); } void destructor(void* data) { reinterpret_cast(data)->~T(); } void destructor(void** data) { delete reinterpret_cast(*data); *data = 0; } const std::type_info& type() const { return typeid(T); } bool to_bool(const void* p) const { return converter_numeric::yes>().to_bool(p); } char to_char(const void* p) const { return converter_numeric::yes>().to_char(p); } unsigned char to_uchar(const void* p) const { return converter_numeric::yes>().to_uchar(p); } short to_short(const void* p) const { return converter_numeric::yes>().to_short(p); } unsigned short to_ushort(const void* p) const { return converter_numeric::yes>().to_ushort(p); } int to_int(const void* p) const { return converter_numeric::yes>().to_int(p); } unsigned int to_uint(const void* p) const { return converter_numeric::yes>().to_uint(p); } long to_long(const void* p) const { return converter_numeric::yes>().to_long(p); } unsigned long to_ulong(const void* p) const { return converter_numeric::yes>().to_ulong(p); } long long to_long_long(const void* p) const { return converter_numeric::yes>().to_long_long(p); } float to_float(const void* p) const { return converter_numeric::yes>().to_float(p); } double to_double(const void* p) const { return converter_numeric::yes>().to_double(p); } std::string to_string(const void* p) const { return converter_string::yes>().to_string(p); } }; union union_data { void* _pointer; size_t _data[1]; char _bool[sizeof(bool)]; char _char[sizeof(char)]; char _short[sizeof(short)]; char _int[sizeof(int)]; char _long[sizeof(long)]; char _long_long[sizeof(long long)]; char _float[sizeof(float)]; char _double[sizeof(double)]; char _string[sizeof(std::string)]; char _vector[sizeof(std::vector)]; char _deque[sizeof(std::deque)]; char _list[sizeof(std::list)]; char _set[sizeof(std::set)]; char _multiset[sizeof(std::multiset)]; }; }; //------------------------------------------------------------- #define VARIANT_INIT_VALUE(type, v) \ _null = false; \ _local = true; \ new (_union._data) type(v); \ _converter = new (_data_converter) detail::converter(); #define VARIANT_SET_VALUE(type, v) \ typedef detail::converter_base converter_base; \ if (!_null) { \ if (_local) _converter->destructor(_union._data); \ else _converter->destructor(&_union._pointer); \ _converter->~converter_base(); \ } \ else _null = false; \ _local = true; \ new (_union._data) type(v); \ _converter = new (_data_converter) detail::converter(); class variant { public: typedef std::vector vector; typedef std::list list; typedef std::deque deque; typedef std::set set; typedef std::multiset multiset; struct null {}; class const_iterator : public std::iterator { friend class variant; template friend struct detail::container; template friend struct detail::container_base; public: const_iterator() : _iter(0) {} const_iterator(const const_iterator& i) { _iter = i._iter->clone(_data_iterator); } const_iterator& operator =(const const_iterator& i) { typedef detail::iterator_base T; if (_iter != i._iter) { if (_iter) _iter->~T(); _iter = i._iter->clone(_data_iterator); } return *this; } ~const_iterator() { typedef detail::iterator_base T; if (_iter) _iter->~T(); } bool operator ==(const const_iterator& i) const { return *_iter == *i._iter; } bool operator !=(const const_iterator& i) const { return *_iter != *i._iter; } const_iterator& operator ++() { ++(*_iter); return *this; } const_iterator operator ++(int) { const_iterator i; (*_iter)++; return i; } const_iterator& operator --() { --(*_iter); return *this; } const_iterator operator --(int) { const_iterator i; (*_iter)--; return i; } const variant& operator *() const { return _iter->operator *(); } const variant* operator ->() const { return _iter->operator ->(); } protected: detail::iterator_base* _iter; union { char _data_iterator[1]; char _vector_iterator[sizeof(detail::iterator_tmp::iterator>)]; char _list_iterator[sizeof(detail::iterator_tmp::iterator>)]; char _deque_iterator[sizeof(detail::iterator_tmp::iterator>)]; char _set_iterator[sizeof(detail::iterator_tmp::iterator>)]; char _multoset_iterator[sizeof(detail::iterator_tmp::iterator>)]; }; private: template typename T::iterator _stl_iterator(T*) const { return reinterpret_cast*>(_data_iterator)->_iterator; } }; class iterator : public const_iterator { friend class variant; public: iterator() : const_iterator() {} iterator(const iterator& i) : const_iterator(i) {} iterator& operator =(const iterator& i) { const_iterator::operator =(i); return *this; } ~iterator() {} bool operator ==(const iterator& i) const { return *_iter == *i._iter; } bool operator !=(const iterator& i) const { return *_iter != *i._iter; } iterator& operator ++() { ++(*_iter); return *this; } iterator operator ++(int) { iterator i; (*_iter)++; return i; } iterator& operator --() { --(*_iter); return *this; } iterator operator --(int) { iterator i; (*_iter)--; return i; } variant& operator *() { return _iter->operator *(); } variant* operator ->() { return _iter->operator ->(); } }; variant() : _null(true) {} variant(null) : _null(true) {} variant(const variant& v) { if (!v._null) { _null = false; _local = v._local; _converter = v._converter->clone(_data_converter); if (_local) _converter->constructor(_union._data, v.get_data()); else _converter->constructor(&_union._pointer, v.get_data()); } else _null = true; } template explicit variant(const T& v) { _init(v); } ~variant() { if (!_null) { if (_local) _converter->destructor(_union._data); else _converter->destructor(&_union._pointer); _converter->~converter_base(); } } private: template void _init(const T& v) { _null = false; if (sizeof(T) <= sizeof(detail::union_data)) { _local = true; new (_union._data) T(v); } else { _local = false; _union._pointer = new T(v); } _converter = new (_data_converter) detail::converter(); } template void _init(T* v) { VARIANT_INIT_VALUE(T*, v); } void _init(bool v) { VARIANT_INIT_VALUE(bool, v); } void _init(char v) { VARIANT_INIT_VALUE(char, v); } void _init(unsigned char v) { VARIANT_INIT_VALUE(unsigned char, v); } void _init(short v) { VARIANT_INIT_VALUE(short, v); } void _init(unsigned short v) { VARIANT_INIT_VALUE(unsigned short, v); } void _init(int v) { VARIANT_INIT_VALUE(int, v); } void _init(unsigned int v) { VARIANT_INIT_VALUE(unsigned int, v); } void _init(long v) { VARIANT_INIT_VALUE(long, v); } void _init(unsigned long v) { VARIANT_INIT_VALUE(unsigned long, v); } void _init(long long v) { VARIANT_INIT_VALUE(long long, v); } void _init(float v) { VARIANT_INIT_VALUE(float, v); } void _init(double v) { VARIANT_INIT_VALUE(double, v); } void _init(const char* v) { VARIANT_INIT_VALUE(std::string, v); } void _init(const std::string& v) { VARIANT_INIT_VALUE(std::string, v); } template void _init(const std::vector& v) { typedef std::vector type; VARIANT_INIT_VALUE(type, v); } template void _init(const std::deque& v) { typedef std::deque type; VARIANT_INIT_VALUE(type, v); } template void _init(const std::list& v) { typedef std::list type; VARIANT_INIT_VALUE(type, v); } template void _init(const std::set& v) { typedef std::set type; VARIANT_INIT_VALUE(type, v); } template void _init(const std::multiset& v) { typedef std::multiset type; VARIANT_INIT_VALUE(type, v); } //------------------------------------------------------------- public: variant& operator =(null) { if (!_null) { if (_local) _converter->destructor(_union._data); else _converter->destructor(&_union._pointer); _converter->~converter_base(); _null = true; } return *this; } variant& operator =(const variant& v) { _set_value(v); return *this; } template variant& operator =(const T& v) { return _copy(v); } private: template variant& _copy(const T& v) { typedef detail::converter_base converter_base; if (!_null) { if (_local) _converter->destructor(_union._data); else _converter->destructor(&_union._pointer); _converter->~converter_base(); } else _null = false; if (sizeof(T) <= sizeof(detail::union_data)) { _local = true; new (_union._data) T(v); } else { _local = false; _union._pointer = new T(v); } _converter = new (_data_converter) detail::converter(); return *this; } template variant& _copy(T* v) { _set_value(v); return *this; } variant& _copy(bool v) { _set_value(v); return *this; } variant& _copy(char v) { _set_value(v); return *this; } variant& _copy(unsigned char v) { _set_value(v); return *this; } variant& _copy(short v) { _set_value(v); return *this; } variant& _copy(unsigned short v) { _set_value(v); return *this; } variant& _copy(int v) { _set_value(v); return *this; } variant& _copy(unsigned int v) { _set_value(v); return *this; } variant& _copy(long v) { _set_value(v); return *this; } variant& _copy(unsigned long v) { _set_value(v); return *this; } variant& _copy(long long v) { _set_value(v); return *this; } variant& _copy(float v) { _set_value(v); return *this; } variant& _copy(double v) { _set_value(v); return *this; } variant& _copy(const char* v) { _set_value(v); return *this; } variant& _copy(const std::string& v) { _set_value(v); return *this; } template variant& _copy(const std::vector& v) { _set_value(v); return *this; } template variant& _copy(const std::deque& v) { _set_value(v); return *this; } template variant& _copy(const std::list& v) { _set_value(v); return *this; } template variant& _copy(const std::set& v) { _set_value(v); return *this; } template variant& _copy(const std::multiset& v) { _set_value(v); return *this; } //------------------------------------------------------------- private: void _set_value(const variant& v) { if (_null || (get_data() != v.get_data())) { if (!_null) { if (_local) _converter->destructor(_union._data); else _converter->destructor(&_union._pointer); _converter->~converter_base(); } _null = v._null; if (!v._null) { _converter = v._converter->clone(_data_converter); _local = v._local; if (_local) _converter->constructor(_union._data, v.get_data()); else _converter->constructor(_union._pointer, v.get_data()); } } } template void _set_value(T* v) { VARIANT_SET_VALUE(T*, v); } void _set_value(bool v) { VARIANT_SET_VALUE(bool, v); } void _set_value(char v) { VARIANT_SET_VALUE(char, v); } void _set_value(unsigned char v) { VARIANT_SET_VALUE(unsigned char, v); } void _set_value(short v) { VARIANT_SET_VALUE(short, v); } void _set_value(unsigned short v) { VARIANT_SET_VALUE(unsigned short, v); } void _set_value(int v) { VARIANT_SET_VALUE(int, v); } void _set_value(unsigned int v) { VARIANT_SET_VALUE(unsigned int, v); } void _set_value(long v) { VARIANT_SET_VALUE(long, v); } void _set_value(unsigned long v) { VARIANT_SET_VALUE(unsigned long, v); } void _set_value(long long v) { VARIANT_SET_VALUE(long long, v); } void _set_value(float v) { VARIANT_SET_VALUE(float, v); } void _set_value(double v) { VARIANT_SET_VALUE(double, v); } void _set_value(const char* v) { VARIANT_SET_VALUE(std::string, v); } void _set_value(const std::string& v) { VARIANT_SET_VALUE(std::string, v); } template void _set_value(const std::vector& v) { typedef std::vector type; VARIANT_SET_VALUE(type, v); } template void _set_value(const std::deque& v) { typedef std::deque type; VARIANT_SET_VALUE(type, v); } template void _set_value(const std::list& v) { typedef std::list type; VARIANT_SET_VALUE(type, v); } template void _set_value(const std::set& v) { typedef std::set type; VARIANT_SET_VALUE(type, v); } template void _set_value(const std::multiset& v) { typedef std::multiset type; VARIANT_SET_VALUE(type, v); } //------------------------------------------------------------- public: bool is_null() const { return _null; } bool is_character() const { return _converter->is_character(); } bool is_numeric() const { return _converter->is_numeric(); } bool is_real() const { return _converter->is_real(); } bool is_string() const { return _converter->is_string(); } bool is_pointer() const { return _converter->is_pointer(); } bool is_container() const { return _converter->is_container(); } bool to_bool() const { return _converter->to_bool(get_data()); } char to_char() const { return _converter->to_char(get_data()); } unsigned char to_uchar() const { return _converter->to_uchar(get_data()); } short to_short() const { return _converter->to_short(get_data()); } unsigned short to_ushort() const { return _converter->to_ushort(get_data()); } int to_int() const { return _converter->to_int(get_data()); } unsigned int to_uint() const { return _converter->to_uint(get_data()); } long to_long() const { return _converter->to_long(get_data()); } unsigned long to_ulong() const { return _converter->to_ulong(get_data()); } long long to_long_long() const { return _converter->to_long_long(get_data()); } float to_float() const { return _converter->to_float(get_data()); } double to_double() const { return _converter->to_double(get_data()); } std::string to_string() const { return _converter->to_string(get_data()); } std::vector to_vector() const { _if_container(); variant v; v = std::vector(); v.insert(*this); return *reinterpret_cast*>(v.get_data()); } std::list to_list() const { _if_container(); variant v; v = std::list(); v.insert(*this); return *reinterpret_cast*>(v.get_data()); } std::deque to_deque() const { _if_container(); variant v; v = std::deque(); v.insert(*this); return *reinterpret_cast*>(v.get_data()); } std::set to_set() const { _if_container(); variant v; v = std::set(); v.insert(*this); return *reinterpret_cast*>(v.get_data()); } std::multiset to_multiset() const { _if_container(); variant v; v = std::multiset(); v.insert(*this); return *reinterpret_cast*>(v.get_data()); } //------------------------------------------------------------- bool operator ==(null) const { return is_null(); } bool operator !=(null) const { return !is_null(); } bool operator ==(const variant& v) const { if (!_null && !v._null) { int id1 = specjalization_id(), id2 = v.specjalization_id(); switch(std::max(id1, id2)) { case 0: case 1: return to_long_long() == v.to_long_long(); case 2: return to_double() == v.to_double(); case 3: return to_string() == v.to_string(); } return (id1 + id2) == 10 ? (*reinterpret_cast(get_data()) == *reinterpret_cast(v.get_data())) : (id1 == 4) && (id2 == 4) ? size() == v.size() :id1 == id2; } else return false; } bool operator !=(const variant& v) const { return !(*this == v); } bool operator <=(const variant& v) const { if (!_null && !v._null) { int id1 = specjalization_id(), id2 = v.specjalization_id(); switch(std::max(id1, id2)) { case 0: case 1: return to_long_long() <= v.to_long_long(); case 2: return to_double() <= v.to_double(); case 3: return to_string() <= v.to_string(); } return (id1 + id2) == 10 ? (*reinterpret_cast(get_data()) <= *reinterpret_cast(v.get_data())) : (id1 == 4) && (id2 == 4) ? size() <= v.size() :id1 <= id2; } else return false; } bool operator >(const variant& v) const { return !(*this <= v); } bool operator >=(const variant& v) const { if (!_null && !v._null) { int id1 = specjalization_id(), id2 = v.specjalization_id(); switch(std::max(id1, id2)) { case 0: case 1: return to_long_long() >= v.to_long_long(); case 2: return to_double() >= v.to_double(); case 3: return to_string() >= v.to_string(); } return (id1 + id2) == 10 ? (*reinterpret_cast(get_data()) >= *reinterpret_cast(v.get_data())) : (id1 == 4) && (id2 == 4) ? size() >= v.size() :id1 >= id2; } else return false; } bool operator <(const variant& v) const { return !(*this >= v); } operator bool () const { return to_bool(); } operator char () const { return to_char(); } operator unsigned char () const { return to_uchar(); } operator short () const { return to_short(); } operator unsigned short() const { return to_ushort(); } operator int () const { return to_int(); } operator unsigned int () const { return to_uint(); } operator long () const { return to_long(); } operator unsigned long () const { return to_ulong(); } operator long long () const { return to_long_long(); } operator float () const { return to_float(); } operator double () const { return to_double(); } operator std::string () const { return to_string(); } template variant(const std::vector& v) { typedef std::vector type; VARIANT_INIT_VALUE(type, v); } template variant(const std::deque& v) { typedef std::deque type; VARIANT_INIT_VALUE(type, v); } template variant(const std::list& v) { typedef std::list type; VARIANT_INIT_VALUE(type, v); } template variant(const std::set& v) { typedef std::set type; VARIANT_INIT_VALUE(type, v); } template variant(const std::multiset& v) { typedef std::multiset type; VARIANT_INIT_VALUE(type, v); } //------------------------------------------------------------- template T& cast() { if (!can_cast()) throw variant_exception(); return *reinterpret_cast(_get_data()); } template const T& cast() const { if (!can_cast()) throw variant_exception(); return *reinterpret_cast(get_data()); } template bool can_cast() const { return typeid(T) == _converter->type(); } const std::type_info& type() const { return _converter->type(); } const void* get_data() const { return _local ? _union._data : _union._pointer; } int specjalization_id() const { return _converter->specjalization_id(); } private: void _if_container() const { if (!is_container()) throw variant_exception(); }; bool _local; bool _null; detail::union_data _union; detail::converter_base* _converter; char _data_converter[sizeof(detail::converter)]; //------------------------------------------------------------- public: void* _get_data() { return _local ? _union._data : _union._pointer; } variant& back() { return _converter->back(_get_data()); } const variant& back() const { return _converter->back(get_data()); } iterator begin() { iterator i; i._iter = _converter->begin(_get_data(), i._data_iterator); return i; } const_iterator begin() const { const_iterator i; i._iter = const_cast*>(_converter->begin(get_data(), i._data_iterator)); return i; } iterator end() { iterator i; i._iter = _converter->end(_get_data(), i._data_iterator); return i; } const_iterator end() const { const_iterator i; i._iter = const_cast*>(_converter->end(get_data(), i._data_iterator)); return i; } void clear() { return _converter->clear(_get_data()); } bool empty() const { return _converter->empty(get_data()); } template void erase(const T& value) { _converter->erase(_get_data(), variant(value)); } void erase(const_iterator where) { _converter->erase(_get_data(), where); } void erase(const_iterator first, const_iterator last) { _converter->erase(_get_data(), first, last); } template iterator find(const T& value) { iterator i; i._iter = _converter->find(_get_data(), variant(value), i._data_iterator); return i; } template const_iterator find(const T& value) const { const_iterator i; i._iter = const_cast*>(_converter->find(get_data(), variant(value), i._data_iterator)); return i; } variant& front() { return _converter->front(_get_data()); } const variant& front() const { return _converter->front(get_data()); } template void insert(const T& value) { _converter->insert(_get_data(), variant(value)); } template void insert(const_iterator where, const T& value) { _converter->insert(_get_data(), where, variant(value)); } void insert(const_iterator where, const_iterator first, const_iterator last) { _converter->insert(_get_data(), where, first, last); } void insert(const_iterator first, const_iterator last) { _converter->insert(_get_data(), first, last); } size_t max_size() const { return _converter->max_size(get_data()); } void pop_back() { _converter->pop_back(_get_data()); } void pop_front() { _converter->pop_front(_get_data()); } template void push_back(const T& value) { _converter->push_back(_get_data(), variant(value)); } template void push_front(const T& value) { _converter->push_front(_get_data(), variant(value)); } iterator rbegin() { iterator i; i._iter = _converter->rbegin(_get_data(), i._data_iterator); return i; } const_iterator rbegin() const { const_iterator i; i._iter = const_cast*>(_converter->rbegin(get_data(), i._data_iterator)); return i; } iterator rend() { iterator i; i._iter = _converter->rend(_get_data(), i._data_iterator); return i; } const_iterator rend() const { const_iterator i; i._iter = const_cast*>(_converter->rend(get_data(), i._data_iterator)); return i; } template void remove(const T& value) { erase(find(value)); } size_t size() const { return _converter->size(get_data()); } void sort() { sort_asc(); } void sort_asc() { _converter->sort_asc(_get_data(), _converter, _data_converter); } void sort_desc() { _converter->sort_desc(_get_data(), _converter, _data_converter); } }; template std::ostream& operator << (std::basic_ostream& os, const variant& v) { os << v.to_string(); return os; } template std::istream& operator >> (std::basic_istream& is, variant& v) { std::string s; is >> s; v = s; return is; } //------------------------------------------------------------- template bool operator ==(const variant& l, T r) { if (!l.is_null()) { switch(l.specjalization_id()) { case 0: case 1: return l.to_long_long() == r; case 2: return l.to_double() == r; case 3: return l.to_string() == static_cast(std::stringstream() << r).str(); case 5: return *reinterpret_cast(l.get_data()) == r; } } return false; } template bool operator ==(const variant& l, T* r) { return !l.is_null() && l.is_pointer() ? (reinterpret_cast(*reinterpret_cast(l.get_data())) == r) : false; } bool operator ==(const variant& l, const std::string& r) { return !l.is_null() ? l.to_string() == r : false; } bool operator ==(const variant& l, char r) { return !l.is_null() ? l.to_string() == (std::string() + r) : false; } template bool operator ==(T l, const variant& r) { if (!r.is_null()) { switch(r.specjalization_id()) { case 0: case 1: return l == r.to_long_long(); case 2: return l == r.to_double(); case 3: return static_cast(std::stringstream() << l).str() == r.to_string(); case 5: return l == *reinterpret_cast(r.get_data()); } } return false; } template bool operator ==(T* l, const variant& r) { return !r.is_null() && r.is_pointer() ? (l == reinterpret_cast(*reinterpret_cast(r.get_data()))) : false; } bool operator ==(char l, const variant& r) { return !r.is_null() ? (std::string() + l) == r.to_string() : false; } bool operator ==(const std::string& l, const variant& r) { return !r.is_null() ? l == r.to_string() : false; } //------------------------------------------------------------- template bool operator !=(const variant& l, T r) { return !(l == r); } template bool operator !=(const variant& l, T* r) { return !(l == r); } bool operator !=(const variant& l, char r) { return !(l == r); } bool operator !=(const variant& l, const std::string& r) { return !(l == r); } template bool operator !=(T l, const variant& r) { return !(l == r); } template bool operator !=(T* l, const variant& r) { return !(l == r); } bool operator !=(char l, const variant& r) { return !(l == r); } bool operator !=(const std::string& l, const variant& r) { return !(l == r); } //------------------------------------------------------------- template bool operator <=(const variant& l, T r) { if (!l.is_null()) { switch(l.specjalization_id()) { case 0: case 1: return l.to_long_long() <= r; case 2: return l.to_double() <= r; case 3: return l.to_string() <= static_cast(std::stringstream() << r).str(); case 5: return *reinterpret_cast(l.get_data()) <= r; } } return false; } template bool operator <=(const variant& l, T* r) { return !l.is_null() && l.is_pointer() ? (reinterpret_cast(*reinterpret_cast(l.get_data())) <= r) : false; } bool operator <=(const variant& l, const std::string& r) { return !l.is_null() ? l.to_string() <= r : false; } bool operator <=(const variant& l, char r) { return !l.is_null() ? l.to_string() <= (std::string() + r) : false; } template bool operator <=(T l, const variant& r) { if (!r.is_null()) { switch(r.specjalization_id()) { case 0: case 1: return l <= r.to_long_long(); case 2: return l <= r.to_double(); case 3: return static_cast(std::stringstream() << l).str() <= r.to_string(); case 5: return l <= *reinterpret_cast(r.get_data()); } } return true; } template bool operator <=(T* l, const variant& r) { return !r.is_null() && r.is_pointer() ? (l <= reinterpret_cast(*reinterpret_cast(r.get_data()))) : true; } bool operator <=(char l, const variant& r) { return !r.is_null() ? (std::string() + l) <= r.to_string() : true; } bool operator <=(const std::string& l, const variant& r) { return !r.is_null() ? l <= r.to_string() : true; } //------------------------------------------------------------- template bool operator >(const variant& l, T r) { return !(l <= r); } template bool operator >(const variant& l, T* r) { return !(l <= r); } bool operator >(const variant& l, char r) { return !(l <= r); } bool operator >(const variant& l, const std::string& r) { return !(l <= r); } template bool operator >(T l, const variant& r) { return !(l <= r); } template bool operator >(T* l, const variant& r) { return !(l <= r); } bool operator >(char l, const variant& r) { return !(l <= r); } bool operator >(const std::string& l, const variant& r) { return !(l <= r); } //------------------------------------------------------------- template bool operator >=(const variant& l, T r) { if (!l.is_null()) { switch(l.specjalization_id()) { case 0: case 1: return l.to_long_long() >= r; case 2: return l.to_double() >= r; case 3: return l.to_string() >= static_cast(std::stringstream() << r).str(); case 5: return *reinterpret_cast(l.get_data()) >= r; } } return true; } template bool operator >=(const variant& l, T* r) { return !l.is_null() && l.is_pointer() ? (reinterpret_cast(*reinterpret_cast(l.get_data())) >= r) : true; } bool operator >=(const variant& l, const std::string& r) { return !l.is_null() ? l.to_string() >= r : true; } bool operator >=(const variant& l, char r) { return !l.is_null() ? l.to_string() >= (std::string() + r) : true; } template bool operator >=(T l, const variant& r) { if (!r.is_null()) { switch(r.specjalization_id()) { case 0: case 1: return l >= r.to_long_long(); case 2: return l >= r.to_double(); case 3: return static_cast(std::stringstream() << l).str() >= r.to_string(); case 5: return l >= *reinterpret_cast(r.get_data()); } } return false; } template bool operator >=(T* l, const variant& r) { return !r.is_null() && r.is_pointer() ? (l >= reinterpret_cast(*reinterpret_cast(r.get_data()))) : false; } bool operator >=(char l, const variant& r) { return !r.is_null() ? (std::string() + l) >= r.to_string() : false; } bool operator >=(const std::string& l, const variant& r) { return !r.is_null() ? l >= r.to_string() : false; } //------------------------------------------------------------- template bool operator <(const variant& l, T r) { return !(l >= r); } template bool operator <(const variant& l, T* r) { return !(l >= r); } bool operator <(const variant& l, char r) { return !(l >= r); } bool operator <(const variant& l, const std::string& r) { return !(l >= r); } template bool operator <(T l, const variant& r) { return !(l >= r); } template bool operator <(T* l, const variant& r) { return !(l >= r); } bool operator <(char l, const variant& r) { return !(l >= r); } bool operator <(const std::string& l, const variant& r) { return !(l >= r); } #endif // #ifndef VARIANT_HPP_INCLUDED