Created
November 26, 2020 12:47
-
-
Save dwilliamson/2e80a5c5f504fb4c4ba1dc5605be6880 to your computer and use it in GitHub Desktop.
Don't do this...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ------------------------------------------------------------------------------------------------------------------------------- | |
// Opaque Object Containers: Provide RAII/Move semantics for opaque pointers. | |
// ------------------------------------------------------------------------------------------------------------------------------- | |
// Opaque handles must implement the commented out types/functions | |
template <typename Type> | |
struct ctrOpaqueTypeTraits | |
{ | |
// using Type = OpaqueType; | |
// static constexpr auto New = Type_New; | |
// static constexpr auto Delete = Type_Delete; | |
}; | |
// Opaque object container. | |
// Don't construct directly; use `ctrOpaqueNew` instead. | |
template <typename Type> | |
struct ctrOpaqueObject | |
{ | |
using Traits = ctrOpaqueTypeTraits<Type>; | |
// Default constructor for storing equivalent of null reference pointer. | |
// WARNING(don): Undefind Behaviour that works for all required platforms. | |
ctrOpaqueObject() | |
: ref(*reinterpret_cast<Type*>(nullptr)) | |
{ | |
} | |
// Take ownership | |
ctrOpaqueObject(Type* ptr) | |
: ref(*ptr) | |
{ | |
assert(ptr != nullptr); | |
} | |
~ctrOpaqueObject() | |
{ | |
Delete(); | |
} | |
// Disallow copying as the traits don't have entries for this | |
ctrOpaqueObject(const ctrOpaqueObject&) = delete; | |
ctrOpaqueObject& operator=(const ctrOpaqueObject&) = delete; | |
// Allow moving around | |
ctrOpaqueObject(ctrOpaqueObject&& other) | |
: ref(other.ref) | |
{ | |
SetNull(other); | |
} | |
ctrOpaqueObject& operator=(ctrOpaqueObject&& other) | |
{ | |
Delete(); | |
Move(coreMove(other)); | |
SetNull(other); | |
return *this; | |
} | |
Type& ref; | |
private: | |
void Delete() | |
{ | |
if (&ref != nullptr) | |
{ | |
Traits::Delete(&ref); | |
} | |
} | |
void Move(ctrOpaqueObject&& other) | |
{ | |
// Copy reference from other | |
// WARNING(don): Undefined Behaviour that works for all required platforms. | |
*reinterpret_cast<Type**>(this) = *reinterpret_cast<Type**>(&other); | |
} | |
void SetNull(ctrOpaqueObject& object) | |
{ | |
// Set the equivalent of null reference pointer. | |
// WARNING(don): Undefind Behaviour that works for all required platforms. | |
*reinterpret_cast<Type**>(&object) = nullptr; | |
} | |
}; | |
// Create an instance of the opaque object and give ownership to the returned opaque object. | |
// Will assert if the returned instance is null. | |
template <typename Type, typename... Arguments> | |
ctrOpaqueObject<Type> ctrOpaqueNew(Arguments&&... arguments) | |
{ | |
return ctrOpaqueObject<Type>(ctrOpaqueTypeTraits<Type>::New(coreForward(arguments)...)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment