pw_result: Add dereference operators

Change-Id: I61a912c10377872b475f770d1e45f0c35afd0257
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/55304
Commit-Queue: Adam MacBeth <amacbeth@google.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
diff --git a/pw_result/docs.rst b/pw_result/docs.rst
index b628bbd..02c9475 100644
--- a/pw_result/docs.rst
+++ b/pw_result/docs.rst
@@ -44,6 +44,27 @@
     return pw::OkStatus();
   }
 
+``pw::Result`` can be used to directly access the contained type:
+
+.. code-block:: cpp
+
+  #include "pw_result/result.h"
+
+  pw::Result<Foo> foo = TryCreateFoo();
+  if (foo.ok()) {
+    foo->DoBar();
+  }
+
+or in C++17:
+
+.. code-block:: cpp
+
+  if (pw::Result<Foo> foo = TryCreateFoo(); foo.ok()) {
+    foo->DoBar();
+  }
+
+See `Abseil's StatusOr <https://abseil.io/tips/181>`_ for guidance on using a
+similar type.
 
 .. warning::
 
diff --git a/pw_result/public/pw_result/result.h b/pw_result/public/pw_result/result.h
index 3af06ae..2366e03 100644
--- a/pw_result/public/pw_result/result.h
+++ b/pw_result/public/pw_result/result.h
@@ -69,6 +69,36 @@
     return std::move(value_);
   }
 
+  constexpr T& operator*() const& {
+    PW_ASSERT(status_.ok());
+    return value_;
+  }
+
+  T& operator*() & {
+    PW_ASSERT(status_.ok());
+    return value_;
+  }
+
+  constexpr T&& operator*() const&& {
+    PW_ASSERT(status_.ok());
+    return std::move(value_);
+  }
+
+  T&& operator*() && {
+    PW_ASSERT(status_.ok());
+    return std::move(value_);
+  }
+
+  constexpr T* operator->() const {
+    PW_ASSERT(status_.ok());
+    return &value_;
+  }
+
+  T* operator->() {
+    PW_ASSERT(status_.ok());
+    return &value_;
+  }
+
   template <typename U>
   constexpr T value_or(U&& default_value) const& {
     if (ok()) {
diff --git a/pw_result/result_test.cc b/pw_result/result_test.cc
index 6642cf3..93f1200 100644
--- a/pw_result/result_test.cc
+++ b/pw_result/result_test.cc
@@ -40,6 +40,22 @@
   EXPECT_EQ(bad.value_or(42), 42);
 }
 
+TEST(Result, Deref) {
+  struct Tester {
+    constexpr bool True() { return true; };
+    constexpr bool False() { return false; };
+  };
+
+  auto tester = Result(Tester());
+  EXPECT_TRUE(tester.ok());
+  EXPECT_TRUE(tester->True());
+  EXPECT_FALSE(tester->False());
+  EXPECT_TRUE((*tester).True());
+  EXPECT_FALSE((*tester).False());
+  EXPECT_EQ(tester.value().True(), tester->True());
+  EXPECT_EQ(tester.value().False(), tester->False());
+}
+
 TEST(Result, ConstructType) {
   struct Point {
     Point(int a, int b) : x(a), y(b) {}