Commit 6d8bd01c authored by Lucian Grijincu's avatar Lucian Grijincu Committed by Facebook GitHub Bot

folly::Try: add value_or() implementations mimicking std::optional::value_or API

Summary:
Add API equivalent to `std::optional::value_or`: https://en.cppreference.com/w/cpp/utility/optional/value_or

Returns the contained value if *this has a value, otherwise returns default_value.

  template< class U > constexpr T value_or( U&& default_value ) const&;

Equivalent to `bool(*this) ? **this : static_cast<T>(std::forward<U>(default_value))`

   template< class U > constexpr T value_or( U&& default_value ) &&;

Equivalent to `bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(default_value))`

Reviewed By: yfeldblum

Differential Revision: D27346319

fbshipit-source-id: 598b740cb9068cffb0cc0fbda3579e64fd125e8b
parent d3f0a283
......@@ -168,6 +168,19 @@ const T&& Try<T>::value() const&& {
return std::move(value_);
}
template <class T>
template <class U>
T Try<T>::value_or(U&& defaultValue) const& {
return hasValue() ? **this : static_cast<T>(static_cast<U&&>(defaultValue));
}
template <class T>
template <class U>
T Try<T>::value_or(U&& defaultValue) && {
return hasValue() ? std::move(**this)
: static_cast<T>(static_cast<U&&>(defaultValue));
}
template <class T>
void Try<T>::throwUnlessValue() const {
switch (contains_) {
......
......@@ -178,6 +178,17 @@ class Try {
*/
const T&& value() const&&;
/*
* Returns a copy of the contained value if *this has a value,
* otherwise returns a value constructed from defaultValue.
*
* The selected constructor of the return value may throw exceptions.
*/
template <class U>
T value_or(U&& defaultValue) const&;
template <class U>
T value_or(U&& defaultValue) &&;
/*
* [Re]throw if the Try contains an exception or is empty. Otherwise do
* nothing.
......
......@@ -192,6 +192,8 @@ TEST(Try, emplaceWithThrowingConstructor) {
EXPECT_FALSE(t.hasValue());
EXPECT_FALSE(t.hasException());
EXPECT_THROW(t.value_or(true), MyException);
}
{
......@@ -202,6 +204,8 @@ TEST(Try, emplaceWithThrowingConstructor) {
EXPECT_THROW(t.emplace(true), MyException);
EXPECT_FALSE(t.hasValue());
EXPECT_FALSE(t.hasException());
EXPECT_THROW(t.value_or(true), MyException);
}
}
......@@ -376,6 +380,7 @@ TEST(Try, MoveDereference) {
auto t = Try<std::unique_ptr<int>>{std::move(ptr)};
auto result = *std::move(t);
EXPECT_EQ(*result, 1);
EXPECT_TRUE(t.hasValue());
}
TEST(Try, MoveConstRvalue) {
......@@ -429,6 +434,47 @@ TEST(Try, ValueOverloads) {
}
}
TEST(Try, ValueOr) {
struct CopyableValue {
int x;
};
{
Try<CopyableValue> o{CopyableValue{42}};
CopyableValue defaultValue{17};
EXPECT_EQ(o.value_or(defaultValue).x, 42);
EXPECT_EQ(o.value_or(defaultValue).x, (*o).x);
}
{
Try<CopyableValue> empty;
EXPECT_FALSE(empty.hasValue());
CopyableValue defaultValue{17};
EXPECT_EQ(empty.value_or(defaultValue).x, defaultValue.x);
}
{
Try<std::unique_ptr<int>> o{std::make_unique<int>(42)};
std::unique_ptr<int> defaultValue = std::make_unique<int>(17);
std::unique_ptr<int> v = std::move(o).value_or(std::move(defaultValue));
ASSERT_TRUE(v);
EXPECT_EQ(*v, 42);
ASSERT_TRUE(defaultValue);
EXPECT_EQ(*defaultValue, 17);
EXPECT_TRUE(o.hasValue());
ASSERT_FALSE(*o);
}
{
Try<std::unique_ptr<int>> empty;
std::unique_ptr<int> defaultValue = std::make_unique<int>(17);
std::unique_ptr<int> v = std::move(empty).value_or(std::move(defaultValue));
ASSERT_TRUE(v);
EXPECT_EQ(*v, 17);
EXPECT_FALSE(defaultValue);
EXPECT_FALSE(empty.hasValue());
}
}
// Make sure we can copy Trys for copyable types
TEST(Try, copy) {
Try<int> t;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment