Face Engine SDK  4.6.0
A face detection, recognition and tracking engine.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Optional.h
1 #pragma once
2 
3 #include <type_traits>
4 #include <assert.h>
5 #include <stdexcept>
6 
7 namespace fsdk {
8 
9  struct In_place_t {
10  explicit In_place_t() = default;
11  };
12 
13  template<typename BaseType>
14  class Optional {
15  using Storage = typename std::aligned_storage<sizeof(BaseType), std::alignment_of<BaseType>::value>::type;
16 
17  Storage m_storage;
18  bool m_valid = false;
19 
20  public:
22 
23  Optional() = default;
24 
25  ~Optional() {
26  reset();
27  }
28 
29  Optional(const Optional &src) : m_valid(src.m_valid) {
30  if (src.m_valid) {
31  new(&m_storage) BaseType(*src);
32  }
33  }
34 
35  Optional(Optional &&src) : m_valid(src.m_valid) {
36  if (src.m_valid) {
37  new(&m_storage) BaseType(std::move(*src));
38  }
39  }
40 
41  template<typename U = BaseType, typename =
42  typename std::enable_if<
43  std::is_constructible<BaseType, U &&>::value &&
44  !(std::is_same<typename std::decay<U>::type, self_type>::value)
45  >::type
46  >
47  Optional(U &&value) : m_valid(true) {
48  new(&m_storage) BaseType(std::forward<U>(value));
49  }
50 
51  template<typename... Args, typename = typename std::enable_if<std::is_constructible<BaseType, Args...>::value>::type>
52  explicit Optional(In_place_t tag, Args &&... args) : m_valid(true) {
53  new(&m_storage) BaseType(std::forward<Args>(args)...);
54  }
55 
56  Optional &operator=(Optional &&src) noexcept {
57  if (src.m_valid) {
58  if (m_valid) {
59  **this = std::move(*src);
60  } else {
61  new(&m_storage) BaseType(std::move(*src));
62  m_valid = true;
63  }
64  } else if (m_valid) {
65  reinterpret_cast<BaseType *>(&m_storage)->~BaseType();
66  m_valid = false;
67  }
68 
69  return *this;
70  }
71 
72  Optional &operator=(const Optional &src) {
73  if (src.m_valid) {
74  if (m_valid) {
75  **this = *src;
76  } else {
77  new(&m_storage) BaseType(*src);
78  m_valid = true;
79  }
80  } else if (m_valid) {
81  reinterpret_cast<BaseType *>(&m_storage)->~BaseType();
82  m_valid = false;
83  }
84 
85  return *this;
86  }
87 
88  template<typename U = BaseType, typename =
89  typename std::enable_if<
90  !std::is_same<typename std::decay<U>::type, self_type>::value &&
91  std::is_constructible<BaseType, U>::value &&
92  std::is_assignable<BaseType &, U>::value
93  >::type>
94  Optional &operator=(U &&value) {
95  if (m_valid) {
96  **this = std::forward<U>(value);
97  } else {
98  new(&m_storage) BaseType(std::forward<U>(value));
99  m_valid = true;
100  }
101 
102  return *this;
103  }
104 
105  void reset() {
106  if (m_valid) {
107  (**this).BaseType::~BaseType();
108  m_valid = false;
109  }
110  }
111 
112  constexpr explicit operator bool() const {
113  return m_valid;
114  }
115 
116  constexpr bool has_value() const {
117  return m_valid;
118  }
119 
120  constexpr bool valid() const {
121  return has_value();
122  }
123 
124  BaseType &operator*() &{
125  assert(m_valid);
126  return *reinterpret_cast<BaseType *>(&m_storage);
127  }
128 
129  const BaseType &operator*() const &{
130  assert(m_valid);
131  return *reinterpret_cast<const BaseType *>(&m_storage);
132  }
133 
134  BaseType &&operator*() &&{
135  assert(m_valid);
136  return std::move(*reinterpret_cast<BaseType *>(&m_storage));
137  }
138 
139  const BaseType &&operator*() const &&{
140  assert(m_valid);
141  return std::move(*reinterpret_cast<BaseType *>(&m_storage));
142  }
143 
144  BaseType *operator->() {
145  assert(m_valid);
146  return reinterpret_cast<BaseType *>(&m_storage);
147  }
148 
149  const BaseType *operator->() const {
150  assert(m_valid);
151  return reinterpret_cast<const BaseType *>(&m_storage);
152  }
153 
154  BaseType &value() {
155  if (!has_value()) {
156  throw std::logic_error("bad_optional_access");
157  }
158 
159  return **this;
160  }
161 
162  const BaseType &value() const {
163  if (!has_value()) {
164  throw std::logic_error("bad_optional_access");
165  }
166 
167  return **this;
168  }
169 
170  template<typename U>
171  BaseType value_or(U &&default_value) &&{
172  return has_value() ? std::move(**this) : static_cast<BaseType>(std::forward<U>(default_value));
173  }
174 
175  template<typename U>
176  const BaseType value_or(U &&default_value) const &{
177  return has_value() ? **this : static_cast<BaseType>(std::forward<U>(default_value));
178  }
179 
180  template<typename... Args>
181  BaseType &emplace(Args &&... args) {
182  reset();
183 
184  new(&m_storage) BaseType(std::forward<Args>(args)...);
185  m_valid = true;
186 
187  return **this;
188  }
189  };
190 
191  template<typename T>
192  Optional<typename std::decay<T>::type> make_optional(T &&val) {
193  return Optional<typename std::decay<T>::type>(std::forward<T>(val));
194  }
195 
196  template<typename T, typename... Args>
197  Optional<T> make_optional(Args &&... args) {
198  return Optional<T>(In_place_t{}, std::forward<Args>(args)...);
199  }
200 }
Definition: Optional.h:14
Definition: Optional.h:9