Skip to content
Snippets Groups Projects
Commit f5f6e997 authored by Jan Trávníček's avatar Jan Trávníček
Browse files

finishing variant

parent 2e01ec0f
No related branches found
No related tags found
No related merge requests found
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* https://gist.github.com/tibordp/6909880 * https://gist.github.com/tibordp/6909880
* Created on: Feb 28, 2014 * Created on: Feb 28, 2014
* Author: Tibor Djurica Potpara * Author: Tibor Djurica Potpara
* Modified: Jan Travnicek * Modified: Jan Travnicek
*/ */
   
#ifndef VATIANT_HPP_ #ifndef VATIANT_HPP_
...@@ -43,7 +43,7 @@ struct variant_helper<F, Ts...> { ...@@ -43,7 +43,7 @@ struct variant_helper<F, Ts...> {
variant_helper<Ts...>::destroy(id, data); variant_helper<Ts...>::destroy(id, 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)
{ {
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))); new (new_v) F(std::move(*reinterpret_cast<F*>(old_v)));
...@@ -72,7 +72,7 @@ struct variant_helper<F, Ts...> { ...@@ -72,7 +72,7 @@ struct variant_helper<F, Ts...> {
{ {
if (this_t == typeid(F).hash_code() && other_t != typeid(F).hash_code()) return true; if (this_t == typeid(F).hash_code() && other_t != typeid(F).hash_code()) return true;
if (this_t != typeid(F).hash_code() && other_t == typeid(F).hash_code()) return false; if (this_t != typeid(F).hash_code() && other_t == typeid(F).hash_code()) return false;
if (this_t == typeid(F).hash_code() && other_t == typeid(F).hash_code()) if (this_t == typeid(F).hash_code() && other_t == typeid(F).hash_code())
return *(reinterpret_cast<const F*>(this_v)) < *(reinterpret_cast<const F*>(other_v)); return *(reinterpret_cast<const F*>(this_v)) < *(reinterpret_cast<const F*>(other_v));
else else
...@@ -91,20 +91,20 @@ inline static bool compareLess(size_t this_t, const void * this_v, size_t other_ ...@@ -91,20 +91,20 @@ inline static bool compareLess(size_t this_t, const void * this_v, size_t other_
   
template<typename F, typename... Ts> template<typename F, typename... Ts>
struct variant { struct variant {
private: private:
static const size_t data_size = static_max<sizeof(F), sizeof(Ts)...>::value; static const size_t data_size = static_max<sizeof(F), sizeof(Ts)...>::value;
static const size_t data_align = static_max<alignof(F), alignof(Ts)...>::value; static const size_t data_align = static_max<alignof(F), alignof(Ts)...>::value;
using data_t = typename std::aligned_storage<data_size, data_align>::type; using data_t = typename std::aligned_storage<data_size, data_align>::type;
using helper_t = variant_helper<F, Ts...>; using helper_t = variant_helper<F, Ts...>;
size_t type_id; size_t type_id;
data_t data; data_t data;
public: public:
//default constructor //default constructor
variant() : type_id(typeid(F).hash_code()) { new (&data) F(); } variant() : type_id(typeid(F).hash_code()) { new (&data) F(); }
//copy consructor //copy consructor
variant(const variant<F, Ts...>& old) : type_id(old.type_id) variant(const variant<F, Ts...>& old) : type_id(old.type_id)
{ {
...@@ -115,23 +115,17 @@ public: ...@@ -115,23 +115,17 @@ public:
variant(variant<F, Ts...>&& old) : type_id(old.type_id) variant(variant<F, Ts...>&& old) : type_id(old.type_id)
{ {
helper_t::move(old.type_id, &old.data, &data); helper_t::move(old.type_id, &old.data, &data);
new (&old.data) F();
old.type_id = typeid(F).hash_code();
} }
//assignment operator //assignment operator
variant<F, Ts...>& operator= (variant<F, Ts...> old) variant<F, Ts...>& operator= (variant<F, Ts...> old)
{ {
std::swap(type_id, old.type_id); std::swap(type_id, old.type_id);
std::swap(data, old.data); std::swap(data, old.data);
return *this;
}
   
//move assignment operator
variant<F, Ts...>& operator= (variant<F, Ts...>&& old)
{
std::swap(type_id, std::move(old.type_id));
std::swap(data, std::move(old.data));
return *this; return *this;
} }
   
...@@ -140,7 +134,7 @@ public: ...@@ -140,7 +134,7 @@ public:
{ {
return helper_t::compareEq(type_id, &data, other.type_id, &other.data); return helper_t::compareEq(type_id, &data, other.type_id, &other.data);
} }
bool operator< (const variant<F, Ts...>& other) const bool operator< (const variant<F, Ts...>& other) const
{ {
return helper_t::compareLess(type_id, &data, other.type_id, &other.data); return helper_t::compareLess(type_id, &data, other.type_id, &other.data);
...@@ -150,12 +144,12 @@ public: ...@@ -150,12 +144,12 @@ public:
bool is() const { bool is() const {
return (type_id == typeid(T).hash_code()); return (type_id == typeid(T).hash_code());
} }
template<typename T> template<typename T>
void set(T&& value) void set(T&& value)
{ {
if(std::is_base_of_any<T, F, Ts...>::value) { if(std::is_base_of_any<T, F, Ts...>::value) {
helper_t::destroy(type_id, &data); helper_t::destroy(type_id, &data);
new (&data) T(value); new (&data) T(value);
type_id = typeid(T).hash_code(); type_id = typeid(T).hash_code();
} else } else
...@@ -163,10 +157,10 @@ public: ...@@ -163,10 +157,10 @@ public:
} }
   
template<typename T> template<typename T>
void set(T& value) void set(const T& value)
{ {
if(std::is_base_of_any<T, F, Ts...>::value) { if(std::is_base_of_any<T, F, Ts...>::value) {
helper_t::destroy(type_id, &data); helper_t::destroy(type_id, &data);
new (&data) T(value); new (&data) T(value);
type_id = typeid(T).hash_code(); type_id = typeid(T).hash_code();
} else } else
...@@ -181,8 +175,8 @@ public: ...@@ -181,8 +175,8 @@ public:
return *reinterpret_cast<T*>(&data); return *reinterpret_cast<T*>(&data);
else else
throw std::bad_cast(); throw std::bad_cast();
} }
template<typename T> template<typename T>
const T& get() const const T& get() const
{ {
...@@ -191,8 +185,8 @@ public: ...@@ -191,8 +185,8 @@ public:
return *reinterpret_cast<const T*>(&data); return *reinterpret_cast<const T*>(&data);
else else
throw std::bad_cast(); throw std::bad_cast();
} }
~variant() { ~variant() {
helper_t::destroy(type_id, &data); helper_t::destroy(type_id, &data);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment