lawrence_danna updated this revision to Diff 225967. lawrence_danna added a comment.
ugh I edited the wrong revision, reverted. Sorry for the noise. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D69230/new/ https://reviews.llvm.org/D69230 Files: llvm/include/llvm/ADT/Optional.h llvm/unittests/ADT/OptionalTest.cpp
Index: llvm/unittests/ADT/OptionalTest.cpp =================================================================== --- llvm/unittests/ADT/OptionalTest.cpp +++ llvm/unittests/ADT/OptionalTest.cpp @@ -221,7 +221,7 @@ TEST_F(OptionalTest, Emplace) { MultiArgConstructor::ResetCounts(); Optional<MultiArgConstructor> A; - + A.emplace(1, 2); EXPECT_TRUE(A.hasValue()); EXPECT_EQ(1, A->x); @@ -592,3 +592,35 @@ } } // end anonymous namespace + +class NaturalNumber { + friend struct llvm::optional_detail::has_is_valid<NaturalNumber>; + int value; + constexpr NaturalNumber() : value(-1) {} + +public: + operator int() const { return value; } + NaturalNumber(int x) : value(x) { assert(value >= 0); } +}; + +template <> struct llvm::optional_detail::has_is_valid<NaturalNumber, void> { + static const bool value = true; + static bool is_valid(const NaturalNumber &n) { return n.value >= 0; } + static constexpr NaturalNumber make_invalid() { return NaturalNumber(); } +}; + +TEST_F(OptionalTest, TestHasInvalid) { + + constexpr Optional<NaturalNumber> none; + + static_assert(sizeof(Optional<NaturalNumber>) == sizeof(int), + "no extra bool"); + + Optional<NaturalNumber> x = None; + EXPECT_FALSE(x.hasValue()); + EXPECT_TRUE(x == none); + EXPECT_EQ(*reinterpret_cast<int *>(&x), -1); + x = NaturalNumber{42}; + EXPECT_TRUE(x.hasValue()); + EXPECT_EQ((int)x.getValue(), 42); +} Index: llvm/include/llvm/ADT/Optional.h =================================================================== --- llvm/include/llvm/ADT/Optional.h +++ llvm/include/llvm/ADT/Optional.h @@ -31,9 +31,12 @@ struct in_place_t {}; +template <typename T, typename Enable = void> struct has_is_valid { + const static bool value = false; +}; + /// Storage for any type. -template <typename T, bool = is_trivially_copyable<T>::value> -class OptionalStorage { +template <typename T, typename Enable = void> class OptionalStorage { union { char empty; T value; @@ -138,7 +141,72 @@ } }; -template <typename T> class OptionalStorage<T, true> { +template <typename T> +class OptionalStorage< + T, typename std::enable_if<has_is_valid<T>::value, void>::type> { + + T value; + typedef has_is_valid<T> THelper; + +public: + ~OptionalStorage() = default; + + constexpr OptionalStorage() noexcept : value{THelper::make_invalid()} {} + + OptionalStorage(OptionalStorage const &other) = default; + OptionalStorage(OptionalStorage &&other) = default; + + OptionalStorage &operator=(OptionalStorage const &other) = default; + OptionalStorage &operator=(OptionalStorage &&other) = default; + + template <class... Args> + explicit OptionalStorage(in_place_t, Args &&... args) + : value(std::forward<Args>(args)...) { + asert(THelper::is_valid(value)); + } + + void reset() noexcept { value = THelper::make_invalid; } + + bool hasValue() const noexcept { return THelper::is_valid(value); } + + T &getValue() LLVM_LVALUE_FUNCTION noexcept { + assert(THelper::is_valid(value)); + return value; + } + T const &getValue() const LLVM_LVALUE_FUNCTION noexcept { + assert(THelper::is_valid(value)); + return value; + } +#if LLVM_HAS_RVALUE_REFERENCE_THIS + T &&getValue() && noexcept { + assert(THelper::is_valid(value)); + return std::move(value); + } +#endif + + template <class... Args> void emplace(Args &&... args) { + value = T(std::forward<Args>(args)...); + asert(THelper::is_valid(value)); + } + + OptionalStorage &operator=(T const &y) { + assert(THelper::is_valid(y)); + value = y; + return *this; + } + + OptionalStorage &operator=(T &&y) { + assert(THelper::is_valid(y)); + value = std::move(y); + return *this; + } +}; + +template <typename T> +class OptionalStorage< + T, typename std::enable_if<std::is_trivially_copyable<T>::value && + !has_is_valid<T>::value, + void>::type> { union { char empty; T value;
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits