Add absl::optional_ref<T>

PiperOrigin-RevId: 872459397
Change-Id: Ib2a3265c46c1ceca31190f5d4722bde06b59eeb4
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake
index 0fa06af..60a4ec2 100644
--- a/CMake/AbseilDll.cmake
+++ b/CMake/AbseilDll.cmake
@@ -453,6 +453,7 @@
   "types/any.h"
   "types/compare.h"
   "types/optional.h"
+  "types/optional_ref.h"
   "types/span.h"
   "types/internal/span.h"
   "types/variant.h"
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index cac5e4b..a52c358 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -164,3 +164,29 @@
         "@googletest//:gtest_main",
     ],
 )
+
+cc_library(
+    name = "optional_ref",
+    hdrs = ["optional_ref.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:config",
+        "//absl/base:core_headers",
+    ],
+)
+
+cc_test(
+    name = "optional_ref_test",
+    size = "small",
+    srcs = ["optional_ref_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    deps = [
+        ":optional_ref",
+        "//absl/base:config",
+        "//absl/log",
+        "//absl/strings",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt
index 20a7e90..75dd07d 100644
--- a/absl/types/CMakeLists.txt
+++ b/absl/types/CMakeLists.txt
@@ -154,6 +154,34 @@
     GTest::gmock_main
 )
 
+absl_cc_library(
+  NAME
+    internal_optional_ref
+  HDRS
+    "optional_ref.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    optional_ref_test
+  SRCS
+    "optional_ref_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::base
+    absl::config
+    absl::internal_optional_ref
+    absl::strings
+    GTest::gmock_main
+)
+
 # Deprecated empty library.
 # Clients should remove this dependency.
 absl_cc_library(
diff --git a/absl/types/optional_ref.h b/absl/types/optional_ref.h
new file mode 100644
index 0000000..fb21333
--- /dev/null
+++ b/absl/types/optional_ref.h
@@ -0,0 +1,294 @@
+// Copyright 2026 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: optional_ref.h
+// -----------------------------------------------------------------------------
+//
+// `optional_ref<T>` provides a `std::optional`-like interface around `T*`.
+// It is similar to C++26's `std::optional<T&>`, but with slight enhancements,
+// such as the fact that it permits construction from rvalues. That is, it
+// relaxes the std::reference_constructs_from_temporary constraint. Its intent
+// is to make it easier for functions to accept nullable object addresses,
+// regardless of whether or not they point to temporaries.
+//
+// It can be constructed in the following ways:
+//   * optional_ref<T> ref;
+//   * optional_ref<T> ref = std::nullopt;
+//   * T foo; optional_ref<T> ref = foo;
+//   * std::optional<T> foo; optional_ref<T> ref = foo;
+//   * T* foo = ...; optional_ref<T> ref = foo;
+//   * optional_ref<T> foo; optional_ref<const T> ref = foo;
+//
+// Since it is trivially copyable and destructible, it should be passed by
+// value.
+//
+// Other properties:
+//   * Assignment is not allowed. Example:
+//       optional_ref<int> ref;
+//       // Compile error.
+//       ref = 2;
+//
+//   * operator bool() is intentionally not defined, as it would be error prone
+//     for optional_ref<bool>.
+//
+// Example usage, assuming some type `T` that is expensive to copy:
+//   void ProcessT(optional_ref<const T> input) {
+//     if (!input.has_value()) {
+//       // Handle empty case.
+//       return;
+//     }
+//     const T& val = *input;
+//     // Do something with val.
+//   }
+//
+//   ProcessT(std::nullopt);
+//   ProcessT(BuildT());
+
+#ifndef ABSL_TYPES_OPTIONAL_REF_H_
+#define ABSL_TYPES_OPTIONAL_REF_H_
+
+#include <cstddef>
+#include <memory>
+#include <optional>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/macros.h"
+#include "absl/base/optimization.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+template <typename T>
+class optional_ref {
+  template <typename U>
+  using EnableIfConvertibleFrom =
+      std::enable_if_t<std::is_convertible_v<U*, T*>>;
+
+ public:
+  using value_type = T;
+
+  constexpr optional_ref() : ptr_(nullptr) {}
+  constexpr optional_ref(  // NOLINT(google-explicit-constructor)
+      std::nullopt_t)
+      : ptr_(nullptr) {}
+
+  // Constructor given a concrete value.
+  constexpr optional_ref(  // NOLINT(google-explicit-constructor)
+      T& input ABSL_ATTRIBUTE_LIFETIME_BOUND)
+      : ptr_(std::addressof(input)) {}
+
+  // Constructors given an existing std::optional value.
+  // Templated on the input optional's type to avoid creating a temporary.
+  template <typename U, typename = EnableIfConvertibleFrom<const U>>
+  constexpr optional_ref(  // NOLINT(google-explicit-constructor)
+      const std::optional<U>& input ABSL_ATTRIBUTE_LIFETIME_BOUND)
+      : ptr_(input.has_value() ? std::addressof(*input) : nullptr) {}
+  template <typename U, typename = EnableIfConvertibleFrom<U>>
+  constexpr optional_ref(  // NOLINT(google-explicit-constructor)
+      std::optional<U>& input ABSL_ATTRIBUTE_LIFETIME_BOUND)
+      : ptr_(input.has_value() ? std::addressof(*input) : nullptr) {}
+
+  // Constructor given a T*, where nullptr indicates empty/absent.
+  constexpr optional_ref(  // NOLINT(google-explicit-constructor)
+      T* input ABSL_ATTRIBUTE_LIFETIME_BOUND)
+      : ptr_(input) {}
+
+  // Don't allow naked nullptr as input, as this creates confusion in the case
+  // of optional_ref<T*>. Use std::nullopt instead to create an empty
+  // optional_ref.
+  constexpr optional_ref(  // NOLINT(google-explicit-constructor)
+      std::nullptr_t) = delete;
+
+  // Copying is allowed.
+  optional_ref(const optional_ref<T>&) = default;
+  // Assignment is not allowed.
+  optional_ref<T>& operator=(const optional_ref<T>&) = delete;
+
+  // Conversion from optional_ref<U> is allowed iff U* is convertible to T*.
+  // (Note this also allows non-const to const conversions.)
+  template <typename U, typename = EnableIfConvertibleFrom<U>>
+  constexpr optional_ref(  // NOLINT(google-explicit-constructor)
+      optional_ref<U> input)
+      : ptr_(input.as_pointer()) {}
+
+  // Determines whether the `optional_ref` contains a value. Returns `false` if
+  // and only if `*this` is empty.
+  constexpr bool has_value() const { return ptr_ != nullptr; }
+
+  // Returns a reference to an `optional_ref`s underlying value. The constness
+  // and lvalue/rvalue-ness of the `optional_ref` is preserved to the view of
+  // the `T` sub-object. Throws the same error as `std::optional`'s `value()`
+  // when the `optional_ref` is empty.
+  constexpr T& value() const {
+    return ABSL_PREDICT_TRUE(ptr_ != nullptr)
+               ? *ptr_
+               // Replicate the same error logic as in `std::optional`'s
+               // `value()`. It either throws an exception or aborts the
+               // program. We intentionally ignore the return value of
+               // the constructed optional's value as we only need to run
+               // the code for error checking.
+               : ((void)std::optional<T>().value(), *ptr_);
+  }
+
+  // Returns the value iff *this has a value, otherwise returns `default_value`.
+  template <typename U>
+  constexpr T value_or(U&& default_value) const {
+    // Instantiate std::optional<T>::value_or(U) to trigger its static_asserts.
+    if (false) {
+      // We use `std::add_const_t` here since just using `const` makes MSVC
+      // complain about the syntax.
+      (void)std::add_const_t<std::optional<T>>{}.value_or(
+          std::forward<U>(default_value));
+    }
+    return ptr_ != nullptr ? *ptr_
+                           : static_cast<T>(std::forward<U>(default_value));
+  }
+
+  // Accesses the underlying `T` value of an `optional_ref`. If the
+  // `optional_ref` is empty, behavior is undefined.
+  constexpr T& operator*() const {
+    ABSL_HARDENING_ASSERT(ptr_ != nullptr);
+    return *ptr_;
+  }
+  constexpr T* operator->() const {
+    ABSL_HARDENING_ASSERT(ptr_ != nullptr);
+    return ptr_;
+  }
+
+  // Convenience function to represent the `optional_ref` as a `T*` pointer.
+  constexpr T* as_pointer() const { return ptr_; }
+  // Convenience function to represent the `optional_ref` as an `optional`,
+  // which incurs a copy when the `optional_ref` is non-empty. The template type
+  // allows for implicit type conversion; example:
+  //   optional_ref<std::string> a = ...;
+  //   std::optional<std::string_view> b = a.as_optional<std::string_view>();
+  template <typename U = std::decay_t<T>>
+  constexpr std::optional<U> as_optional() const {
+    if (ptr_ == nullptr) return std::nullopt;
+    return *ptr_;
+  }
+
+ private:
+  T* const ptr_;
+
+  // T constraint checks.  You can't have an optional of nullopt_t or
+  // in_place_t.
+  static_assert(!std::is_same_v<std::nullopt_t, std::remove_cv_t<T>>,
+                "optional_ref<nullopt_t> is not allowed.");
+  static_assert(!std::is_same_v<std::in_place_t, std::remove_cv_t<T>>,
+                "optional_ref<in_place_t> is not allowed.");
+};
+
+// Template type deduction guides:
+
+template <typename T>
+optional_ref(const T&) -> optional_ref<const T>;
+template <typename T>
+optional_ref(T&) -> optional_ref<T>;
+
+template <typename T>
+optional_ref(const std::optional<T>&) -> optional_ref<const T>;
+template <typename T>
+optional_ref(std::optional<T>&) -> optional_ref<T>;
+
+template <typename T>
+optional_ref(T*) -> optional_ref<T>;
+
+namespace optional_ref_internal {
+
+// This is a C++-11 compatible version of std::equality_comparable_with that
+// only requires `t == u` is a valid boolean expression.
+//
+// We still need this for a couple reasons:
+// -  As of 2026-02-13, Abseil supports C++17.
+//  - Even for targets that are built with the default toolchain, using
+//    std::equality_comparable_with gives us an error due to mutual recursion
+//    between its definition and our definition of operator==.
+//
+template <typename T, typename U>
+using enable_if_equality_comparable_t = std::enable_if_t<std::is_convertible_v<
+    decltype(std::declval<T>() == std::declval<U>()), bool>>;
+
+}  // namespace optional_ref_internal
+
+// Compare an optional referenced value to std::nullopt.
+
+template <typename T>
+constexpr bool operator==(optional_ref<T> a, std::nullopt_t) {
+  return !a.has_value();
+}
+template <typename T>
+constexpr bool operator==(std::nullopt_t, optional_ref<T> b) {
+  return !b.has_value();
+}
+template <typename T>
+constexpr bool operator!=(optional_ref<T> a, std::nullopt_t) {
+  return a.has_value();
+}
+template <typename T>
+constexpr bool operator!=(std::nullopt_t, optional_ref<T> b) {
+  return b.has_value();
+}
+
+// Compare two optional referenced values. Note, this does not test that the
+// contained `ptr_`s are equal. If the caller wants "shallow" reference equality
+// semantics, they should use `as_pointer()` explicitly.
+
+template <typename T, typename U>
+constexpr bool operator==(optional_ref<T> a, optional_ref<U> b) {
+  return a.has_value() ? *a == b : !b.has_value();
+}
+
+// Compare an optional referenced value to a non-optional value.
+
+template <
+    typename T, typename U,
+    typename = optional_ref_internal::enable_if_equality_comparable_t<T, U>>
+constexpr bool operator==(const T& a, optional_ref<U> b) {
+  return b.has_value() && a == *b;
+}
+template <
+    typename T, typename U,
+    typename = optional_ref_internal::enable_if_equality_comparable_t<T, U>>
+constexpr bool operator==(optional_ref<T> a, const U& b) {
+  return b == a;
+}
+
+// Inequality operators, as above.
+
+template <typename T, typename U>
+constexpr bool operator!=(optional_ref<T> a, optional_ref<U> b) {
+  return !(a == b);
+}
+template <
+    typename T, typename U,
+    typename = optional_ref_internal::enable_if_equality_comparable_t<T, U>>
+constexpr bool operator!=(optional_ref<T> a, const U& b) {
+  return !(a == b);
+}
+template <
+    typename T, typename U,
+    typename = optional_ref_internal::enable_if_equality_comparable_t<T, U>>
+constexpr bool operator!=(const T& a, optional_ref<U> b) {
+  return !(a == b);
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_TYPES_OPTIONAL_REF_H_
diff --git a/absl/types/optional_ref_test.cc b/absl/types/optional_ref_test.cc
new file mode 100644
index 0000000..dda1624
--- /dev/null
+++ b/absl/types/optional_ref_test.cc
@@ -0,0 +1,370 @@
+// Copyright 2026 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/types/optional_ref.h"
+
+#include <cstddef>
+#include <memory>
+#include <optional>
+#include <string>
+#include <string_view>
+#include <type_traits>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/log/log.h"
+#include "absl/strings/str_cat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace {
+
+using ::testing::Optional;
+using ::testing::Pointee;
+
+TEST(OptionalRefTest, SimpleType) {
+  int val = 5;
+  optional_ref<int> ref = optional_ref(val);
+  optional_ref<int> empty_ref = std::nullopt;
+  EXPECT_THAT(ref, Optional(5));
+  EXPECT_TRUE(ref.has_value());
+  EXPECT_EQ(*ref, val);
+  EXPECT_EQ(ref.value(), val);
+  EXPECT_EQ(ref, ref);
+  EXPECT_EQ(ref, val);
+  EXPECT_EQ(val, ref);
+  EXPECT_NE(ref, empty_ref);
+  EXPECT_NE(empty_ref, ref);
+}
+
+TEST(OptionalRefTest, SimpleConstType) {
+  const int val = 5;
+  optional_ref<const int> ref = optional_ref(val);
+  EXPECT_THAT(ref, Optional(5));
+}
+
+TEST(OptionalRefTest, DefaultConstructed) {
+  optional_ref<int> ref;
+  EXPECT_EQ(ref, std::nullopt);
+  EXPECT_EQ(std::nullopt, ref);
+}
+
+TEST(OptionalRefTest, EmptyOptional) {
+  auto ref = optional_ref<int>(std::nullopt);
+  EXPECT_EQ(ref, std::nullopt);
+  EXPECT_EQ(std::nullopt, ref);
+}
+
+TEST(OptionalRefTest, OptionalType) {
+  const std::optional<int> val = 5;
+  optional_ref<const int> ref = val;
+  EXPECT_THAT(ref, Optional(5));
+  EXPECT_EQ(ref.as_pointer(), &*val);
+
+  const std::optional<int> empty;
+  optional_ref<const int> empty_ref = empty;
+  EXPECT_EQ(empty_ref, std::nullopt);
+
+  // Cannot make non-const reference to const optional.
+  static_assert(
+      !std::is_convertible_v<const std::optional<int>&, optional_ref<int>>);
+}
+
+TEST(OptionalRefTest, NonConstOptionalType) {
+  std::optional<int> val = 5;
+  optional_ref<int> ref = val;
+  EXPECT_THAT(ref, Optional(5));
+  EXPECT_EQ(ref.as_pointer(), &*val);
+
+  std::optional<int> empty;
+  optional_ref<int> empty_ref = empty;
+  EXPECT_EQ(empty_ref, std::nullopt);
+}
+
+TEST(OptionalRefTest, NonConstOptionalTypeToConstRef) {
+  std::optional<int> val = 5;
+  optional_ref<const int> ref = val;
+  EXPECT_THAT(ref, Optional(5));
+  EXPECT_EQ(ref.as_pointer(), &*val);
+
+  std::optional<int> empty;
+  optional_ref<const int> empty_ref = empty;
+  EXPECT_EQ(empty_ref, std::nullopt);
+}
+
+TEST(OptionalRefTest, NonConstOptionalWithConstValueType) {
+  std::optional<const int> val = 5;
+  optional_ref<const int> ref = val;
+  EXPECT_THAT(ref, Optional(5));
+  EXPECT_EQ(ref.as_pointer(), &*val);
+
+  std::optional<const int> empty;
+  optional_ref<const int> empty_ref = empty;
+  EXPECT_EQ(empty_ref, std::nullopt);
+
+  // Not possible to convert to non-const reference.
+  static_assert(
+      !std::is_convertible_v<std::optional<const int>&, optional_ref<int>>);
+}
+
+class TestInterface {};
+class TestDerivedClass : public TestInterface {};
+
+TEST(OptionalRefTest, BaseDerivedConvertibleOptionalType) {
+  const std::optional<TestDerivedClass> dc = TestDerivedClass{};
+  optional_ref<const TestInterface> ref = dc;
+  EXPECT_NE(ref, std::nullopt);
+  EXPECT_EQ(ref.as_pointer(), &*dc);
+
+  const std::optional<TestDerivedClass> empty;
+  optional_ref<const TestInterface> empty_ref = empty;
+  EXPECT_EQ(empty_ref, std::nullopt);
+
+  // Not possible in the other direction.
+  static_assert(!std::is_convertible_v<const std::optional<TestInterface>&,
+                                       optional_ref<const TestDerivedClass>>);
+  static_assert(!std::is_convertible_v<const std::optional<TestDerivedClass>&,
+                                       optional_ref<TestInterface>>);
+}
+
+TEST(OptionalRefTest, NonConstBaseDerivedConvertibleOptionalType) {
+  std::optional<TestDerivedClass> dc = TestDerivedClass{};
+  optional_ref<TestInterface> ref = dc;
+  EXPECT_NE(ref, std::nullopt);
+  EXPECT_EQ(ref.as_pointer(), &*dc);
+
+  std::optional<TestDerivedClass> empty;
+  optional_ref<TestInterface> empty_ref = empty;
+  EXPECT_EQ(empty_ref, std::nullopt);
+
+  // Not possible in the other direction.
+  static_assert(!std::is_convertible_v<std::optional<TestInterface>&,
+                                       optional_ref<TestDerivedClass>>);
+}
+
+TEST(OptionalRefTest, NonConstBaseDerivedConvertibleOptionalTypeToConstRef) {
+  std::optional<TestDerivedClass> dc = TestDerivedClass{};
+  optional_ref<const TestInterface> ref = dc;
+  EXPECT_NE(ref, std::nullopt);
+  EXPECT_EQ(ref.as_pointer(), &*dc);
+
+  std::optional<TestDerivedClass> empty;
+  optional_ref<const TestInterface> empty_ref = empty;
+  EXPECT_EQ(empty_ref, std::nullopt);
+
+  // Not possible in the other direction.
+  static_assert(!std::is_convertible_v<std::optional<TestInterface>&,
+                                       optional_ref<const TestDerivedClass>>);
+  static_assert(!std::is_convertible_v<const std::optional<TestInterface>&,
+                                       optional_ref<const TestDerivedClass>>);
+}
+
+TEST(OptionalRefTest, PointerCtor) {
+  int val = 5;
+  optional_ref<const int> ref = &val;
+  EXPECT_THAT(ref, Optional(5));
+
+  auto auto_ref = optional_ref(&val);
+  static_assert(std::is_same_v<decltype(auto_ref), optional_ref<int>>,
+                "optional_ref(T*) should deduce to optional_ref<T>.");
+  EXPECT_THAT(auto_ref, Optional(5));
+
+  int* foo = nullptr;
+  optional_ref<const int> empty_ref = foo;
+  EXPECT_EQ(empty_ref, std::nullopt);
+
+  optional_ref<int*> ptr_ref = foo;
+  EXPECT_THAT(ptr_ref, Optional(nullptr));
+  static_assert(
+      !std::is_constructible_v<optional_ref<int*>, std::nullptr_t>,
+      "optional_ref should not be constructible with std::nullptr_t.");
+
+  // Pointer polymorphism works.
+  TestDerivedClass dc;
+  optional_ref<const TestInterface> dc_ref = &dc;
+  EXPECT_NE(dc_ref, std::nullopt);
+}
+
+TEST(OptionalRefTest, ValueDeathWhenEmpty) {
+  optional_ref<int> ref;
+#ifdef ABSL_HAVE_EXCEPTIONS
+  EXPECT_THROW(ref.value(), std::bad_optional_access);
+#else
+  EXPECT_DEATH_IF_SUPPORTED(ref.value(), "");
+#endif
+}
+
+TEST(OptionalRefTest, ImplicitCtor) {
+  const int val = 5;
+  optional_ref<const int> ref = val;
+  EXPECT_THAT(ref, Optional(5));
+}
+
+TEST(OptionalRefTest, DoesNotCopy) {
+  // Non-copyable type.
+  auto val = std::make_unique<int>(5);
+  optional_ref<std::unique_ptr<int>> ref = optional_ref(val);
+  EXPECT_THAT(ref, Optional(Pointee(5)));
+}
+
+TEST(OptionalRefTest, DoesNotCopyConst) {
+  // Non-copyable type.
+  const auto val = std::make_unique<int>(5);
+  optional_ref<const std::unique_ptr<int>> ref = optional_ref(val);
+  EXPECT_THAT(ref, Optional(Pointee(5)));
+}
+
+TEST(OptionalRefTest, RefCopyable) {
+  auto val = std::make_unique<int>(5);
+  optional_ref<std::unique_ptr<int>> ref = optional_ref(val);
+  optional_ref<std::unique_ptr<int>> copy = ref;
+  EXPECT_THAT(copy, Optional(Pointee(5)));
+}
+
+TEST(OptionalRefTest, ConstConvertible) {
+  auto val = std::make_unique<int>(5);
+  optional_ref<std::unique_ptr<int>> ref = optional_ref(val);
+  optional_ref<const std::unique_ptr<int>> converted = ref;
+  EXPECT_THAT(converted, Optional(Pointee(5)));
+  EXPECT_EQ(converted.as_pointer(), &val);
+
+  // Not possible in the other direction.
+  static_assert(!std::is_convertible_v<optional_ref<const std::unique_ptr<int>>,
+                                       optional_ref<std::unique_ptr<int>>>);
+}
+
+TEST(OptionalRefTest, BaseDerivedConvertible) {
+  TestDerivedClass dc;
+  optional_ref<TestDerivedClass> dc_ref = dc;
+  optional_ref<TestInterface> converted = dc_ref;
+  EXPECT_NE(converted, std::nullopt);
+  EXPECT_EQ(converted.as_pointer(), &dc);
+
+  // Not possible in the other direction.
+  static_assert(!std::is_convertible_v<optional_ref<TestInterface>,
+                                       optional_ref<TestDerivedClass>>);
+}
+
+TEST(OptionalRefTest, BaseDerivedConstConvertible) {
+  TestDerivedClass dc;
+  optional_ref<TestDerivedClass> dc_ref = dc;
+  optional_ref<const TestInterface> converted = dc_ref;
+  EXPECT_NE(converted, std::nullopt);
+  EXPECT_EQ(converted.as_pointer(), &dc);
+
+  // Not possible in the other direction.
+  static_assert(!std::is_convertible_v<optional_ref<const TestInterface>,
+                                       optional_ref<TestDerivedClass>>);
+  static_assert(!std::is_convertible_v<optional_ref<const TestDerivedClass>,
+                                       optional_ref<TestInterface>>);
+}
+
+TEST(OptionalRefTest, BaseDerivedBothConstConvertible) {
+  TestDerivedClass dc;
+  optional_ref<const TestDerivedClass> dc_ref = dc;
+  optional_ref<const TestInterface> converted = dc_ref;
+  EXPECT_NE(converted, std::nullopt);
+  EXPECT_EQ(converted.as_pointer(), &dc);
+
+  // Not possible in the other direction.
+  static_assert(!std::is_convertible_v<optional_ref<const TestInterface>,
+                                       optional_ref<const TestDerivedClass>>);
+}
+
+TEST(OptionalRefTest, TriviallyCopyable) {
+  static_assert(
+      std::is_trivially_copyable_v<optional_ref<std::unique_ptr<int>>>);
+}
+
+TEST(OptionalRefTest, TriviallyDestructible) {
+  static_assert(
+      std::is_trivially_destructible_v<optional_ref<std::unique_ptr<int>>>);
+}
+
+TEST(OptionalRefTest, RefNotAssignable) {
+  static_assert(!std::is_copy_assignable_v<optional_ref<int>>);
+  static_assert(!std::is_move_assignable_v<optional_ref<int>>);
+}
+
+struct TestStructWithCopy {
+  TestStructWithCopy() = default;
+  TestStructWithCopy(TestStructWithCopy&&) {
+    LOG(FATAL) << "Move constructor should not be called";
+  }
+  TestStructWithCopy(const TestStructWithCopy&) {
+    LOG(FATAL) << "Copy constructor should not be called";
+  }
+  TestStructWithCopy& operator=(const TestStructWithCopy&) {
+    LOG(FATAL) << "Assign operator should not be called";
+  }
+};
+
+TEST(OptionalRefTest, DoesNotCopyUsingFatalCopyAssignOps) {
+  TestStructWithCopy val;
+  optional_ref<TestStructWithCopy> ref = optional_ref(val);
+  EXPECT_NE(ref, std::nullopt);
+  EXPECT_NE(optional_ref(TestStructWithCopy{}), std::nullopt);
+}
+
+std::string AddExclamation(optional_ref<const std::string> input) {
+  if (!input.has_value()) {
+    return "";
+  }
+  return absl::StrCat(*input, "!");
+}
+
+TEST(OptionalRefTest, RefAsFunctionParameter) {
+  EXPECT_EQ(AddExclamation(std::nullopt), "");
+  EXPECT_EQ(AddExclamation(std::string("abc")), "abc!");
+  std::string s = "def";
+  EXPECT_EQ(AddExclamation(s), "def!");
+  EXPECT_EQ(AddExclamation(std::make_optional<std::string>(s)), "def!");
+}
+
+TEST(OptionalRefTest, ValueOrWhenHasValue) {
+  std::optional<int> val = 5;
+  EXPECT_EQ(optional_ref(val).value_or(2), 5);
+}
+
+TEST(OptionalRefTest, ValueOrWhenEmpty) {
+  std::optional<int> val = std::nullopt;
+  EXPECT_EQ(optional_ref(val).value_or(2), 2);
+}
+
+TEST(OptionalRefTest, AsOptional) {
+  EXPECT_EQ(optional_ref<int>().as_optional(), std::nullopt);
+  std::string val = "foo";
+  optional_ref<const std::string> ref = val;
+  static_assert(
+      std::is_same_v<decltype(ref.as_optional()), std::optional<std::string>>,
+      "The type parameter of optional_ref should decay by default for the "
+      "return type in as_optional().");
+  std::optional<std::string> opt_string = ref.as_optional();
+  EXPECT_THAT(opt_string, Optional(val));
+
+  std::optional<std::string_view> opt_view =
+      ref.as_optional<std::string_view>();
+  EXPECT_THAT(opt_view, Optional(val));
+}
+
+TEST(OptionalRefTest, Constexpr) {
+  static constexpr int foo = 123;
+  constexpr optional_ref<const int> ref(foo);
+  static_assert(ref.has_value() && *ref == foo && ref.value() == foo, "");
+}
+
+}  // namespace
+ABSL_NAMESPACE_END
+}  // namespace absl