about summary refs log tree commit diff
path: root/absl/container/internal/compressed_tuple.h
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2019-07-17T20·35-0400
committerDerek Mauro <dmauro@google.com>2019-07-17T20·40-0400
commitc6c3c1b498e4ee939b24be59cae29d59c3863be8 (patch)
tree030b875cdbbd25d2d0b7bca0b68a71351eeb2c41 /absl/container/internal/compressed_tuple.h
parent44efe96dfca674a17b45ca53fc77fb69f1e29bf4 (diff)
Export of internal Abseil changes.
--
ed3a3431eee9e48e6553b0320e0308d2dde6725c by Derek Mauro <dmauro@google.com>:

Project import generated by Copybara.

PiperOrigin-RevId: 258631680
GitOrigin-RevId: ed3a3431eee9e48e6553b0320e0308d2dde6725c
Change-Id: I1d7ae86a79783842092d29504605ba039c369603
Diffstat (limited to 'absl/container/internal/compressed_tuple.h')
-rw-r--r--absl/container/internal/compressed_tuple.h49
1 files changed, 41 insertions, 8 deletions
diff --git a/absl/container/internal/compressed_tuple.h b/absl/container/internal/compressed_tuple.h
index c29ab41eb9fd..7d08e370dec1 100644
--- a/absl/container/internal/compressed_tuple.h
+++ b/absl/container/internal/compressed_tuple.h
@@ -102,7 +102,9 @@ template <typename T, size_t I,
 struct Storage {
   T value;
   constexpr Storage() = default;
-  explicit constexpr Storage(T&& v) : value(absl::forward<T>(v)) {}
+  template <typename V>
+  explicit constexpr Storage(absl::in_place_t, V&& v)
+      : value(absl::forward<V>(v)) {}
   constexpr const T& get() const& { return value; }
   T& get() & { return value; }
   constexpr const T&& get() const&& { return absl::move(*this).value; }
@@ -112,7 +114,11 @@ struct Storage {
 template <typename T, size_t I>
 struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage<T, I, true> : T {
   constexpr Storage() = default;
-  explicit constexpr Storage(T&& v) : T(absl::forward<T>(v)) {}
+
+  template <typename V>
+  explicit constexpr Storage(absl::in_place_t, V&& v)
+      : T(absl::forward<V>(v)) {}
+
   constexpr const T& get() const& { return *this; }
   T& get() & { return *this; }
   constexpr const T&& get() const&& { return absl::move(*this); }
@@ -132,8 +138,9 @@ struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl<
     : uses_inheritance,
       Storage<Ts, std::integral_constant<size_t, I>::value>... {
   constexpr CompressedTupleImpl() = default;
-  explicit constexpr CompressedTupleImpl(Ts&&... args)
-      : Storage<Ts, I>(absl::forward<Ts>(args))... {}
+  template <typename... Vs>
+  explicit constexpr CompressedTupleImpl(absl::in_place_t, Vs&&... args)
+      : Storage<Ts, I>(absl::in_place, absl::forward<Vs>(args))... {}
   friend CompressedTuple<Ts...>;
 };
 
@@ -143,8 +150,9 @@ struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl<
     // We use the dummy identity function as above...
     : Storage<Ts, std::integral_constant<size_t, I>::value, false>... {
   constexpr CompressedTupleImpl() = default;
-  explicit constexpr CompressedTupleImpl(Ts&&... args)
-      : Storage<Ts, I, false>(absl::forward<Ts>(args))... {}
+  template <typename... Vs>
+  explicit constexpr CompressedTupleImpl(absl::in_place_t, Vs&&... args)
+      : Storage<Ts, I, false>(absl::in_place, absl::forward<Vs>(args))... {}
   friend CompressedTuple<Ts...>;
 };
 
@@ -159,6 +167,11 @@ constexpr bool ShouldAnyUseBase() {
       Or({std::integral_constant<bool, ShouldUseBase<Ts>()>()...})){};
 }
 
+template <typename T, typename V>
+using TupleMoveConstructible = typename std::conditional<
+      std::is_reference<T>::value, std::is_convertible<V, T>,
+      std::is_constructible<T, V&&>>::type;
+
 }  // namespace internal_compressed_tuple
 
 // Helper class to perform the Empty Base Class Optimization.
@@ -192,9 +205,29 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
   using StorageT = internal_compressed_tuple::Storage<ElemT<I>, I>;
 
  public:
+  // There seems to be a bug in MSVC dealing in which using '=default' here will
+  // cause the compiler to ignore the body of other constructors. The work-
+  // around is to explicitly implement the default constructor.
+#if defined(_MSC_VER)
+  constexpr CompressedTuple() : CompressedTuple::CompressedTupleImpl() {}
+#else
   constexpr CompressedTuple() = default;
-  explicit constexpr CompressedTuple(Ts... base)
-      : CompressedTuple::CompressedTupleImpl(absl::forward<Ts>(base)...) {}
+#endif
+  explicit constexpr CompressedTuple(const Ts&... base)
+      : CompressedTuple::CompressedTupleImpl(absl::in_place, base...) {}
+
+  template <typename... Vs,
+            absl::enable_if_t<
+                absl::conjunction<
+                    // Ensure we are not hiding default copy/move constructors.
+                    absl::negation<std::is_same<void(CompressedTuple),
+                                                void(absl::decay_t<Vs>...)>>,
+                    internal_compressed_tuple::TupleMoveConstructible<
+                        Ts, Vs&&>...>::value,
+                bool> = true>
+  explicit constexpr CompressedTuple(Vs&&... base)
+      : CompressedTuple::CompressedTupleImpl(absl::in_place,
+                                             absl::forward<Vs>(base)...) {}
 
   template <int I>
   ElemT<I>& get() & {