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<typename T>
+ using EnableNotVariant = typename std::enable_if<!std::is_same<typename std::remove_cv<typename std::remove_reference<T>::type>::type, Variant>::value>::type;
+
const Functions *funcs = nullptr;
alignas(void *) char storage[INTERNAL_SIZE];
public:
Variant() = default;
- template<typename T>
- Variant(const T &v) { assign(v); }
+ template<typename T, typename = EnableNotVariant<T>>
+ Variant(T &&v) { assign(std::forward<T>(v)); }
Variant(const Variant &v) { copy_from(v); }
+ Variant(Variant &&v) { move_from(std::move(v)); }
~Variant() { clear(); }
- template<typename T>
- Variant &operator=(const T &v) { assign(v); return *this; }
+ template<typename T, typename = EnableNotVariant<T>>
+ Variant &operator=(T &&v) { assign(std::forward<T>(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<typename T>
- void assign(const T &);
+ void assign(T &&);
void copy_from(const Variant &);
+ void move_from(Variant &&);
template<typename T>
T &get();
static const std::type_info &get_type() { return typeid(T); }
template<typename T>
- static EnableSmall<T, void> create(char *s, const T &v)
- { new(s) T(v); }
+ static EnableSmall<T, void> create(char *s, T &&v)
+ { new(s) typename std::remove_reference<T>::type(std::forward<T>(v)); }
template<typename T>
- static EnableLarge<T, void> create(char *s, const T &v)
- { *reinterpret_cast<T **>(s) = new T(v); }
+ static EnableLarge<T, void> create(char *s, T &&v)
+ { using V = typename std::remove_reference<T>::type; *reinterpret_cast<V **>(s) = new V(std::forward<T>(v)); }
template<typename T>
static typename std::enable_if<!IsEqualityComparable<T>::value, bool>::type compare(const char *, const char *)
static EnableLarge<T, void> clone(char *s, const char *v)
{ *reinterpret_cast<T **>(s) = new T(**reinterpret_cast<const T *const *>(v)); }
+ template<typename T>
+ static EnableSmall<T, void> move(char *s, char *v)
+ { new(s) T(std::move(*reinterpret_cast<T *>(v))); }
+
+ template<typename T>
+ static EnableLarge<T, void> move(char *s, char *v)
+ { T *&p = *reinterpret_cast<T **>(v); *reinterpret_cast<T **>(s) = p; p = nullptr; }
+
template<typename T>
static EnableSmall<T, void> destroy(char *s)
{ reinterpret_cast<T *>(s)->~T(); }
}
template<typename T>
-inline void Variant::assign(const T &v)
+inline void Variant::assign(T &&v)
{
clear();
- funcs = get_functions<typename std::remove_cv<T>::type>();
- create(storage, v);
+ funcs = get_functions<typename std::remove_cv<typename std::remove_reference<T>::type>::type>();
+ create(storage, std::forward<T>(v));
}
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<typename T>
inline T &Variant::get()
{
&get_type<T>,
&compare<T>,
&clone<T>,
+ &move<T>,
&destroy<T>
};
return &funcs;