ctrl-utils
optional.h
1 
10 #if __cplusplus >= 201703L
11 #include <optional> // std::optional
12 #else // __cplusplus
13 
14 #include <cassert> // assert
15 #include <exception> // std::exception
16 
17 #ifndef CTRL_UTILS_OPTIONAL_H_
18 #define CTRL_UTILS_OPTIONAL_H_
19 
20 namespace std {
21 
22 class bad_optional_access : public exception {
23  public:
24  bad_optional_access() = default;
25  virtual const char* what() const noexcept override { return "bad optional access"; }
26  virtual ~bad_optional_access() noexcept = default;
27 };
28 
29 template<typename T>
30 class optional {
31 
32  public:
33 
34  optional() {}
35 
36  optional(const optional<T>& other) : value_(other.value_), has_value_(other.has_value_) {}
37  optional(optional<T>&& other) : value_(std::move(other.value_)), has_value_(other.has_value_) {}
38 
39  optional(const T& value) : value_(value), has_value_(true) {}
40  optional(T&& value) : value_(std::forward<T>(value)), has_value_(true) {}
41 
42  optional& operator=(const optional<T>& other) { value_ = other.value_; has_value_ = other.has_value_; return *this; }
43  optional& operator=(optional<T>&& other) { value_ = std::move(other.value_); has_value_ = other.has_value_; return *this; }
44 
45  optional& operator=(const T& value) { value_ = value; has_value_ = true; return *this; }
46  optional& operator=(T&& value) { value_ = std::forward<T>(value); has_value_ = true; return *this; }
47 
48  const T* operator->() const { assert(has_value_); return &value_; }
49  T* operator->() { assert(has_value_); return &value_; }
50  const T& operator*() const { assert(has_value_); return value_; }
51  T& operator*() { assert(has_value_); return value_; }
52 
53  explicit operator bool() const { return has_value_; }
54  bool has_value() const { return has_value_; }
55 
56  const T& value() const { if (!has_value_) throw std::bad_optional_access(); return value_; }
57  T& value() { if (!has_value_) throw std::bad_optional_access(); return value_; }
58 
59  T value_or(T&& default_value) const { return has_value_ ? value_ : default_value; }
60 
61  void swap(optional& other) { std::swap(value_, other.value_); std::swap(has_value_, other.has_value_); }
62 
63  void reset() { has_value_ = false; }
64 
65  template<typename... Args>
66  T& emplace(Args&&... args) { value_ = T(std::forward<Args>(args)...); has_value_ = true; return value_; }
67 
68  private:
69 
70  T value_;
71  bool has_value_ = false;
72 
73 };
74 
75 template<typename T>
76 bool operator==(const std::optional<T>& lhs, const std::optional<T>& rhs) {
77  return lhs.has_value() == rhs.has_value() && (!lhs.has_value() || lhs.value() == rhs.value());
78 }
79 
80 } // namespace std
81 
82 #endif // CTRL_UTILS_OPTIONAL_H_
83 
84 #endif // __cplusplus
Definition: optional.h:22
Definition: optional.h:30
Definition: chrono.h:15