mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	core: Use unrestricted union to hold storage of ResultVal value
This commit is contained in:
		
							parent
							
								
									987d85a33b
								
							
						
					
					
						commit
						6dd05e610a
					
				
					 1 changed files with 16 additions and 42 deletions
				
			
		|  | @ -269,7 +269,6 @@ public: | |||
|         : result_code(error_code) | ||||
|     { | ||||
|         ASSERT(error_code.IsError()); | ||||
|         UpdateDebugPtr(); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|  | @ -287,40 +286,37 @@ public: | |||
|         : result_code(o.result_code) | ||||
|     { | ||||
|         if (!o.empty()) { | ||||
|             new (&storage) T(*o.GetPointer()); | ||||
|             new (&object) T(o.object); | ||||
|         } | ||||
|         UpdateDebugPtr(); | ||||
|     } | ||||
| 
 | ||||
|     ResultVal(ResultVal&& o) | ||||
|         : result_code(o.result_code) | ||||
|     { | ||||
|         if (!o.empty()) { | ||||
|             new (&storage) T(std::move(*o.GetPointer())); | ||||
|             new (&object) T(std::move(o.object)); | ||||
|         } | ||||
|         UpdateDebugPtr(); | ||||
|     } | ||||
| 
 | ||||
|     ~ResultVal() { | ||||
|         if (!empty()) { | ||||
|             GetPointer()->~T(); | ||||
|             object.~T(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     ResultVal& operator=(const ResultVal& o) { | ||||
|         if (!empty()) { | ||||
|             if (!o.empty()) { | ||||
|                 *GetPointer() = *o.GetPointer(); | ||||
|                 object = o.object; | ||||
|             } else { | ||||
|                 GetPointer()->~T(); | ||||
|                 object.~T(); | ||||
|             } | ||||
|         } else { | ||||
|             if (!o.empty()) { | ||||
|                 new (&storage) T(*o.GetPointer()); | ||||
|                 new (&object) T(o.object); | ||||
|             } | ||||
|         } | ||||
|         result_code = o.result_code; | ||||
|         UpdateDebugPtr(); | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
|  | @ -333,11 +329,10 @@ public: | |||
|     void emplace(ResultCode success_code, Args&&... args) { | ||||
|         ASSERT(success_code.IsSuccess()); | ||||
|         if (!empty()) { | ||||
|             GetPointer()->~T(); | ||||
|             object.~T(); | ||||
|         } | ||||
|         new (&storage) T(std::forward<Args>(args)...); | ||||
|         new (&object) T(std::forward<Args>(args)...); | ||||
|         result_code = success_code; | ||||
|         UpdateDebugPtr(); | ||||
|     } | ||||
| 
 | ||||
|     /// Returns true if the `ResultVal` contains an error code and no value.
 | ||||
|  | @ -350,15 +345,15 @@ public: | |||
| 
 | ||||
|     ResultCode Code() const { return result_code; } | ||||
| 
 | ||||
|     const T& operator* () const { return *GetPointer(); } | ||||
|           T& operator* ()       { return *GetPointer(); } | ||||
|     const T* operator->() const { return  GetPointer(); } | ||||
|           T* operator->()       { return  GetPointer(); } | ||||
|     const T& operator* () const { return object; } | ||||
|           T& operator* ()       { return object; } | ||||
|     const T* operator->() const { return &object; } | ||||
|           T* operator->()       { return &object; } | ||||
| 
 | ||||
|     /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing.
 | ||||
|     template <typename U> | ||||
|     T ValueOr(U&& value) const { | ||||
|         return !empty() ? *GetPointer() : std::move(value); | ||||
|         return !empty() ? object : std::move(value); | ||||
|     } | ||||
| 
 | ||||
|     /// Asserts that the result succeeded and returns a reference to it.
 | ||||
|  | @ -372,31 +367,10 @@ public: | |||
|     } | ||||
| 
 | ||||
| private: | ||||
|     typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type StorageType; | ||||
| 
 | ||||
|     StorageType storage; | ||||
|     // A union is used to allocate the storage for the value, while allowing us to construct and
 | ||||
|     // destruct it at will.
 | ||||
|     union { T object; }; | ||||
|     ResultCode result_code; | ||||
| #ifdef _DEBUG | ||||
|     // The purpose of this pointer is to aid inspecting the type with a debugger, eliminating the
 | ||||
|     // need to cast `storage` to a pointer or pay attention to `result_code`.
 | ||||
|     const T* debug_ptr; | ||||
| #endif | ||||
| 
 | ||||
|     void UpdateDebugPtr() { | ||||
| #ifdef _DEBUG | ||||
|         debug_ptr = empty() ? nullptr : static_cast<const T*>(static_cast<const void*>(&storage)); | ||||
| #endif | ||||
|     } | ||||
| 
 | ||||
|     const T* GetPointer() const { | ||||
|         ASSERT(!empty()); | ||||
|         return static_cast<const T*>(static_cast<const void*>(&storage)); | ||||
|     } | ||||
| 
 | ||||
|     T* GetPointer() { | ||||
|         ASSERT(!empty()); | ||||
|         return static_cast<T*>(static_cast<void*>(&storage)); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue