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