Skip to content

Instantly share code, notes, and snippets.

@dwilliamson
Created November 26, 2020 12:47
Show Gist options
  • Save dwilliamson/2e80a5c5f504fb4c4ba1dc5605be6880 to your computer and use it in GitHub Desktop.
Save dwilliamson/2e80a5c5f504fb4c4ba1dc5605be6880 to your computer and use it in GitHub Desktop.
Don't do this...
// -------------------------------------------------------------------------------------------------------------------------------
// 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