Skip to content

Commit

Permalink
Add then-chaining conversion to Expected
Browse files Browse the repository at this point in the history
Summary: See inline comment / test.

Reviewed By: Gownta

Differential Revision: D49215070

fbshipit-source-id: d9543bf1727be88ac2a85c0f80d25fd3b7081d48
  • Loading branch information
Alexey Spiridonov authored and facebook-github-bot committed Sep 15, 2023
1 parent 77101e0 commit ab1c489
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 0 deletions.
21 changes: 21 additions & 0 deletions folly/Expected.h
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,27 @@ class Expected final : expected_detail::ExpectedStorage<Value, Error> {
this->assign(std::move(that));
}

// Implicit then-chaining conversion: if `Expected<Value, Error>` can be
// constructed from `V`, then we can directly convert `Expected<V, E>` to
// `Expected<Value, Error>`.
//
// Specifically, this allows a user-defined conversions of `V` to
// `Expected<Value, Error>` to work as desired with range-based iteration
// over containers of `Expected<V, E>`.
template <
class V,
class E FOLLY_REQUIRES_TRAILING(
!std::is_same<Expected<V, E>, Expected>::value &&
!std::is_constructible<Value, V&&>::value &&
std::is_constructible<Expected<Value, Error>, V&&>::value &&
std::is_constructible<Error, E&&>::value)>
/* implicit */ Expected(Expected<V, E> that)
: Base{expected_detail::EmptyTag{}} {
this->assign(std::move(that).then([](V&& v) -> Expected<Value, Error> {
return Expected<Value, Error>{v};
}));
}

FOLLY_REQUIRES(std::is_copy_constructible<Value>::value)
constexpr /* implicit */ Expected(const Value& val) noexcept(
noexcept(Value(val)))
Expand Down
13 changes: 13 additions & 0 deletions folly/test/ExpectedTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -974,4 +974,17 @@ TEST(Expected, TestUnique) {
}));
}

struct ConvertibleNum {
/*implicit*/ operator Expected<int, E>() const { return num_; }
int num_;
};

TEST(Expected, TestChainedConversion) {
auto vs =
std::vector<Expected<ConvertibleNum, E>>{ConvertibleNum{.num_ = 137}};
for (Expected<int, E> v : vs) {
ASSERT_EQ(137, *v);
}
}

} // namespace folly

0 comments on commit ab1c489

Please sign in to comment.