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

Reply via email to