Commit c36c506a authored by Chad Austin's avatar Chad Austin Committed by Facebook Github Bot

Disallow construction of std::optional from folly::none

Summary:
I spent a day trying to convert some code from folly::Optional to
std::optional. One hour of that was making the necessary syntax
changes. The rest was diagnosing why certain bits of code broke. The
reason turned out to be that `folly::Optional` allowed construction
from nullptr and that `std::optional<bool>{folly::none}` would result
in `std::make_optional(false)`, not `std::nullopt`.

Instead of implementing folly::none with a pointer-to-member, copy the
implementation of the upcoming std::nullopt.

As teams switch to C++17, this should smooth the migration.

Reviewed By: yfeldblum

Differential Revision: D10475780

fbshipit-source-id: 3a072b5e7e95209721d871361f5a24e3e30472cd
parent edcd66e1
......@@ -71,15 +71,19 @@ template <class Value>
class Optional;
namespace detail {
struct NoneHelper {};
template <class Value>
struct OptionalPromiseReturn;
} // namespace detail
typedef int detail::NoneHelper::*None;
struct None {
/**
* DEPRECATED: use folly::none
*/
None() {}
const None none = {};
explicit constexpr None(int) {}
};
constexpr None none = None{0};
class FOLLY_EXPORT OptionalEmptyException : public std::runtime_error {
public:
......@@ -128,6 +132,16 @@ class Optional {
construct(newValue);
}
/**
* DEPRECATED: use folly::none
*/
template <typename Null = std::nullptr_t>
FOLLY_CPP14_CONSTEXPR /* implicit */
Optional(typename std::enable_if<
!std::is_pointer<Value>::value &&
std::is_same<Null, std::nullptr_t>::value,
Null>::type) noexcept {}
template <typename... Args>
FOLLY_CPP14_CONSTEXPR explicit Optional(in_place_t, Args&&... args) noexcept(
std::is_nothrow_constructible<Value, Args...>::value)
......@@ -207,6 +221,18 @@ class Optional {
return *this;
}
/**
* DEPRECATED: use folly::none
*/
template <typename Null = std::nullptr_t>
Optional& operator=(typename std::enable_if<
!std::is_pointer<Value>::value &&
std::is_same<Null, std::nullptr_t>::value,
Null>::type) noexcept {
reset();
return *this;
}
template <class... Args>
Value& emplace(Args&&... args) {
clear();
......
......@@ -798,4 +798,14 @@ TEST(Optional, ConstMember) {
EXPECT_EQ(sum, 3);
}
TEST(Optional, NoneMatchesNullopt) {
auto op = make_optional<int>(10);
op = {};
EXPECT_FALSE(op.has_value());
op = make_optional<int>(20);
op = none;
EXPECT_FALSE(op.has_value());
}
} // 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