Commit f8c8b74f authored by Shai Szulanski's avatar Shai Szulanski Committed by Facebook GitHub Bot

Add conversions between folly and std optional

Summary: These are similar enough that implicit conversion to make the migration boundary easy to manage seems justified

Reviewed By: WillerZ

Differential Revision: D25384005

fbshipit-source-id: 4602d9016919860ff0626de4fa4ae5442fca094a
parent a247041e
......@@ -60,6 +60,9 @@
#include <stdexcept>
#include <type_traits>
#include <utility>
#if __cplusplus >= 201703L && __has_include(<optional>)
#include <optional>
#endif
#include <folly/Portability.h>
#include <folly/Traits.h>
......@@ -156,6 +159,42 @@ class Optional {
p.promise_->value_ = this;
}
// Conversions to ease migration to std::optional
#if __cplusplus >= 201703L && __has_include(<optional>)
template <
typename U,
typename = std::enable_if_t<std::is_same_v<U, std::optional<Value>>>>
explicit Optional(U&& newValue) noexcept(
std::is_nothrow_move_constructible<Value>::value) {
if (newValue.has_value()) {
construct(std::move(*newValue));
newValue.reset();
}
}
template <
typename U,
typename = std::enable_if_t<std::is_same_v<U, std::optional<Value>>>>
explicit Optional(const U& newValue) noexcept(
std::is_nothrow_copy_constructible<Value>::value) {
if (newValue.has_value()) {
construct(*newValue);
}
}
explicit operator std::optional<Value>() &&
noexcept(std::is_nothrow_move_constructible<Value>::value) {
std::optional<Value> ret = storage_.hasValue
? std::optional<Value>(std::move(storage_.value))
: std::nullopt;
reset();
return ret;
}
explicit operator std::optional<Value>() &
noexcept(std::is_nothrow_copy_constructible<Value>::value) {
return storage_.hasValue ? std::optional<Value>(storage_.value)
: std::nullopt;
}
#endif
void assign(const None&) { reset(); }
void assign(Optional&& src) {
......
......@@ -815,4 +815,24 @@ TEST(Optional, NoneMatchesNullopt) {
EXPECT_FALSE(op.has_value());
}
#if __cplusplus >= 201703L && __has_include(<optional>)
TEST(Optional, StdOptionalConversions) {
folly::Optional<int> f = 42;
std::optional<int> s = static_cast<std::optional<int>>(f);
EXPECT_EQ(*s, 42);
EXPECT_TRUE(f);
f = static_cast<folly::Optional<int>>(s);
EXPECT_EQ(*f, 42);
EXPECT_TRUE(s);
folly::Optional<std::unique_ptr<int>> fp = std::make_unique<int>(42);
std::optional<std::unique_ptr<int>> sp(std::move(fp));
EXPECT_EQ(**sp, 42);
EXPECT_FALSE(fp);
fp = static_cast<folly::Optional<std::unique_ptr<int>>>(std::move(sp));
EXPECT_EQ(**fp, 42);
EXPECT_FALSE(sp);
}
#endif
} // namespace folly
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