aboutsummaryrefslogtreecommitdiff
path: root/src/brussel.common/ScopedResource.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/brussel.common/ScopedResource.hpp')
-rw-r--r--src/brussel.common/ScopedResource.hpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/brussel.common/ScopedResource.hpp b/src/brussel.common/ScopedResource.hpp
new file mode 100644
index 0000000..b4098eb
--- /dev/null
+++ b/src/brussel.common/ScopedResource.hpp
@@ -0,0 +1,54 @@
+#pragma once
+
+#include <type_traits>
+
+/// std::unique_ptr, but for non-pointer resources
+template <typename T, typename TDeleter, T kNullValue = T()>
+ requires std::is_trivial_v<T> && std::equality_comparable<T>
+class ScopedResource {
+private:
+ T mValue;
+
+public:
+ ScopedResource()
+ : mValue{ kNullValue } {}
+ explicit ScopedResource(T t)
+ : mValue{ std::move(t) } {}
+
+ ScopedResource(const ScopedResource& that) = delete;
+ ScopedResource& operator=(const ScopedResource& that) = delete;
+
+ ScopedResource(ScopedResource&& that) noexcept
+ : mValue(that.mValue) {}
+ ScopedResource& operator=(ScopedResource&& that) noexcept {
+ if (this == &that)
+ return *this;
+ TDeleter::DeleteObject(mValue);
+ mValue = that.mValue;
+ that.mValue = kNullValue;
+ return *this;
+ }
+
+ ScopedResource& operator=(T newValue) {
+ TDeleter::DeleteObject(mValue);
+ mValue = newValue;
+ return *this;
+ }
+
+ ~ScopedResource() {
+ TDeleter::DeleteObject(mValue);
+ }
+
+ explicit operator bool() const {
+ return mValue != kNullValue;
+ }
+
+ const T& get() const { return mValue; }
+ T& get() { return mValue; }
+
+ T release() {
+ T tmp = mValue;
+ mValue = kNullValue;
+ return tmp;
+ }
+};