Spicy
optional-ref.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 //
3 // This was originally inspired by the version in
4 // https://github.com/Chlorie/clu, but it turned into pretty much a rewrite. (That
5 // code comes with an MIT license, FWIW).
6 
7 #pragma once
8 
9 #include <memory>
10 #include <optional>
11 #include <stdexcept>
12 #include <utility>
13 
14 namespace hilti {
15 
21 template<typename T>
22 class optional_ref {
23 public:
24  using nonConstT = typename std::remove_const<T>::type;
25 
26  optional_ref() = default;
27  optional_ref(const optional_ref<T>& other) = default;
28  optional_ref(optional_ref<T>&& other) = default;
29  optional_ref(std::nullopt_t) {}
30  optional_ref(T& other) : _ptr(&other) {}
31  optional_ref(T&& other) = delete; // to avoid easy mistakes
32 
33  bool has_value() const { return _ptr; }
34 
35  T& value() const {
36  if ( ! _ptr )
37  throw std::bad_optional_access();
38 
39  return *_ptr;
40  }
41 
42  T& value_or(T& default_) const { return _ptr ? *_ptr : default_; }
43  void reset() { _ptr = nullptr; }
44 
45  T* operator->() const { return _ptr; }
46  T& operator*() const { return *_ptr; }
47 
48  optional_ref& operator=(const optional_ref<T>& other) = default;
49  optional_ref& operator=(optional_ref<T>&& other) = default;
50 
51  optional_ref& operator=(std::nullopt_t) {
52  _ptr = nullptr;
53  return *this;
54  }
55 
56  optional_ref& operator=(T& t) {
57  _ptr = &t;
58  return *this;
59  }
60 
61  optional_ref& operator=(T&& t) = delete; // to avoid easy mistakes
62 
63  explicit operator bool() const { return _ptr; }
64 
65  bool operator==(const optional_ref<T>& other) const {
66  if ( has_value() && other.has_value() )
67  return value() == other.value();
68 
69  return ! (has_value() || other.has_value());
70  }
71 
72  bool operator!=(const optional_ref<T>& other) const { return ! (*this == other); }
73 
74  operator std::optional<nonConstT>() const {
75  if ( has_value() )
76  return value();
77  else
78  return std::nullopt;
79  }
80 
81 private:
82  T* _ptr = nullptr;
83 };
84 
85 } // namespace hilti
Definition: optional-ref.h:22