]> granicus.if.org Git - llvm/commitdiff
Make Optional<T> Trivially Copyable when T is trivially copyable
authorSerge Guelton <sguelton@redhat.com>
Sat, 16 Feb 2019 09:19:58 +0000 (09:19 +0000)
committerSerge Guelton <sguelton@redhat.com>
Sat, 16 Feb 2019 09:19:58 +0000 (09:19 +0000)
This is another attempt in the process, works nicely on my setup,
let's check how it behaves on other targets.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354199 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/Optional.h
unittests/ADT/OptionalTest.cpp

index 25a3185064f413225f0c63db53ea87114657dd75..ab83b67b11bdf65a94707eebce17a61082d138f6 100644 (file)
@@ -108,6 +108,59 @@ template <typename T, bool = is_trivially_copyable<T>::value> struct OptionalSto
     return reinterpret_cast<const T *>(storage.buffer);
   }
 };
+template <typename T> struct OptionalStorage<T, true> {
+  AlignedCharArrayUnion<T> storage;
+  bool hasVal = false;
+
+  OptionalStorage() = default;
+
+  OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
+  OptionalStorage(const OptionalStorage &O)  = default;
+  OptionalStorage(T &&y) : hasVal(true) {
+    new (storage.buffer) T(std::forward<T>(y));
+  }
+  OptionalStorage(OptionalStorage &&O) = default;
+
+  OptionalStorage &operator=(T &&y) {
+    if (hasVal)
+      *getPointer() = std::move(y);
+    else {
+      new (storage.buffer) T(std::move(y));
+      hasVal = true;
+    }
+    return *this;
+  }
+  OptionalStorage &operator=(OptionalStorage &&O) = default;
+
+  OptionalStorage &operator=(const T &y) {
+    if (hasVal)
+      *getPointer() = y;
+    else {
+      new (storage.buffer) T(y);
+      hasVal = true;
+    }
+    return *this;
+  }
+  OptionalStorage &operator=(const OptionalStorage &O) = default;
+
+  ~OptionalStorage() = default;
+
+  void reset() {
+    if (hasVal) {
+      (*getPointer()).~T();
+      hasVal = false;
+    }
+  }
+
+  T *getPointer() {
+    assert(hasVal);
+    return reinterpret_cast<T *>(storage.buffer);
+  }
+  const T *getPointer() const {
+    assert(hasVal);
+    return reinterpret_cast<const T *>(storage.buffer);
+  }
+};
 
 } // namespace optional_detail
 
index 98adaccca961341bc95eac617f90545e09735c79..015fcf38981381699f8ddbcee74909d5d1c47e4b 100644 (file)
 
 #include <array>
 
+
 using namespace llvm;
 
+static_assert(llvm::is_trivially_copyable<Optional<int>>::value,
+              "trivially copyable");
+
+static_assert(llvm::is_trivially_copyable<Optional<std::array<int, 3>>>::value,
+              "trivially copyable");
+
 namespace {
 
 struct NonDefaultConstructible {