Hermes
optional.h
Go to the documentation of this file.
1 
37 #ifndef HERMES_HERMES_COMMON_OPTIONAL_H
38 #define HERMES_HERMES_COMMON_OPTIONAL_H
39 
40 #include <hermes/common/defs.h>
41 #include <iostream>
42 
43 namespace hermes {
44 
45 // *********************************************************************************************************************
46 // Optional
47 // *********************************************************************************************************************
64 template<typename T>
65 class Optional {
66 public:
67  // *******************************************************************************************************************
68  // CONSTRUCTORS
69  // *******************************************************************************************************************
70  // new
75  HERMES_DEVICE_CALLABLE explicit Optional(const T &v) : has_value_(true) {
76  new(reinterpret_cast<T *>(&value_)) T(v);
77  }
80  HERMES_DEVICE_CALLABLE explicit Optional(T &&v) : has_value_(true) {
81  new(reinterpret_cast<T *>(&value_)) T(std::move(v));
82  }
85  // assignment
89  *this = other;
90  }
94  *this = std::move(other);
95  }
96  // *******************************************************************************************************************
97  // OPERATORS
98  // *******************************************************************************************************************
101  HERMES_DEVICE_CALLABLE explicit operator bool() const { return has_value_; }
102  // assignment
107  reset();
108  if (other.has_value_) {
109  has_value_ = true;
110  new(reinterpret_cast<T *>(&value_)) T(other.value());
111  }
112  return *this;
113  }
118  reset();
119  if (other.has_value_) {
120  has_value_ = true;
121  new(reinterpret_cast<T *>(&value_)) T(std::move(other.value()));
122  }
123  return *this;
124  }
129  reset();
130  new(reinterpret_cast<T *>(&value_)) T(v);
131  has_value_ = true;
132  return *this;
133  }
138  reset();
139  new(reinterpret_cast<T *>(&value_)) T(std::move(v));
140  has_value_ = true;
141  return *this;
142  }
143  // access
149  HERMES_DEVICE_CALLABLE const T *operator->() const { return &value(); }
155  HERMES_DEVICE_CALLABLE const T &operator*() const { return value(); }
156  // *******************************************************************************************************************
157  // METHODS
158  // *******************************************************************************************************************
161  if (has_value_) {
162  value().~T();
163  has_value_ = false;
164  }
165  }
168  [[nodiscard]] HERMES_DEVICE_CALLABLE bool hasValue() const { return has_value_; }
169  // access
173  HERMES_DEVICE_CALLABLE T valueOr(const T &v) const { return has_value_ ? value() : v; }
177  return *reinterpret_cast<T *>(&value_);
178  }
181  HERMES_DEVICE_CALLABLE const T &value() const {
182  return *reinterpret_cast<const T *>(&value_);
183  }
184 private:
185  bool has_value_{false};
186  typename std::aligned_storage<sizeof(T), alignof(T)>::type value_;
187 };
188 
189 // *********************************************************************************************************************
190 // IO
191 // *********************************************************************************************************************
197 template<typename T>
198 inline std::ostream &operator<<(std::ostream &o, const Optional<T> &optional) {
199  if (optional.hasValue())
200  return o << "Optional<" << typeid(T).name() << "> = " << optional.hasValue();
201  return o << "Optional<" << typeid(T).name() << "> = [no value]";
202 }
203 
204 }
205 
206 #endif //HERMES_HERMES_COMMON_OPTIONAL_H
207 
Works just as std::optional, but supports GPU code. It may contain a value or not.
Definition: optional.h:65
HERMES_DEVICE_CALLABLE const T & operator*() const
Gets value const reference.
Definition: optional.h:155
HERMES_DEVICE_CALLABLE Optional & operator=(const Optional &other)
Copy assignment.
Definition: optional.h:106
HERMES_DEVICE_CALLABLE bool hasValue() const
Checks if this holds a value.
Definition: optional.h:168
HERMES_DEVICE_CALLABLE T & operator*()
Gets value reference.
Definition: optional.h:152
HERMES_DEVICE_CALLABLE Optional(const Optional &other)
Copy constructor.
Definition: optional.h:88
HERMES_DEVICE_CALLABLE Optional & operator=(T &&v)
Move value assignment.
Definition: optional.h:137
HERMES_DEVICE_CALLABLE const T * operator->() const
Gets const value pointer.
Definition: optional.h:149
HERMES_DEVICE_CALLABLE Optional & operator=(Optional &&other) noexcept
Move assinment.
Definition: optional.h:117
HERMES_DEVICE_CALLABLE const T & value() const
Gets value's const reference.
Definition: optional.h:181
HERMES_DEVICE_CALLABLE Optional & operator=(const T &v)
Value assignment.
Definition: optional.h:128
HERMES_DEVICE_CALLABLE T & value()
Gets value's reference.
Definition: optional.h:176
HERMES_DEVICE_CALLABLE void reset()
Destroys stored value (if present)
Definition: optional.h:160
HERMES_DEVICE_CALLABLE Optional(T &&v)
Move value constructor.
Definition: optional.h:80
HERMES_DEVICE_CALLABLE Optional(const T &v)
Value constructor.
Definition: optional.h:75
HERMES_DEVICE_CALLABLE Optional()
Default constructor.
Definition: optional.h:72
HERMES_DEVICE_CALLABLE Optional(Optional &&other) noexcept
Move constructor.
Definition: optional.h:93
HERMES_DEVICE_CALLABLE T valueOr(const T &v) const
Gets value copy (if present)
Definition: optional.h:173
HERMES_DEVICE_CALLABLE T * operator->()
Gets value pointer.
Definition: optional.h:146
Data type definitions.
#define HERMES_DEVICE_CALLABLE
Specifies that the function can be called from both host and device sides.
Definition: defs.h:45