Spicy
optional-ref.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 //
3 // This was originally inspired by similar code part of
4 // https://github.com/Chlorie/clu, but it turned into pretty much a rewrite.
5 // (FWIW, that code comes with an MIT license.)
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) noexcept = 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  ~optional_ref() = default;
33 
34  bool has_value() const { return _ptr != nullptr; }
35 
36  T& value() const {
37  if ( ! _ptr )
38  throw std::bad_optional_access();
39 
40  return *_ptr;
41  }
42 
43  T& value_or(T& default_) const { return _ptr ? *_ptr : default_; }
44  void reset() { _ptr = nullptr; }
45 
46  T* operator->() const { return _ptr; }
47  T& operator*() const { return *_ptr; }
48 
49  optional_ref& operator=(const optional_ref<T>& other) = default;
50  optional_ref& operator=(optional_ref<T>&& other) noexcept = default;
51 
52  optional_ref& operator=(std::nullopt_t) {
53  _ptr = nullptr;
54  return *this;
55  }
56 
57  optional_ref& operator=(T& t) {
58  _ptr = &t;
59  return *this;
60  }
61 
62  optional_ref& operator=(T&& t) = delete; // to avoid easy mistakes
63 
64  explicit operator bool() const { return _ptr; }
65 
66  bool operator==(const optional_ref<T>& other) const {
67  if ( has_value() && other.has_value() )
68  return value() == other.value();
69 
70  return ! (has_value() || other.has_value());
71  }
72 
73  bool operator!=(const optional_ref<T>& other) const { return ! (*this == other); }
74 
75  operator std::optional<nonConstT>() const {
76  if ( has_value() )
77  return value();
78  else
79  return std::nullopt;
80  }
81 
82 private:
83  T* _ptr = nullptr;
84 };
85 
86 } // namespace hilti
Definition: optional-ref.h:22