Skip to content

Commit

Permalink
docs(common): improve StatuOr<> documentation (#11631)
Browse files Browse the repository at this point in the history
The most interesting change is expressing some SFINAE tricks in a way
that is easier to document.
  • Loading branch information
coryan authored May 16, 2023
1 parent c766479 commit ca6c0ef
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 13 deletions.
37 changes: 24 additions & 13 deletions google/cloud/status_or.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,17 @@ class StatusOr final {

/**
* Assign a `T` (or anything convertible to `T`) into the `StatusOr`.
*
* @return a reference to this object.
* @tparam U a type convertible to @p T
* @tparam Unspecified removes this function from overload resolution if
* `U` is (a possibly cv-qualified version of) `StatusOr<T>`.
*/
// Disable this assignment if U==StatusOr<T>. Well, really if U is a
// cv-qualified version of StatusOr<T>, so we need to apply std::decay<> to
// it first.
template <typename U = T>
typename std::enable_if< // NOLINT(misc-unconventional-assign-operator)
!std::is_same<StatusOr, typename std::decay<U>::type>::value,
StatusOr>::type&
operator=(U&& rhs) {
template <typename U = T,
typename Unspecified = typename std::enable_if<
!std::is_same<StatusOr, typename std::decay<U>::type>::value,
int>::type>
StatusOr& operator=(U&& rhs) {
status_ = Status();
value_ = std::forward<U>(rhs);
return *this;
Expand Down Expand Up @@ -186,13 +188,18 @@ class StatusOr final {

///@{
/**
* @name Deference operators.
* @name Dereference operators.
*
* @par Pre-conditions
* @parblock
* `ok() == true`
*
* @warning Using these operators when `ok() == false` results in undefined
* behavior.
* @endparblock
*
* @return All these return a (properly ref and const-qualified) reference to
* the underlying value.
* @return A properly ref and const-qualified reference to the underlying
* value.
*/
T& operator*() & { return *value_; }

Expand All @@ -207,11 +214,15 @@ class StatusOr final {
/**
* @name Member access operators.
*
* @par Pre-conditions
* @parblock
* `ok() == true`
*
* @warning Using these operators when `ok() == false` results in undefined
* behavior.
* @endparblock
*
* @return All these return a (properly ref and const-qualified) pointer to
* the underlying value.
* @return A properly ref and const-qualified pointer to the underlying value.
*/
T* operator->() & { return &*value_; }

Expand Down
10 changes: 10 additions & 0 deletions google/cloud/status_or_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace google {
namespace cloud {
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
namespace {
using ::google::cloud::testing_util::IsOkAndHolds;
using ::testing::HasSubstr;

TEST(StatusOrTest, ValueType) {
Expand Down Expand Up @@ -190,6 +191,15 @@ TEST(StatusOrTest, MovedFromState) {
EXPECT_EQ(b, StatusOr<int>{}); // NOLINT(bugprone-use-after-move)
}

TEST(StatusOrTest, AssignmentNotAmbiguous) {
StatusOr<std::string> actual(std::string{"42"});
EXPECT_THAT(actual, IsOkAndHolds("42"));
actual = "7";
EXPECT_THAT(actual, IsOkAndHolds("7"));
actual = StatusOr<std::string>("42");
EXPECT_THAT(actual, IsOkAndHolds("42"));
}

using testing_util::NoDefaultConstructor;

TEST(StatusOrNoDefaultConstructor, DefaultConstructed) {
Expand Down

0 comments on commit ca6c0ef

Please sign in to comment.