Simulant  21.12-194
A portable game engine for Windows, OSX, Linux, Dreamcast, and PSP
optional.h
1 #pragma once
2 #include <cstddef>
3 #include <cassert>
4 #include <utility>
5 #include <cstdint>
6 
7 namespace smlt {
8 
9 /* When all compilers support the true optional class we can delete this. This exists largely for compatibility
10  * with old GCC for the Dreamcast port */
11 
12 template<typename T>
13 class optional {
14 public:
15  optional() = default;
16 
17  ~optional() {
18  reset();
19  }
20 
21  template<typename U>
22  optional(optional<U>&& other) {
23  auto src = other.value_ptr();
24  if(src) {
25  set_value(std::move(*src));
26  } else {
27  reset();
28  }
29  }
30 
31  optional(const T& value) {
32  set_value(value);
33  }
34 
35  optional(T&& value) {
36  set_value(std::move(value));
37  }
38 
39  optional(const optional<T>& rhs) {
40  if(rhs.has_value()) {
41  set_value(rhs.value());
42  }
43  }
44 
45  optional& operator=(const optional& other) {
46  if(other.has_value()) {
47  set_value(other.value());
48  } else {
49  reset();
50  }
51 
52  return *this;
53  }
54 
55  explicit operator bool() const {
56  return has_value();
57  }
58 
59  bool has_value() const { return has_value_; }
60 
61  const T& value() const {
62  assert(has_value());
63  return *value_ptr();
64  }
65 
66  T& value() {
67  assert(has_value());
68  return *value_ptr();
69  }
70 
71  T value_or(T&& def) const {
72  bool(*this) ? **this : static_cast<T>(std::forward<T>(def));
73  }
74 
75  T value_or(T&& def) {
76  return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<T>(def));
77  }
78 
79  const T* operator->() const {
80  assert(has_value());
81  return value_ptr();
82  }
83 
84  T* operator->() {
85  assert(has_value());
86  return value_ptr();
87  }
88 
89  const T& operator*() const {
90  assert(has_value());
91  return *value_ptr();
92  }
93 
94  T& operator*() {
95  assert(has_value());
96  return *value_ptr();
97  }
98 
99 private:
100  uint8_t data_[sizeof(T)] __attribute__((aligned(8)));
101  bool has_value_ = false;
102 
103  T* value_ptr() const {
104  return (has_value()) ? (T*) (data_) : nullptr;
105  }
106 
107  void set_value(const T& value) {
108  if(has_value()) {
109  reset();
110  }
111 
112  new (data_) T();
113  has_value_ = true;
114  *(value_ptr()) = value;
115  }
116 
117  void set_value(T&& value) {
118  if(has_value()) {
119  // We destroy the current value if we have one
120  reset();
121  }
122 
123  new (data_) T(std::move(value));
124  has_value_ = true;
125  }
126 
127  void reset() {
128  T* v = value_ptr();
129  if(v) {
130  has_value_ = false;
131  v->~T();
132  }
133  }
134 };
135 
136 
137 }
smlt
Definition: animation.cpp:25
smlt::optional
Definition: optional.h:13