[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