};
private:
+ template<typename T, bool small = (sizeof(T)<=INTERNAL_SIZE && alignof(T)<=alignof(void *))>
+ struct FunctionsImpl;
+
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;
private:
static bool type_equals(const Functions *, const Functions *);
- template<typename T>
- static constexpr bool is_small() { return (sizeof(T)<=INTERNAL_SIZE && alignof(T)<=alignof(void *)); }
-
- template<typename T, typename U>
- using EnableSmall = typename std::enable_if<is_small<T>(), U>::type;
-
- template<typename T, typename U>
- using EnableLarge = typename std::enable_if<!is_small<T>(), U>::type;
-
template<typename T>
static const Functions *get_functions();
template<typename T>
static const std::type_info &get_type() { return typeid(T); }
- template<typename T>
- static EnableSmall<T, void> create(char *s, T &&v)
- { new(s) typename std::remove_reference<T>::type(std::forward<T>(v)); }
+ /* The extra function parameter is needed to avoid duplicate definition error
+ from MSVC 19.29 (VS 2019) */
+ template<typename T, typename = typename std::enable_if<!IsEqualityComparable<T>::value>::type>
+ static bool compare(const T &, const T &, int = 0)
+ { return false; }
- template<typename T>
- 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, typename = typename std::enable_if<IsEqualityComparable<T>::value>::type>
+ static bool compare(const T &v1, const T &v2)
+ { return v1==v2; }
+};
- template<typename T>
- static typename std::enable_if<!IsEqualityComparable<T>::value, bool>::type compare(const char *, const char *)
- { return false; }
- template<typename T>
- static typename std::enable_if<IsEqualityComparable<T>::value, EnableSmall<T, bool>>::type compare(const char *s1, const char *s2)
- { return *reinterpret_cast<const T *>(s1)==*reinterpret_cast<const T *>(s2); }
+template<typename T>
+struct Variant::FunctionsImpl<T, true>
+{
+ static void create(char *s, T &&v)
+ { new(s) typename std::remove_reference<T>::type(std::forward<T>(v)); }
- template<typename T>
- static typename std::enable_if<IsEqualityComparable<T>::value, EnableLarge<T, bool>>::type compare(const char *s1, const char *s2)
- { return **reinterpret_cast<const T *const *>(s1)==**reinterpret_cast<const T *const *>(s2); }
+ static bool compare(const char *s1, const char *s2)
+ { return Variant::compare<T>(*reinterpret_cast<const T *>(s1), *reinterpret_cast<const T *>(s2)); }
- template<typename T>
- static EnableSmall<T, void> clone(char *s, const char *v)
+ static void clone(char *s, const char *v)
{ new(s) T(*reinterpret_cast<const T *>(v)); }
- template<typename T>
- 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)
+ static 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)
+ static void destroy(char *s)
{ reinterpret_cast<T *>(s)->~T(); }
+};
- template<typename T>
- static EnableLarge<T, void> destroy(char *s)
+template<typename T>
+struct Variant::FunctionsImpl<T, false>
+{
+ static void create(char *s, T &&v)
+ { using V = typename std::remove_reference<T>::type; *reinterpret_cast<V **>(s) = new V(std::forward<T>(v)); }
+
+ static bool compare(const char *s1, const char *s2)
+ { return Variant::compare<T>(**reinterpret_cast<const T *const *>(s1), **reinterpret_cast<const T *const *>(s2)); }
+
+ static void clone(char *s, const char *v)
+ { *reinterpret_cast<T **>(s) = new T(**reinterpret_cast<const T *const *>(v)); }
+
+ static void move(char *s, char *v)
+ { T *&p = *reinterpret_cast<T **>(v); *reinterpret_cast<T **>(s) = p; p = nullptr; }
+
+ static void destroy(char *s)
{ delete *reinterpret_cast<T **>(s); }
};
{
clear();
funcs = get_functions<typename std::remove_cv<typename std::remove_reference<T>::type>::type>();
- create(storage, std::forward<T>(v));
+ FunctionsImpl<T>::create(storage, std::forward<T>(v));
}
inline void Variant::copy_from(const Variant &v)
template<typename T>
inline const Variant::Functions *Variant::get_functions()
{
+ using Impl = FunctionsImpl<T>;
static Functions funcs =
{
&get_type<T>,
- &compare<T>,
- &clone<T>,
- &move<T>,
- &destroy<T>
+ &Impl::compare,
+ &Impl::clone,
+ &Impl::move,
+ &Impl::destroy
};
return &funcs;
}