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) |         : result_code(error_code) | ||||||
|     { |     { | ||||||
|         ASSERT(error_code.IsError()); |         ASSERT(error_code.IsError()); | ||||||
|         UpdateDebugPtr(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|  | @ -287,40 +286,37 @@ public: | ||||||
|         : result_code(o.result_code) |         : result_code(o.result_code) | ||||||
|     { |     { | ||||||
|         if (!o.empty()) { |         if (!o.empty()) { | ||||||
|             new (&storage) T(*o.GetPointer()); |             new (&object) T(o.object); | ||||||
|         } |         } | ||||||
|         UpdateDebugPtr(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ResultVal(ResultVal&& o) |     ResultVal(ResultVal&& o) | ||||||
|         : result_code(o.result_code) |         : result_code(o.result_code) | ||||||
|     { |     { | ||||||
|         if (!o.empty()) { |         if (!o.empty()) { | ||||||
|             new (&storage) T(std::move(*o.GetPointer())); |             new (&object) T(std::move(o.object)); | ||||||
|         } |         } | ||||||
|         UpdateDebugPtr(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ~ResultVal() { |     ~ResultVal() { | ||||||
|         if (!empty()) { |         if (!empty()) { | ||||||
|             GetPointer()->~T(); |             object.~T(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ResultVal& operator=(const ResultVal& o) { |     ResultVal& operator=(const ResultVal& o) { | ||||||
|         if (!empty()) { |         if (!empty()) { | ||||||
|             if (!o.empty()) { |             if (!o.empty()) { | ||||||
|                 *GetPointer() = *o.GetPointer(); |                 object = o.object; | ||||||
|             } else { |             } else { | ||||||
|                 GetPointer()->~T(); |                 object.~T(); | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             if (!o.empty()) { |             if (!o.empty()) { | ||||||
|                 new (&storage) T(*o.GetPointer()); |                 new (&object) T(o.object); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         result_code = o.result_code; |         result_code = o.result_code; | ||||||
|         UpdateDebugPtr(); |  | ||||||
| 
 | 
 | ||||||
|         return *this; |         return *this; | ||||||
|     } |     } | ||||||
|  | @ -333,11 +329,10 @@ public: | ||||||
|     void emplace(ResultCode success_code, Args&&... args) { |     void emplace(ResultCode success_code, Args&&... args) { | ||||||
|         ASSERT(success_code.IsSuccess()); |         ASSERT(success_code.IsSuccess()); | ||||||
|         if (!empty()) { |         if (!empty()) { | ||||||
|             GetPointer()->~T(); |             object.~T(); | ||||||
|         } |         } | ||||||
|         new (&storage) T(std::forward<Args>(args)...); |         new (&object) T(std::forward<Args>(args)...); | ||||||
|         result_code = success_code; |         result_code = success_code; | ||||||
|         UpdateDebugPtr(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Returns true if the `ResultVal` contains an error code and no value.
 |     /// Returns true if the `ResultVal` contains an error code and no value.
 | ||||||
|  | @ -350,15 +345,15 @@ public: | ||||||
| 
 | 
 | ||||||
|     ResultCode Code() const { return result_code; } |     ResultCode Code() const { return result_code; } | ||||||
| 
 | 
 | ||||||
|     const T& operator* () const { return *GetPointer(); } |     const T& operator* () const { return object; } | ||||||
|           T& operator* ()       { return *GetPointer(); } |           T& operator* ()       { return object; } | ||||||
|     const T* operator->() const { return  GetPointer(); } |     const T* operator->() const { return &object; } | ||||||
|           T* operator->()       { return  GetPointer(); } |           T* operator->()       { return &object; } | ||||||
| 
 | 
 | ||||||
|     /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing.
 |     /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing.
 | ||||||
|     template <typename U> |     template <typename U> | ||||||
|     T ValueOr(U&& value) const { |     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.
 |     /// Asserts that the result succeeded and returns a reference to it.
 | ||||||
|  | @ -372,31 +367,10 @@ public: | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type StorageType; |     // A union is used to allocate the storage for the value, while allowing us to construct and
 | ||||||
| 
 |     // destruct it at will.
 | ||||||
|     StorageType storage; |     union { T object; }; | ||||||
|     ResultCode result_code; |     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