Cogs.Core
Pointer.h
1#pragma once
2
3#ifdef __clang__
4#pragma clang diagnostic push
5// There is an static assert on that the Destructor type is trivially
6// destructible, and thus there is no need to call the destructor,
7// and we get by without a virtual destructor.
8#pragma clang diagnostic ignored "-Wdelete-non-abstract-non-virtual-dtor"
9#endif
10
11#include <memory>
12#include <new>
13
14namespace Cogs
15{
17 struct DestructorBase
18 {
19 virtual void call(void *) {}
20 };
21
22 template<typename T, typename DeleterFunction>
23 struct Destructor : public DestructorBase
24 {
25 static_assert(std::is_trivially_destructible<DeleterFunction>::value, "DeleterFunction must be trivially destructible.");
26
27 Destructor(DeleterFunction t) : t(t) {}
28
29 void call(void * ptr) override { t(static_cast<T *>(ptr)); }
30
31 private:
32 DeleterFunction t;
33 };
35
64 template<typename T>
65 struct Pointer
66 {
68 Pointer() = default;
69
79 template<typename DeleterFunction>
80 Pointer(T * ptr, DeleterFunction deleter) : ptr(ptr)
81 {
82 static_assert(sizeof(Destructor<T, DeleterFunction>) <= sizeof(storage), "Deleter function too large (check capture list).");
83 static_assert(std::is_trivially_destructible<Destructor<T, DeleterFunction>>::value, "Deleter must be trivially destructible.");
84
85 new (storage) Destructor<T, DeleterFunction>(deleter);
86 }
87
89 Pointer(Pointer && other) noexcept
90 {
91 ptr = other.ptr;
92 std::memcpy(storage, other.storage, sizeof(storage));
93 other.ptr = nullptr;
94 }
95
97 Pointer & operator=(Pointer && other) noexcept
98 {
99 ptr = other.ptr;
100 std::memcpy(storage, other.storage, sizeof(storage));
101 other.ptr = nullptr;
102
103 return *this;
104 }
105
107 Pointer(Pointer & other) = delete;
108
110 Pointer & operator=(Pointer & other) = delete;
111
114 {
115 if (ptr) {
116 auto destructor = (DestructorBase *)storage;
117 destructor->call(ptr);
118 destructor->~DestructorBase();
119 }
120 }
121
135 operator bool() const { return ptr != nullptr; }
136
138 T * get() { return ptr; }
139
141 const T * get() const { return ptr; }
142
144 T * operator->() { return ptr; }
145
147 const T * operator->() const { return ptr; }
148
149 private:
151 uint8_t storage[32 - sizeof(T *)] = {};
152 T * ptr = nullptr;
154 };
155
156 static_assert(sizeof(Pointer<int>) == 32, "Internal size check failed.");
157
171 template<typename T, typename DeleterFunction>
172 Pointer<T> makePointer(T * t, DeleterFunction deleterFunc)
173 {
174 return Pointer<T>(t, deleterFunc);
175 }
176}
177
178#ifdef __clang__
179#pragma clang diagnostic pop
180#endif
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
Pointer< T > makePointer(T *t, DeleterFunction deleterFunc)
Construct a Pointer<T> instance from the given pointer and deleter function.
Definition: Pointer.h:172
Provides scoped storage for a raw pointer and corresponding deletion logic.
Definition: Pointer.h:66
Pointer & operator=(Pointer &other)=delete
Copy assignment disabled.
const T * get() const
Gets the raw pointer stored in this instance.
Definition: Pointer.h:141
const T * operator->() const
Access the raw pointer in this instance.
Definition: Pointer.h:147
T * operator->()
Access the raw pointer in this instance.
Definition: Pointer.h:144
Pointer()=default
Default construct an empty instance.
Pointer(T *ptr, DeleterFunction deleter)
Constructs the instance from the given pointer and deleter function.
Definition: Pointer.h:80
Pointer(Pointer &other)=delete
Copy construction disabled.
T * get()
Gets the raw pointer stored in this instance.
Definition: Pointer.h:138
~Pointer()
Destructs the instance, invoking cleanup logic if the instance is non-empty.
Definition: Pointer.h:113
Pointer & operator=(Pointer &&other) noexcept
Move assign an instance from other.
Definition: Pointer.h:97
Pointer(Pointer &&other) noexcept
Move construct an instance from other.
Definition: Pointer.h:89