ge211  2021.5.1
A student game engine
ge211_util.hxx
1 #pragma once
2 
3 #include <cstdlib>
4 #include <memory>
5 #include <string>
6 #include <sstream>
7 #include <type_traits>
8 
9 namespace ge211 {
10 
13 template <typename OBJECT_TYPE>
14 using Owned = OBJECT_TYPE*;
15 
18 template <typename OBJECT_TYPE>
19 using Borrowed = OBJECT_TYPE*;
20 
22 template <typename PRINTABLE>
23 std::string to_string(const PRINTABLE& value)
24 {
26  oss << value;
27  return oss.str();
28 }
29 
30 // `detail` is for implementation details
31 namespace detail {
32 
33 template <typename OBJECT_TYPE>
34 using deleter_t = void (*)(Owned<OBJECT_TYPE>);
35 
36 template <typename OBJECT_TYPE>
37 void no_op_deleter(Owned<OBJECT_TYPE>) {}
38 
39 template <typename OBJECT_TYPE>
40 void c_heap_deleter(Owned<OBJECT_TYPE> o)
41 {
42  std::free(o);
43 }
44 
45 template <
46  typename OBJECT_TYPE,
47  deleter_t<OBJECT_TYPE> Deleter_Fn = &c_heap_deleter,
48  bool Delete_Null = false
49 >
50 class delete_ptr
51 {
52 public:
53  using object_type = OBJECT_TYPE;
54  using owned_pointer = Owned<object_type>;
55  using borrowed_pointer = Borrowed<object_type>;
56  using deleter_fn_type = deleter_t<object_type>;
57 
58  static constexpr deleter_fn_type deleter_fn = Deleter_Fn;
59  static constexpr bool delete_null = Delete_Null;
60 
61  delete_ptr() noexcept
62  : ptr_(nullptr) { }
63 
64  explicit delete_ptr(owned_pointer ptr) noexcept
65  : ptr_(ptr) { }
66 
67  delete_ptr(std::nullptr_t) noexcept
68  : ptr_(nullptr) { }
69 
70  delete_ptr(delete_ptr const&) = delete;
71  delete_ptr& operator=(delete_ptr const&) = delete;
72 
73  delete_ptr(delete_ptr&& that) noexcept
74  : ptr_(that.release()) { }
75 
76  delete_ptr& operator=(delete_ptr&& that) noexcept
77  {
78  delete_it_();
79  ptr_ = that.release();
80  return *this;
81  }
82 
83  delete_ptr& operator=(owned_pointer that) noexcept
84  {
85  return *this = delete_ptr(that);
86  }
87 
88  ~delete_ptr()
89  {
90  delete_it_();
91  }
92 
93  owned_pointer release() noexcept
94  {
95  return std::exchange(ptr_, nullptr);
96  }
97 
98  borrowed_pointer get() const noexcept
99  {
100  return ptr_;
101  }
102 
103  object_type& operator*() const
104  {
105  return *ptr_;
106  }
107 
108  borrowed_pointer operator->() const noexcept
109  {
110  return ptr_;
111  }
112 
113  explicit operator bool() const noexcept
114  {
115  return ptr_ != nullptr;
116  }
117 
119  && noexcept
120  {
121  return {release(), deleter_fn};
122  };
123 
124  friend void swap(delete_ptr& a, delete_ptr& b) noexcept
125  {
126  std::swap(a.ptr_, b.ptr_);
127  }
128 
129 private:
130  void delete_it_() noexcept
131  {
132  if (delete_null || ptr_)
133  deleter_fn(ptr_);
134  }
135 
136  owned_pointer ptr_;
137 };
138 
139 template <
140  typename OBJECT_TYPE,
141  deleter_t<OBJECT_TYPE> Deleter_Fn
142 >
143 bool operator==(delete_ptr<OBJECT_TYPE, Deleter_Fn> const& a,
144  delete_ptr<OBJECT_TYPE, Deleter_Fn> const& b)
145 {
146  return a.get() == b.get();
147 }
148 
149 template <
150  typename OBJECT_TYPE,
151  deleter_t<OBJECT_TYPE> Deleter_Fn
152 >
153 bool operator!=(delete_ptr<OBJECT_TYPE, Deleter_Fn> const& a,
154  delete_ptr<OBJECT_TYPE, Deleter_Fn> const& b)
155 {
156  return !(a == b);
157 }
158 
159 template <typename OBJECT_TYPE>
160 class lazy_ptr
161 {
162 public:
163  using value = OBJECT_TYPE;
164  using reference = OBJECT_TYPE&;
165  using pointer = OBJECT_TYPE*;
166 
167  lazy_ptr()
168  { }
169 
170  bool is_forced() const
171  {
172  return ptr_ != nullptr;
173  }
174 
175  reference operator*() const
176  {
177  force_();
178  return *ptr_;
179  }
180 
181  pointer operator->() const
182  {
183  return std::addressof(operator*());
184  }
185 
186 private:
187  mutable std::unique_ptr<value> ptr_;
188 
189  void force_() const
190  {
191  if (!ptr_)
192  ptr_.reset(new value);
193  }
194 };
195 
198 template <typename FROM_TYPE, typename TO_TYPE = FROM_TYPE>
199 constexpr bool is_nothrow_convertible()
200 {
201  FROM_TYPE t{};
202  return noexcept(TO_TYPE(t));
203 }
204 
206 template <typename EQ_TYPE>
207 constexpr bool is_nothrow_comparable()
208 {
209  EQ_TYPE t{};
210  return noexcept(t == t) && noexcept(t != t);
211 }
212 
215 template <typename ARITH_LEFT, typename ARITH_RIGHT = ARITH_LEFT>
216 constexpr bool has_nothrow_arithmetic()
217 {
218  ARITH_LEFT t{};
219  ARITH_RIGHT u{};
220  return noexcept(t + u) && noexcept(t - u) && noexcept(t * u);
221 }
222 
225 template <typename DIVIDEND, typename DIVISOR = DIVIDEND>
226 constexpr bool has_nothrow_division()
227 {
228  DIVIDEND t{};
229  DIVISOR u{};
230  return noexcept(t / u);
231 }
232 
235 template <typename>
236 struct Name_of_type
237 {
238  static constexpr char const* value = "?";
239 };
240 
241 template <typename TYPE>
242 char const* name_of_type()
243 {
244  return Name_of_type<TYPE>::value;
245 }
246 
247 #define Specialize_name_of_type(Type) \
248  template <> \
249  struct Name_of_type<Type> \
250  { static constexpr char const* value = #Type; };
251 
252 Specialize_name_of_type(char)
253 Specialize_name_of_type(signed char)
254 Specialize_name_of_type(unsigned char)
255 Specialize_name_of_type(short)
256 Specialize_name_of_type(unsigned short)
257 Specialize_name_of_type(int)
258 Specialize_name_of_type(unsigned)
259 Specialize_name_of_type(long)
260 Specialize_name_of_type(unsigned long)
261 Specialize_name_of_type(float)
262 Specialize_name_of_type(double)
263 
264 #undef Specialize_name_of_type
265 
266 } // end namespace detail
267 
268 } // end namespace ge211
269 
std::string
ge211::to_string
std::string to_string(const PRINTABLE &value)
Converts any printable type to a std::string.
Definition: ge211_util.hxx:23
std::rel_ops::operator!=
T operator!=(T... args)
std::unique_ptr::reset
T reset(T... args)
ge211
The game engine namespace.
Definition: ge211.hxx:4
std::nullptr_t
std::addressof
T addressof(T... args)
ge211::geometry::operator*
Dims< COORDINATE > operator*(SCALAR scalar, Dims< COORDINATE > dims)
Multiplies a scalar and a Dims.
Definition: ge211_geometry.hxx:255
ge211::Owned
OBJECT_TYPE * Owned
Type alias to indicate that the given pointer owns its object.
Definition: ge211_util.hxx:14
ge211::events::operator==
bool operator==(Key a, Key b)
Equality for keys.
Definition: ge211_event.hxx:244
std::swap
T swap(T... args)
std::ostringstream
std::free
T free(T... args)
std::ostringstream::str
T str(T... args)
std::unique_ptr
ge211::Borrowed
OBJECT_TYPE * Borrowed
Type alias to indicate that the given pointer does not own its object.
Definition: ge211_util.hxx:19