From cba6f2ee89389f707ce1a49cf5a31a732c27d0a6 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Sat, 1 Mar 2014 08:12:53 +0100
Subject: [PATCH] working variant type

---
 alib/src/std/type_traits.hpp | 28 +++++++++++++++++++++++
 alib/src/std/variant.hpp     | 43 ++++++++++++++++++++++++++----------
 2 files changed, 59 insertions(+), 12 deletions(-)
 create mode 100644 alib/src/std/type_traits.hpp

diff --git a/alib/src/std/type_traits.hpp b/alib/src/std/type_traits.hpp
new file mode 100644
index 0000000000..1ee68e2268
--- /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 1e091c6e0c..0ea1d040d6 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
-- 
GitLab