X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FOptional.h;h=acd0b1267d0b51ecdb94c7f57a8b34e85f91efa6;hb=897877b826bf39211ef62a1172aa192efb54f4a2;hp=2bb2d658eb897467cb7786f8343b51f3851196bd;hpb=3597c587da97b02466811339af1e9ced2e73d988;p=folly.git diff --git a/folly/Optional.h b/folly/Optional.h index 2bb2d658..acd0b126 100644 --- a/folly/Optional.h +++ b/folly/Optional.h @@ -61,9 +61,10 @@ #include #include -#include #include +#include #include +#include namespace folly { @@ -203,15 +204,41 @@ class Optional { } template - void emplace(Args&&... args) { + Value& emplace(Args&&... args) { clear(); - storage_.construct(std::forward(args)...); + return storage_.construct(std::forward(args)...); + } + + template + typename std::enable_if< + std::is_constructible&, Args&&...>::value, + Value&>::type + emplace(std::initializer_list ilist, Args&&... args) { + clear(); + return storage_.construct(ilist, std::forward(args)...); } - void clear() { + void reset() noexcept { storage_.clear(); } + void clear() noexcept { + reset(); + } + + void swap(Optional& that) noexcept(IsNothrowSwappable::value) { + if (hasValue() && that.hasValue()) { + using std::swap; + swap(value(), that.value()); + } else if (hasValue()) { + that.emplace(std::move(value())); + reset(); + } else if (that.hasValue()) { + emplace(std::move(that.value())); + that.reset(); + } + } + FOLLY_CPP14_CONSTEXPR const Value& value() const & { require_value(); return *storage_.value_pointer(); @@ -240,12 +267,16 @@ class Optional { } Value* get_pointer() && = delete; - FOLLY_CPP14_CONSTEXPR bool hasValue() const noexcept { + FOLLY_CPP14_CONSTEXPR bool has_value() const noexcept { return storage_.hasValue(); } + FOLLY_CPP14_CONSTEXPR bool hasValue() const noexcept { + return has_value(); + } + FOLLY_CPP14_CONSTEXPR explicit operator bool() const noexcept { - return hasValue(); + return has_value(); } FOLLY_CPP14_CONSTEXPR const Value& operator*() const & { @@ -350,9 +381,10 @@ class Optional { } template - void construct(Args&&... args) { + Value& construct(Args&&... args) { new (raw_pointer()) Value(std::forward(args)...); this->hasValue_ = true; + return *launder(reinterpret_cast(this->value_)); } private: @@ -375,14 +407,8 @@ T* get_pointer(Optional& opt) { } template -void swap(Optional& a, Optional& b) { - if (a.hasValue() && b.hasValue()) { - // both full - using std::swap; - swap(a.value(), b.value()); - } else if (a.hasValue() || b.hasValue()) { - std::swap(a, b); // fall back to default implementation if they're mixed. - } +void swap(Optional& a, Optional& b) noexcept(noexcept(a.swap(b))) { + a.swap(b); } template ::type>> @@ -625,6 +651,6 @@ template struct coroutine_traits, Args...> { using promise_type = folly::detail::OptionalPromise; }; -} // experimental +} // namespace experimental FOLLY_NAMESPACE_STD_END #endif // FOLLY_HAS_COROUTINES