浏览代码

Fix self-assignment and forwarding reference overloading in Variant and ObserverPtr

Michael Ragazzon 3 年之前
父节点
当前提交
846af18b72
共有 4 个文件被更改,包括 19 次插入12 次删除
  1. 4 0
      Include/RmlUi/Core/ObserverPtr.h
  2. 3 3
      Include/RmlUi/Core/Variant.h
  3. 5 6
      Include/RmlUi/Core/Variant.inl
  4. 7 3
      Source/Core/Variant.cpp

+ 4 - 0
Include/RmlUi/Core/ObserverPtr.h

@@ -79,6 +79,8 @@ public:
 			block->num_observers += 1;
 	}
 	ObserverPtr<T>& operator=(const ObserverPtr<T>& other) noexcept {
+		if(this == &other)
+			return *this;
 		reset();
 		block = other.block;
 		if (block)
@@ -89,6 +91,8 @@ public:
 	// Move
 	ObserverPtr(ObserverPtr<T>&& other) noexcept : block(std::exchange(other.block, nullptr)) {}
 	ObserverPtr<T>& operator=(ObserverPtr<T>&& other) noexcept {
+		if(this == &other)
+			return *this;
 		reset();
 		block = std::exchange(other.block, nullptr);
 		return *this;

+ 3 - 3
Include/RmlUi/Core/Variant.h

@@ -84,11 +84,11 @@ public:
 	~Variant();
 
 	// Construct by variant type
-	template< typename T >
+	template <typename T, typename = std::enable_if_t<!std::is_same<Variant, std::decay_t<T>>::value>>
 	explicit Variant(T&& t);
 
 	// Assign by variant type
-	template<typename T>
+	template <typename T, typename = std::enable_if_t<!std::is_same<Variant, std::decay_t<T>>::value>>
 	Variant& operator=(T&& t);
 
 	void Clear();
@@ -157,7 +157,7 @@ private:
 	
 	static constexpr size_t LOCAL_DATA_SIZE = (sizeof(TransitionList) > sizeof(String) ? sizeof(TransitionList) : sizeof(String));
 
-	Type type;
+	Type type = NONE;
 	alignas(TransitionList) char data[LOCAL_DATA_SIZE];
 };
 

+ 5 - 6
Include/RmlUi/Core/Variant.inl

@@ -33,13 +33,13 @@ inline Variant::Type Variant::GetType() const
 	return type;
 }
 
-template< typename T >
-Variant::Variant(T&& t) : type(NONE)
+template <typename T, typename>
+Variant::Variant(T&& t)
 {
 	Set(std::forward<T>(t));
 }
 
-template< typename T >
+template <typename T, typename>
 Variant& Variant::operator=(T&& t)
 {
 	Clear();
@@ -81,7 +81,6 @@ bool Variant::GetInto(T& value) const
 	return false;
 }
 
-// Templatised data accessor.
 template< typename T >
 T Variant::Get(T default_value) const
 {
@@ -90,9 +89,9 @@ T Variant::Get(T default_value) const
 }
 
 template<typename T>
-inline const T& Variant::GetReference() const
+const T& Variant::GetReference() const
 {
-	return *(T*)data;
+	return *reinterpret_cast<const T*>(&data);
 }
 
 } // namespace Rml

+ 7 - 3
Source/Core/Variant.cpp

@@ -31,7 +31,7 @@
 
 namespace Rml {
 
-Variant::Variant() : type(NONE)
+Variant::Variant()
 {
 	// Make sure our object size assumptions fit inside the static buffer
 	static_assert(sizeof(Colourb) <= LOCAL_DATA_SIZE, "Local data too small for Colourb");
@@ -45,12 +45,12 @@ Variant::Variant() : type(NONE)
 	static_assert(sizeof(FontEffectsPtr) <= LOCAL_DATA_SIZE, "Local data too small for FontEffectsPtr");
 }
 
-Variant::Variant(const Variant& copy) : type(NONE)
+Variant::Variant(const Variant& copy)
 {
 	Set(copy);
 }
 
-Variant::Variant(Variant&& other) noexcept : type(NONE)
+Variant::Variant(Variant&& other) noexcept
 {
 	Set(std::move(other));
 }
@@ -409,6 +409,8 @@ void Variant::Set(FontEffectsPtr&& value)
 
 Variant& Variant::operator=(const Variant& copy)
 {
+	if (this == &copy)
+		return *this;
 	if (copy.type != type)
 		Clear();
 	Set(copy);
@@ -417,6 +419,8 @@ Variant& Variant::operator=(const Variant& copy)
 
 Variant& Variant::operator=(Variant&& other) noexcept
 {
+	if (this == &other)
+		return *this;
 	if (other.type != type)
 		Clear();
 	Set(std::move(other));