about summary refs log tree commit diff
path: root/absl/container/internal/compressed_tuple.h
diff options
context:
space:
mode:
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() & {