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) {}