From 6dd05e610aeca5e34439971c1e5589e1a8675e02 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sat, 5 Mar 2016 00:10:52 -0800 Subject: core: Use unrestricted union to hold storage of ResultVal value --- src/core/hle/result.h | 58 ++++++++++++++------------------------------------- 1 file changed, 16 insertions(+), 42 deletions(-) (limited to 'src/core/hle/result.h') diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 0fce5988b..69613fbbb 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -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)...); + new (&object) T(std::forward(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 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::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(static_cast(&storage)); -#endif - } - - const T* GetPointer() const { - ASSERT(!empty()); - return static_cast(static_cast(&storage)); - } - - T* GetPointer() { - ASSERT(!empty()); - return static_cast(static_cast(&storage)); - } }; /** -- cgit v1.2.3