diff --git a/alib2std/src/extensions/variant.hpp b/alib2std/src/extensions/variant.hpp index 3537bb6ce564184479023b1449df9a182d67eccc..d1be55e08e36af11af40d2aeec1c62db5c23a993 100644 --- a/alib2std/src/extensions/variant.hpp +++ b/alib2std/src/extensions/variant.hpp @@ -37,6 +37,7 @@ #include "compare.hpp" #include "utility.hpp" #include "type_traits.hpp" +#include "typeindex.h" namespace ext { @@ -54,80 +55,48 @@ struct static_max<arg1, arg2, others...> { static_max<arg2, others...>::value; }; -struct type_id_hash_code { - size_t m_hash_code; - - type_id_hash_code ( size_t hash_code ) : m_hash_code ( hash_code ) { - } - - friend inline bool operator == ( const type_id_hash_code & first, const type_id_hash_code & second ) { - return first.m_hash_code == second.m_hash_code; - } - - friend inline bool operator != ( const type_id_hash_code & first, const type_id_hash_code & second ) { - return first.m_hash_code != second.m_hash_code; - } - - friend inline bool operator < ( const type_id_hash_code & first, const type_id_hash_code & second ) { - return first.m_hash_code < second.m_hash_code; - } - - friend inline bool operator <= ( const type_id_hash_code & first, const type_id_hash_code & second ) { - return first.m_hash_code <= second.m_hash_code; - } - - friend inline bool operator > ( const type_id_hash_code & first, const type_id_hash_code & second ) { - return first.m_hash_code > second.m_hash_code; - } - - friend inline bool operator >= ( const type_id_hash_code & first, const type_id_hash_code & second ) { - return first.m_hash_code >= second.m_hash_code; - } - -}; - template<typename... Ts> struct variant_helper; template<typename F, typename... Ts> struct variant_helper<F, Ts...> { - inline static void destroy(type_id_hash_code id, void * data) { - if (id == typeid(F).hash_code()) + inline static void destroy(ext::type_index id, void * data) { + if (id == ext::type_index ( ext::type_index ( typeid ( F ) ) ) ) reinterpret_cast<F*>(data)->~F(); else variant_helper<Ts...>::destroy(id, data); } - inline static void copy(type_id_hash_code old_t, const void * old_v, void * new_v) { - if (old_t == typeid(F).hash_code()) + inline static void copy(ext::type_index old_t, const void * old_v, void * new_v) { + if (old_t == ext::type_index ( typeid ( F ) )) new (new_v) F(*reinterpret_cast<const F*>(old_v)); else variant_helper<Ts...>::copy(old_t, old_v, new_v); } - inline static void move(type_id_hash_code old_t, void * old_v, void * new_v) { - if (old_t == typeid(F).hash_code()) + inline static void move(ext::type_index old_t, void * old_v, void * new_v) { + if (old_t == ext::type_index ( typeid ( F ) )) new (new_v) F(std::move(*reinterpret_cast<F*>(old_v))); else variant_helper<Ts...>::move(old_t, old_v, new_v); } - inline static void print(std::ostream& out, type_id_hash_code id, const void* data) { - if (id == typeid(F).hash_code()) + inline static void print(std::ostream& out, ext::type_index id, const void* data) { + if (id == ext::type_index ( typeid ( F ) )) out << *reinterpret_cast<const F*>(data); else variant_helper<Ts...>::print(out, id, data); } - inline static std::string string(type_id_hash_code id, const void* data) { - if (id == typeid(F).hash_code()) + inline static std::string string(ext::type_index id, const void* data) { + if (id == ext::type_index ( typeid ( F ) )) return ext::to_string ( *reinterpret_cast<const F*>(data) ); else return variant_helper<Ts...>::string(id, data); } - inline static int compareHelper(type_id_hash_code this_t, const void * this_v, type_id_hash_code other_t, const void * other_v) { - if (this_t == typeid(F).hash_code() && other_t == typeid(F).hash_code()) { + inline static int compareHelper(ext::type_index this_t, const void * this_v, ext::type_index other_t, const void * other_v) { + if (this_t == ext::type_index ( typeid ( F ) ) && other_t == ext::type_index ( typeid ( F ) )) { static ext::compare<typename std::decay < F >::type > comp; return comp( *(reinterpret_cast<const F*>(this_v)), *(reinterpret_cast<const F*>(other_v))); } else @@ -137,37 +106,37 @@ struct variant_helper<F, Ts...> { template<typename... Ts> struct variant_helper<void, Ts...> { - inline static void destroy(type_id_hash_code id, void * data) { - if (id != typeid(void).hash_code()) + inline static void destroy(ext::type_index id, void * data) { + if (id != ext::type_index ( typeid ( void ) )) variant_helper<Ts...>::destroy(id, data); } - inline static void copy(type_id_hash_code old_t, const void * old_v, void * new_v) { - if (old_t != typeid(void).hash_code()) + inline static void copy(ext::type_index old_t, const void * old_v, void * new_v) { + if (old_t != ext::type_index ( typeid ( void ) )) variant_helper<Ts...>::copy(old_t, old_v, new_v); } - inline static void move(type_id_hash_code old_t, void * old_v, void * new_v) { - if (old_t != typeid(void).hash_code()) + inline static void move(ext::type_index old_t, void * old_v, void * new_v) { + if (old_t != ext::type_index ( typeid ( void ) )) variant_helper<Ts...>::move(old_t, old_v, new_v); } - inline static void print(std::ostream& out, type_id_hash_code id, const void* data) { - if (id == typeid(void).hash_code()) + inline static void print(std::ostream& out, ext::type_index id, const void* data) { + if (id == ext::type_index ( typeid ( void ) )) out << "void"; else variant_helper<Ts...>::print(out, id, data); } - inline static std::string string(type_id_hash_code id, const void* data) { - if (id == typeid(void).hash_code()) + inline static std::string string(ext::type_index id, const void* data) { + if (id == ext::type_index ( typeid ( void ) )) return "void"; else return variant_helper<Ts...>::string(id, data); } - inline static int compareHelper(type_id_hash_code this_t, const void * this_v, type_id_hash_code other_t, const void * other_v) { - if (this_t == typeid(void).hash_code() && other_t == typeid(void).hash_code()) + inline static int compareHelper(ext::type_index this_t, const void * this_v, ext::type_index other_t, const void * other_v) { + if (this_t == ext::type_index ( typeid ( void ) ) && other_t == ext::type_index ( typeid ( void ) )) return 0; else return variant_helper<Ts...>::compareHelper(this_t, this_v, other_t, other_v); @@ -175,12 +144,12 @@ struct variant_helper<void, Ts...> { }; template<> struct variant_helper<> { -inline static void destroy(type_id_hash_code, void *) { } -inline static void copy(type_id_hash_code, const void *, void *) { } -inline static void move(type_id_hash_code, void *, void *) { } -inline static void print(std::ostream&, type_id_hash_code, const void *) {} -inline static std::string string(type_id_hash_code, const void *) { return ""; } -inline static int compareHelper(type_id_hash_code, const void *, type_id_hash_code, const void *) { return 0; } +inline static void destroy(ext::type_index, void *) { } +inline static void copy(ext::type_index, const void *, void *) { } +inline static void move(ext::type_index, void *, void *) { } +inline static void print(std::ostream&, ext::type_index, const void *) {} +inline static std::string string(ext::type_index, const void *) { return ""; } +inline static int compareHelper(ext::type_index, const void *, ext::type_index, const void *) { return 0; } }; template<typename ST, typename AT, typename... Ts> @@ -194,10 +163,10 @@ class variant_base<ST, AT> { using data_t = typename std::aligned_storage<data_size, data_align>::type; protected: - type_id_hash_code type_id; + ext::type_index type_id; data_t data; - variant_base( type_id_hash_code id ) : type_id ( id ) { + variant_base( ext::type_index id ) : type_id ( id ) { // just to make the -Werror=maybe-uninitialized go away std::memset( & data, 0, data_size ); } @@ -208,11 +177,11 @@ class variant_base<ST, AT, F, Ts...> : public variant_base<ST, AT, Ts...> { using variant_base<ST, AT, Ts...>::variant_base; protected: - variant_base( type_id_hash_code id ) : variant_base<ST, AT, Ts...>::variant_base ( id ) { } + variant_base( ext::type_index id ) : variant_base<ST, AT, Ts...>::variant_base ( id ) { } public: - variant_base(const F& value) : variant_base<ST, AT, Ts...>::variant_base ( type_id_hash_code ( typeid(F).hash_code() ) ) { new (&this->data) F(value); } - variant_base(F&& value) : variant_base<ST, AT, Ts...>::variant_base ( type_id_hash_code ( typeid(F).hash_code() ) ) { new (&this->data) F(std::move(value)); } + variant_base(const F& value) : variant_base<ST, AT, Ts...>::variant_base ( ext::type_index ( typeid(F) ) ) { new (&this->data) F(value); } + variant_base(F&& value) : variant_base<ST, AT, Ts...>::variant_base ( ext::type_index ( typeid(F) ) ) { new (&this->data) F(std::move(value)); } variant_base() : variant_base<ST, AT, Ts ... >::variant_base ( ) { } }; @@ -222,10 +191,10 @@ class variant_base<ST, AT, void, Ts...> : public variant_base<ST, AT, Ts...> { using variant_base<ST, AT, Ts...>::variant_base; protected: - variant_base( type_id_hash_code id ) : variant_base<ST, AT, Ts...>::variant_base ( id ) { } + variant_base( ext::type_index id ) : variant_base<ST, AT, Ts...>::variant_base ( id ) { } public: - variant_base() : variant_base<ST, AT, Ts...>::variant_base ( type_id_hash_code ( typeid(void).hash_code() ) ) { } + variant_base() : variant_base<ST, AT, Ts...>::variant_base ( ext::type_index ( typeid ( void ) ) ) { } }; template<typename ... Ts> @@ -296,33 +265,33 @@ public: template<typename T, typename std::enable_if < ext::is_in<T, Ts...>::value >::type* = nullptr > bool is() const { - return (this->type_id == typeid(T).hash_code()); + return (this->type_id == ext::type_index ( typeid ( T ) )); } template < typename T = void > typename std::enable_if < ext::is_in < T, Ts ... >::value, void >::type set ( ) { helper_t::destroy(this->type_id, &this->data); - this->type_id = typeid(void).hash_code(); + this->type_id = ext::type_index ( typeid ( void ) ); } template < typename T > void set ( typename std::enable_if < ext::is_in<T, Ts...>::value && ! std::is_same < void, T >::value, T >::type && value ) { helper_t::destroy(this->type_id, &this->data); new (&this->data) T(value); - this->type_id = typeid(T).hash_code(); + this->type_id = ext::type_index ( typeid ( T ) ); } template < typename T > void set ( const typename std::enable_if < ext::is_in<T, Ts...>::value && ! std::is_same < void, T >::value, T >::type & value ) { helper_t::destroy(this->type_id, &this->data); new (&this->data) T(std::move(value)); - this->type_id = typeid(T).hash_code(); + this->type_id = ext::type_index ( typeid ( T ) ); } template < typename T > typename std::enable_if < ext::is_in<T, Ts...>::value && ! std::is_same < void, T >::value, T >::type & get() { // It is a dynamic_cast-like behaviour - if (this->type_id == typeid(T).hash_code()) + if (this->type_id == ext::type_index ( typeid ( T ) )) return *reinterpret_cast<T*>(&this->data); else throw std::bad_cast(); @@ -331,7 +300,7 @@ public: template<typename T > const typename std::enable_if < ext::is_in<T, Ts...>::value && ! std::is_same < void, T >::value, T >::type& get() const { // It is a dynamic_cast-like behaviour - if (this->type_id == typeid(T).hash_code()) + if (this->type_id == ext::type_index ( typeid ( T ) )) return *reinterpret_cast<const T*>(&this->data); else throw std::bad_cast();