| 32 | // in its constructor. |
| 33 | template <typename T> |
| 34 | class optional_ref final { |
| 35 | public: |
| 36 | static_assert(!std::is_reference_v<T>, "T must not be a reference."); |
| 37 | static_assert(!std::is_same_v<absl::nullopt_t, std::remove_cv_t<T>>, |
| 38 | "optional_ref<absl::nullopt_t> is not allowed."); |
| 39 | static_assert(!std::is_same_v<absl::in_place_t, std::remove_cv_t<T>>, |
| 40 | "optional_ref<absl::in_place_t> is not allowed."); |
| 41 | |
| 42 | using value_type = T; |
| 43 | |
| 44 | optional_ref() = default; |
| 45 | |
| 46 | // NOLINTNEXTLINE(google-explicit-constructor) |
| 47 | constexpr optional_ref(absl::nullopt_t) : optional_ref() {} |
| 48 | |
| 49 | // NOLINTNEXTLINE(google-explicit-constructor) |
| 50 | constexpr optional_ref(T& value ABSL_ATTRIBUTE_LIFETIME_BOUND) |
| 51 | : value_(std::addressof(value)) {} |
| 52 | |
| 53 | template < |
| 54 | typename U, |
| 55 | typename = std::enable_if_t<std::conjunction_v< |
| 56 | std::is_const<T>, std::is_same<std::decay_t<U>, std::decay_t<T>>>>> |
| 57 | // NOLINTNEXTLINE(google-explicit-constructor) |
| 58 | constexpr optional_ref( |
| 59 | const absl::optional<U>& value ABSL_ATTRIBUTE_LIFETIME_BOUND) |
| 60 | : value_(value.has_value() ? std::addressof(*value) : nullptr) {} |
| 61 | |
| 62 | template <typename U, typename = std::enable_if_t< |
| 63 | std::is_same_v<std::decay_t<U>, std::decay_t<T>>>> |
| 64 | // NOLINTNEXTLINE(google-explicit-constructor) |
| 65 | constexpr optional_ref(absl::optional<U>& value ABSL_ATTRIBUTE_LIFETIME_BOUND) |
| 66 | : value_(value.has_value() ? std::addressof(*value) : nullptr) {} |
| 67 | |
| 68 | template < |
| 69 | typename U, |
| 70 | typename = std::enable_if_t<std::conjunction_v< |
| 71 | std::negation<std::is_same<U, T>>, |
| 72 | std::is_convertible<std::add_pointer_t<U>, std::add_pointer_t<T>>>>> |
| 73 | // NOLINTNEXTLINE(google-explicit-constructor) |
| 74 | constexpr optional_ref(const optional_ref<U>& other) : value_(other.value_) {} |
| 75 | |
| 76 | optional_ref(const optional_ref<T>&) = default; |
| 77 | |
| 78 | optional_ref<T>& operator=(const optional_ref<T>&) = delete; |
| 79 | |
| 80 | constexpr bool has_value() const { return value_ != nullptr; } |
| 81 | |
| 82 | constexpr explicit operator bool() const { return has_value(); } |
| 83 | |
| 84 | constexpr T& value() const { |
| 85 | return ABSL_PREDICT_TRUE(has_value()) |
| 86 | ? *value_ |
| 87 | // Replicate the same error logic as in `absl::optional`'s |
| 88 | // `value()`. It either throws an exception or aborts the |
| 89 | // program. We intentionally ignore the return value of |
| 90 | // the constructed optional's value as we only need to run |
| 91 | // the code for error checking. |