Add move assignment and move constructor to Variant.
Add `_to_variant` helper functions to `gdvirtual.gen.inc` to work around an MSVC bug.
This commit is contained in:
@ -127,7 +127,7 @@ def generate_version(argcount, const=False, returns=False, required=False):
|
|||||||
callptrargsptr += ", "
|
callptrargsptr += ", "
|
||||||
argtext += f"m_type{i + 1}"
|
argtext += f"m_type{i + 1}"
|
||||||
callargtext += f"m_type{i + 1} arg{i + 1}"
|
callargtext += f"m_type{i + 1} arg{i + 1}"
|
||||||
callsiargs += f"Variant(arg{i + 1})"
|
callsiargs += f"_to_variant(arg{i + 1})"
|
||||||
callsiargptrs += f"&vargs[{i}]"
|
callsiargptrs += f"&vargs[{i}]"
|
||||||
callptrargs += (
|
callptrargs += (
|
||||||
f"PtrToArg<m_type{i + 1}>::EncodeT argval{i + 1} = (PtrToArg<m_type{i + 1}>::EncodeT)arg{i + 1};\\\n"
|
f"PtrToArg<m_type{i + 1}>::EncodeT argval{i + 1} = (PtrToArg<m_type{i + 1}>::EncodeT)arg{i + 1};\\\n"
|
||||||
@ -185,6 +185,8 @@ def run(target, source, env):
|
|||||||
|
|
||||||
#include "core/object/script_instance.h"
|
#include "core/object/script_instance.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
#define GDVIRTUAL_TRACK(m_virtual, m_initialized)\\
|
#define GDVIRTUAL_TRACK(m_virtual, m_initialized)\\
|
||||||
if (_get_extension()->reloadable) {\\
|
if (_get_extension()->reloadable) {\\
|
||||||
@ -198,6 +200,37 @@ def run(target, source, env):
|
|||||||
#define GDVIRTUAL_TRACK(m_virtual, m_initialized)
|
#define GDVIRTUAL_TRACK(m_virtual, m_initialized)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// MSVC WORKAROUND START
|
||||||
|
// FIXME The below helper functions are needed to work around an MSVC bug.
|
||||||
|
// They should be removed (by modifying core/object/make_virtuals.py) once the bug ceases to be triggered.
|
||||||
|
// The bug is triggered by the following code:
|
||||||
|
// `Variant(arg)`
|
||||||
|
// Through the introduction of the move constructor, MSVC forgets that `operator Variant()`
|
||||||
|
// is also a valid way to resolve this call. So for some argument types, it fails the call because
|
||||||
|
// it cannot convert to `Variant`.
|
||||||
|
// The function `_to_variant` helps the compiler select `.operator Variant()` for appropriate arguments using SFINAE.
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct has_variant_operator : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct has_variant_operator<T, std::void_t<decltype(std::declval<T>().operator Variant())>> : std::true_type {};
|
||||||
|
|
||||||
|
// Function that is enabled if T has `.operator Variant()`.
|
||||||
|
template <typename T>
|
||||||
|
_ALWAYS_INLINE_ typename std::enable_if<has_variant_operator<T>::value, Variant>::type
|
||||||
|
_to_variant(T&& t) {
|
||||||
|
return std::forward<T>(t).operator Variant();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function that is enabled if T does not have `.operator Variant()`.
|
||||||
|
template <typename T>
|
||||||
|
_ALWAYS_INLINE_ typename std::enable_if<!has_variant_operator<T>::value, Variant>::type
|
||||||
|
_to_variant(T&& t) {
|
||||||
|
return Variant(std::forward<T>(t));
|
||||||
|
}
|
||||||
|
// MSVC WORKAROUND END
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for i in range(max_versions + 1):
|
for i in range(max_versions + 1):
|
||||||
|
|||||||
@ -811,11 +811,25 @@ public:
|
|||||||
static void construct_from_string(const String &p_string, Variant &r_value, ObjectConstruct p_obj_construct = nullptr, void *p_construct_ud = nullptr);
|
static void construct_from_string(const String &p_string, Variant &r_value, ObjectConstruct p_obj_construct = nullptr, void *p_construct_ud = nullptr);
|
||||||
|
|
||||||
void operator=(const Variant &p_variant); // only this is enough for all the other types
|
void operator=(const Variant &p_variant); // only this is enough for all the other types
|
||||||
|
void operator=(Variant &&p_variant) {
|
||||||
|
if (unlikely(this == &p_variant)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clear();
|
||||||
|
type = p_variant.type;
|
||||||
|
_data = p_variant._data;
|
||||||
|
p_variant.type = NIL;
|
||||||
|
}
|
||||||
|
|
||||||
static void register_types();
|
static void register_types();
|
||||||
static void unregister_types();
|
static void unregister_types();
|
||||||
|
|
||||||
Variant(const Variant &p_variant);
|
Variant(const Variant &p_variant);
|
||||||
|
Variant(Variant &&p_variant) {
|
||||||
|
type = p_variant.type;
|
||||||
|
_data = p_variant._data;
|
||||||
|
p_variant.type = NIL;
|
||||||
|
}
|
||||||
_FORCE_INLINE_ Variant() {}
|
_FORCE_INLINE_ Variant() {}
|
||||||
_FORCE_INLINE_ ~Variant() {
|
_FORCE_INLINE_ ~Variant() {
|
||||||
clear();
|
clear();
|
||||||
|
|||||||
Reference in New Issue
Block a user