diff --git a/alib/src/std/type_traits.hpp b/alib/src/std/type_traits.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1ee68e2268877a8cfcc1fe23624cfc840211dca7 --- /dev/null +++ b/alib/src/std/type_traits.hpp @@ -0,0 +1,28 @@ +#ifndef TYPE_TRAITS_HPP_ +#define TYPE_TRAITS_HPP_ + +#include <type_traits> + +namespace std { + template <typename T> + struct is_base_of<T, T> { + static const bool value = true; + }; + + template <typename T, typename... Ts> + struct is_base_of_any; + + template <typename T, typename F> + struct is_base_of_any<T, F> + { + static const bool value = is_base_of<T, F>::value; + }; + + template <typename T, typename F, typename... Ts> + struct is_base_of_any<T, F, Ts...> + { + static const bool value = is_base_of<T, F>::value || is_base_of_any<T, Ts...>::value; + }; +} + +#endif diff --git a/alib/src/std/variant.hpp b/alib/src/std/variant.hpp index 1e091c6e0ced0d6f4ad544191580afde2871b02c..0ea1d040d6bf91dae83a4a0a7b7eaf45ac65ecc7 100644 --- a/alib/src/std/variant.hpp +++ b/alib/src/std/variant.hpp @@ -5,10 +5,13 @@ * Modified: Jan Travnicek */ +#ifndef VATIANT_HPP_ +#define VATIANT_HPP_ + #include <iostream> #include <utility> #include <typeinfo> -#include <type_traits> +#include "type_traits.hpp" #include <string> template <size_t arg1, size_t ... others> @@ -42,10 +45,11 @@ struct variant_helper<F, Ts...> { inline static void move(size_t old_t, void * old_v, void * new_v) { - if (old_t == typeid(F).hash_code()) + if (old_t == typeid(F).hash_code()) { new (new_v) F(std::move(*reinterpret_cast<F*>(old_v))); - else - variant_helper<Ts...>::move(old_t, old_v, new_v); + return true; + } else + return variant_helper<Ts...>::move(old_t, old_v, new_v); } inline static void copy(size_t old_t, const void * old_v, void * new_v) @@ -79,7 +83,7 @@ struct variant_helper<F, Ts...> { template<> struct variant_helper<> { inline static void destroy(size_t id, void * data) { } -inline static void move(size_t old_t, void * old_v, void * new_v) { } +inline static bool move(size_t old_t, void * old_v, void * new_v) { return false; } inline static void copy(size_t old_t, const void * old_v, void * new_v) { } inline static bool compareEq(size_t this_t, const void * this_v, size_t other_t, const void * other_v) { return true; } inline static bool compareLess(size_t this_t, const void * this_v, size_t other_t, const void * other_v) { return false; } @@ -147,15 +151,28 @@ public: return (type_id == typeid(T).hash_code()); } - template<typename T, typename... Args> - void set(Args&&... args) + template<typename T> + void set(T&& value) { - // First we destroy the current contents - helper_t::destroy(type_id, &data); - new (&data) T(std::forward<Args>(args)...); - type_id = typeid(T).hash_code(); + if(std::is_base_of_any<T, F, Ts...>::value) { + helper_t::destroy(type_id, &data); + new (&data) T(value); + type_id = typeid(T).hash_code(); + } else + throw std::bad_cast(); } - + + template<typename T> + void set(T& value) + { + if(std::is_base_of_any<T, F, Ts...>::value) { + helper_t::destroy(type_id, &data); + new (&data) T(value); + type_id = typeid(T).hash_code(); + } else + throw std::bad_cast(); + } + template<typename T> T& get() { @@ -170,3 +187,5 @@ public: helper_t::destroy(type_id, &data); } }; + +#endif