Last active
April 12, 2025 17:47
-
-
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
This file contains hidden or 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
#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; | |
} | |
} | |
}; | |
} |
This file contains hidden or 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
#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