From 68d54a837efb1aa8ed41008eee0d93118c154238 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 1 Jun 2023 10:17:56 +0300 Subject: [PATCH] Add move semantics to Variant --- source/core/variant.h | 48 ++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/source/core/variant.h b/source/core/variant.h index fccf891..5cb1b93 100644 --- a/source/core/variant.h +++ b/source/core/variant.h @@ -26,32 +26,39 @@ public: const std::type_info &(*get_type)(); bool (*compare)(const char *, const char *); void (*clone)(char *, const char *); + void (*move)(char *, char *); void (*destroy)(char *); }; private: + template + using EnableNotVariant = typename std::enable_if::type>::type, Variant>::value>::type; + const Functions *funcs = nullptr; alignas(void *) char storage[INTERNAL_SIZE]; public: Variant() = default; - template - Variant(const T &v) { assign(v); } + template> + Variant(T &&v) { assign(std::forward(v)); } Variant(const Variant &v) { copy_from(v); } + Variant(Variant &&v) { move_from(std::move(v)); } ~Variant() { clear(); } - template - Variant &operator=(const T &v) { assign(v); return *this; } + template> + Variant &operator=(T &&v) { assign(std::forward(v)); return *this; } Variant &operator=(const Variant &v) { if(&v!=this) copy_from(v); return *this; } + Variant &operator=(Variant &&v) { if(&v!=this) move_from(std::move(v)); return *this; } void clear(); private: template - void assign(const T &); + void assign(T &&); void copy_from(const Variant &); + void move_from(Variant &&); template T &get(); @@ -98,12 +105,12 @@ private: static const std::type_info &get_type() { return typeid(T); } template - static EnableSmall create(char *s, const T &v) - { new(s) T(v); } + static EnableSmall create(char *s, T &&v) + { new(s) typename std::remove_reference::type(std::forward(v)); } template - static EnableLarge create(char *s, const T &v) - { *reinterpret_cast(s) = new T(v); } + static EnableLarge create(char *s, T &&v) + { using V = typename std::remove_reference::type; *reinterpret_cast(s) = new V(std::forward(v)); } template static typename std::enable_if::value, bool>::type compare(const char *, const char *) @@ -125,6 +132,14 @@ private: static EnableLarge clone(char *s, const char *v) { *reinterpret_cast(s) = new T(**reinterpret_cast(v)); } + template + static EnableSmall move(char *s, char *v) + { new(s) T(std::move(*reinterpret_cast(v))); } + + template + static EnableLarge move(char *s, char *v) + { T *&p = *reinterpret_cast(v); *reinterpret_cast(s) = p; p = nullptr; } + template static EnableSmall destroy(char *s) { reinterpret_cast(s)->~T(); } @@ -143,11 +158,11 @@ inline void Variant::clear() } template -inline void Variant::assign(const T &v) +inline void Variant::assign(T &&v) { clear(); - funcs = get_functions::type>(); - create(storage, v); + funcs = get_functions::type>::type>(); + create(storage, std::forward(v)); } inline void Variant::copy_from(const Variant &v) @@ -157,6 +172,14 @@ inline void Variant::copy_from(const Variant &v) funcs->clone(storage, v.storage); } +inline void Variant::move_from(Variant &&v) +{ + clear(); + if((funcs = v.funcs)) + funcs->move(storage, v.storage); + v.clear(); +} + template inline T &Variant::get() { @@ -187,6 +210,7 @@ inline const Variant::Functions *Variant::get_functions() &get_type, &compare, &clone, + &move, &destroy }; return &funcs; -- 2.45.2