From: Mikko Rasa Date: Mon, 11 Sep 2023 08:00:25 +0000 (+0300) Subject: Refactor Variant's internals to be compatible with older MSVC versions X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=0c435b15bcbe0d8f98c29c84a6dd45f13b7704b9;p=libs%2Fcore.git Refactor Variant's internals to be compatible with older MSVC versions --- diff --git a/source/core/variant.h b/source/core/variant.h index b00f561..f566e5e 100644 --- a/source/core/variant.h +++ b/source/core/variant.h @@ -31,6 +31,9 @@ public: }; private: + template + struct FunctionsImpl; + template using EnableNotVariant = typename std::enable_if::type>::type, Variant>::value>::type; @@ -90,63 +93,59 @@ public: private: static bool type_equals(const Functions *, const Functions *); - template - static constexpr bool is_small() { return (sizeof(T)<=INTERNAL_SIZE && alignof(T)<=alignof(void *)); } - - template - using EnableSmall = typename std::enable_if(), U>::type; - - template - using EnableLarge = typename std::enable_if(), U>::type; - template static const Functions *get_functions(); template static const std::type_info &get_type() { return typeid(T); } - template - static EnableSmall create(char *s, T &&v) - { new(s) typename std::remove_reference::type(std::forward(v)); } + /* The extra function parameter is needed to avoid duplicate definition error + from MSVC 19.29 (VS 2019) */ + template::value>::type> + static bool compare(const T &, const T &, int = 0) + { return false; } - template - static EnableLarge create(char *s, T &&v) - { using V = typename std::remove_reference::type; *reinterpret_cast(s) = new V(std::forward(v)); } + template::value>::type> + static bool compare(const T &v1, const T &v2) + { return v1==v2; } +}; - template - static typename std::enable_if::value, bool>::type compare(const char *, const char *) - { return false; } - template - static typename std::enable_if::value, EnableSmall>::type compare(const char *s1, const char *s2) - { return *reinterpret_cast(s1)==*reinterpret_cast(s2); } +template +struct Variant::FunctionsImpl +{ + static void create(char *s, T &&v) + { new(s) typename std::remove_reference::type(std::forward(v)); } - template - static typename std::enable_if::value, EnableLarge>::type compare(const char *s1, const char *s2) - { return **reinterpret_cast(s1)==**reinterpret_cast(s2); } + static bool compare(const char *s1, const char *s2) + { return Variant::compare(*reinterpret_cast(s1), *reinterpret_cast(s2)); } - template - static EnableSmall clone(char *s, const char *v) + static void clone(char *s, const char *v) { new(s) T(*reinterpret_cast(v)); } - template - static EnableLarge clone(char *s, const char *v) - { *reinterpret_cast(s) = new T(**reinterpret_cast(v)); } - - template - static EnableSmall move(char *s, char *v) + static void 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) + static void destroy(char *s) { reinterpret_cast(s)->~T(); } +}; - template - static EnableLarge destroy(char *s) +template +struct Variant::FunctionsImpl +{ + static void create(char *s, T &&v) + { using V = typename std::remove_reference::type; *reinterpret_cast(s) = new V(std::forward(v)); } + + static bool compare(const char *s1, const char *s2) + { return Variant::compare(**reinterpret_cast(s1), **reinterpret_cast(s2)); } + + static void clone(char *s, const char *v) + { *reinterpret_cast(s) = new T(**reinterpret_cast(v)); } + + static void move(char *s, char *v) + { T *&p = *reinterpret_cast(v); *reinterpret_cast(s) = p; p = nullptr; } + + static void destroy(char *s) { delete *reinterpret_cast(s); } }; @@ -163,7 +162,7 @@ inline void Variant::assign(T &&v) { clear(); funcs = get_functions::type>::type>(); - create(storage, std::forward(v)); + FunctionsImpl::create(storage, std::forward(v)); } inline void Variant::copy_from(const Variant &v) @@ -216,13 +215,14 @@ inline bool Variant::type_equals(const Functions *funcs1, const Functions *funcs template inline const Variant::Functions *Variant::get_functions() { + using Impl = FunctionsImpl; static Functions funcs = { &get_type, - &compare, - &clone, - &move, - &destroy + &Impl::compare, + &Impl::clone, + &Impl::move, + &Impl::destroy }; return &funcs; }