[clang] af5247c - [ADT] Factor out in_place_t and expose in Optional ctor

Scott Linder via cfe-commits cfe-commits at lists.llvm.org
Mon May 17 15:27:07 PDT 2021


Author: Scott Linder
Date: 2021-05-17T22:25:39Z
New Revision: af5247c9347dcf1e30443786bdddf23ca705867a

URL: https://github.com/llvm/llvm-project/commit/af5247c9347dcf1e30443786bdddf23ca705867a
DIFF: https://github.com/llvm/llvm-project/commit/af5247c9347dcf1e30443786bdddf23ca705867a.diff

LOG: [ADT] Factor out in_place_t and expose in Optional ctor

Differential Revision: https://reviews.llvm.org/D100671

Added: 
    

Modified: 
    clang/include/clang/Basic/DirectoryEntry.h
    llvm/include/llvm/ADT/Optional.h
    llvm/include/llvm/ADT/STLForwardCompat.h
    llvm/unittests/ADT/OptionalTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DirectoryEntry.h b/clang/include/clang/Basic/DirectoryEntry.h
index e0f4ae28321a3..edb8031a20b80 100644
--- a/clang/include/clang/Basic/DirectoryEntry.h
+++ b/clang/include/clang/Basic/DirectoryEntry.h
@@ -120,8 +120,7 @@ template <class RefTy> class MapEntryOptionalStorage {
   MapEntryOptionalStorage() : MaybeRef(optional_none_tag()) {}
 
   template <class... ArgTypes>
-  explicit MapEntryOptionalStorage(llvm::optional_detail::in_place_t,
-                                   ArgTypes &&...Args)
+  explicit MapEntryOptionalStorage(llvm::in_place_t, ArgTypes &&...Args)
       : MaybeRef(std::forward<ArgTypes>(Args)...) {}
 
   void reset() { MaybeRef = optional_none_tag(); }

diff  --git a/llvm/include/llvm/ADT/Optional.h b/llvm/include/llvm/ADT/Optional.h
index 67bd1f5f1a542..cdbf2e3532419 100644
--- a/llvm/include/llvm/ADT/Optional.h
+++ b/llvm/include/llvm/ADT/Optional.h
@@ -17,6 +17,7 @@
 
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/None.h"
+#include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/type_traits.h"
 #include <cassert>
@@ -30,8 +31,6 @@ class raw_ostream;
 
 namespace optional_detail {
 
-struct in_place_t {};
-
 /// Storage for any type.
 //
 // The specialization condition intentionally uses
@@ -245,13 +244,16 @@ template <typename T> class Optional {
   constexpr Optional() {}
   constexpr Optional(NoneType) {}
 
-  constexpr Optional(const T &y) : Storage(optional_detail::in_place_t{}, y) {}
+  constexpr Optional(const T &y) : Storage(in_place, y) {}
   constexpr Optional(const Optional &O) = default;
 
-  constexpr Optional(T &&y)
-      : Storage(optional_detail::in_place_t{}, std::move(y)) {}
+  constexpr Optional(T &&y) : Storage(in_place, std::move(y)) {}
   constexpr Optional(Optional &&O) = default;
 
+  template <typename... ArgTypes>
+  constexpr Optional(in_place_t, ArgTypes &&...Args)
+      : Storage(in_place, std::forward<ArgTypes>(Args)...) {}
+
   Optional &operator=(T &&y) {
     Storage = std::move(y);
     return *this;

diff  --git a/llvm/include/llvm/ADT/STLForwardCompat.h b/llvm/include/llvm/ADT/STLForwardCompat.h
index 83ce6d3f68694..440b29df260ca 100644
--- a/llvm/include/llvm/ADT/STLForwardCompat.h
+++ b/llvm/include/llvm/ADT/STLForwardCompat.h
@@ -44,6 +44,25 @@ template <typename B1, typename... Bn>
 struct disjunction<B1, Bn...>
     : std::conditional<bool(B1::value), B1, disjunction<Bn...>>::type {};
 
+struct in_place_t // NOLINT(readability-identifier-naming)
+{
+  explicit in_place_t() = default;
+};
+/// \warning This must not be odr-used, as it cannot be made \c inline in C++14.
+constexpr in_place_t in_place; // NOLINT(readability-identifier-naming)
+
+template <typename T>
+struct in_place_type_t // NOLINT(readability-identifier-naming)
+{
+  explicit in_place_type_t() = default;
+};
+
+template <std::size_t I>
+struct in_place_index_t // NOLINT(readability-identifier-naming)
+{
+  explicit in_place_index_t() = default;
+};
+
 //===----------------------------------------------------------------------===//
 //     Features from C++20
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/unittests/ADT/OptionalTest.cpp b/llvm/unittests/ADT/OptionalTest.cpp
index 2c5d65f80d977..debeb78e8fab7 100644
--- a/llvm/unittests/ADT/OptionalTest.cpp
+++ b/llvm/unittests/ADT/OptionalTest.cpp
@@ -195,6 +195,14 @@ TEST(OptionalTest, NullCopyConstructionTest) {
   EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
 }
 
+TEST(OptionalTest, InPlaceConstructionNonDefaultConstructibleTest) {
+  NonDefaultConstructible::ResetCounts();
+  { Optional<NonDefaultConstructible> A{in_place, 1}; }
+  EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
+  EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+  EXPECT_EQ(1u, NonDefaultConstructible::Destructions);
+}
+
 TEST(OptionalTest, GetValueOr) {
   Optional<int> A;
   EXPECT_EQ(42, A.getValueOr(42));
@@ -214,6 +222,11 @@ struct MultiArgConstructor {
   MultiArgConstructor &operator=(const MultiArgConstructor &) = delete;
   MultiArgConstructor &operator=(MultiArgConstructor &&) = delete;
 
+  friend bool operator==(const MultiArgConstructor &LHS,
+                         const MultiArgConstructor &RHS) {
+    return LHS.x == RHS.x && LHS.y == RHS.y;
+  }
+
   static unsigned Destructions;
   ~MultiArgConstructor() {
     ++Destructions;
@@ -244,6 +257,34 @@ TEST(OptionalTest, Emplace) {
   EXPECT_EQ(1u, MultiArgConstructor::Destructions);
 }
 
+TEST(OptionalTest, InPlaceConstructionMultiArgConstructorTest) {
+  MultiArgConstructor::ResetCounts();
+  {
+    Optional<MultiArgConstructor> A{in_place, 1, 2};
+    EXPECT_TRUE(A.hasValue());
+    EXPECT_EQ(1, A->x);
+    EXPECT_EQ(2, A->y);
+    Optional<MultiArgConstructor> B{in_place, 5, false};
+    EXPECT_TRUE(B.hasValue());
+    EXPECT_EQ(5, B->x);
+    EXPECT_EQ(-5, B->y);
+    EXPECT_EQ(0u, MultiArgConstructor::Destructions);
+  }
+  EXPECT_EQ(2u, MultiArgConstructor::Destructions);
+}
+
+TEST(OptionalTest, InPlaceConstructionAndEmplaceEquivalentTest) {
+  MultiArgConstructor::ResetCounts();
+  {
+    Optional<MultiArgConstructor> A{in_place, 1, 2};
+    Optional<MultiArgConstructor> B;
+    B.emplace(1, 2);
+    EXPECT_EQ(0u, MultiArgConstructor::Destructions);
+    ASSERT_EQ(A, B);
+  }
+  EXPECT_EQ(2u, MultiArgConstructor::Destructions);
+}
+
 struct MoveOnly {
   static unsigned MoveConstructions;
   static unsigned Destructions;
@@ -391,6 +432,15 @@ TEST(OptionalTest, ImmovableEmplace) {
   EXPECT_EQ(0u, Immovable::Destructions);
 }
 
+TEST(OptionalTest, ImmovableInPlaceConstruction) {
+  Immovable::ResetCounts();
+  Optional<Immovable> A{in_place, 4};
+  EXPECT_TRUE((bool)A);
+  EXPECT_EQ(4, A->val);
+  EXPECT_EQ(1u, Immovable::Constructions);
+  EXPECT_EQ(0u, Immovable::Destructions);
+}
+
 // Craft a class which is_trivially_copyable, but not
 // is_trivially_copy_constructible.
 struct NonTCopy {


        


More information about the cfe-commits mailing list