Skip to content

Instantly share code, notes, and snippets.

@cartercanedy
Last active April 12, 2025 17:47
Show Gist options
  • Save cartercanedy/d9806c465090bb3c78a9967b414e01fa to your computer and use it in GitHub Desktop.
Save cartercanedy/d9806c465090bb3c78a9967b414e01fa to your computer and use it in GitHub Desktop.
Reference classes that emulate types from the <memory> header of the standard library
#pragma once
#ifndef __cplusplus_cli
# error "Not for use in native C++ compilations"
#endif
namespace NativeMemory {
template <class T>
value struct DefaultDeleter {
auto operator()(T *t) {
if (t) {
delete t;
}
}
};
}
#pragma once
#ifndef __cplusplus_cli
# error "Not for use in native C++ compilations"
#endif
#error "SharedPtr is a WIP"
#include "DefaultDeleter.h"
namespace NativeMemory {
template <class T, class Deleter = DefaultDeleter<T>>
ref class SharedPtr;
template <class T, class Deleter = DefaultDeleter<T>>
auto MakeShared(T *) -> SharedPtr<T, Deleter>;
template <class T, class Deleter>
auto MakeShared(T *, Deleter) -> SharedPtr<T, Deleter>;
template <class T, class... Args>
auto MakeShared(Args &&...) -> SharedPtr<T, DefaultDeleter<T>>;
}
#pragma once
#ifndef __cplusplus_cli
# error "Not for use in native C++ compilations"
#endif
#include "DefaultDeleter.h"
namespace NativeMemory {
template <class T, class Deleter = DefaultDeleter<T>>
ref class UniquePtr;
template <class T, class Deleter = DefaultDeleter<T>>
auto MakeUnique(T *t) -> UniquePtr<T, Deleter>;
template <class T, class Deleter>
auto MakeUnique(T *t, Deleter deleter = DefaultDeleter<T>()) -> UniquePtr<T, decltype(deleter)>;
template <class T, class... Args>
auto MakeUnique(Args &&... args) -> UniquePtr<T, DefaultDeleter<T>>;
template <class T, class Deleter>
ref class UniquePtr {
static_assert(!__is_ref_class(T), "Cannot create a UniquePtr to a managed type");
T *m_Ptr{nullptr};
Deleter ^m_Deleter{};
auto Swap(UniquePtr<T, Deleter> %other) -> void {
std::swap(m_Ptr, other.m_Ptr);
std::swap(m_Deleter, other.m_Deleter);
}
auto Release() -> T * {
return std::exchange(nullptr);
}
auto Reset(T *newPtr) -> void {
T *oldPtr(Swap(newPtr));
m_Deleter(oldPtr);
}
UniquePtr(UniquePtr %other);
constexpr UniquePtr %operator=(const UniquePtr %other) {
static_assert(false, "Attempted to invoke copy-ctor of UniquePtr<T>");
}
public:
UniquePtr(): m_Ptr{nullptr}, m_Deleter{} { }
explicit UniquePtr(T *t): m_Ptr(t) { }
UniquePtr(T *t, Deleter ^deleter): m_Ptr(t), m_Deleter(deleter) { }
~UniquePtr() {
(*this).!UniquePtr();
m_Deleter(m_Ptr);
}
!UniquePtr() {
if (m_Ptr) {
m_Deleter(m_Ptr);
}
}
auto operator->() -> T * {
return this->m_Ptr;
}
static auto operator*(const UniquePtr<T, Deleter> %inst) -> T & {
return inst->*m_Ptr;
}
auto Get() -> T * {
return m_Ptr;
}
};
template <class T, class... Args>
auto MakeUnique(Args &&... args) -> UniquePtr<T, DefaultDeleter<T>> {
return UniquePtr<T>(new T(args...));
}
template <class T, class Deleter>
auto MakeUnique(T *t) -> UniquePtr<T, Deleter> {
return UniquePtr<T, Deleter>{t};
}
template <class T, class Deleter>
auto MakeUnique(T *t, Deleter deleter) -> UniquePtr<T, Deleter> {
return UniquePtr<T, Deleter>(t, deleter);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment