compressed_tuple.h
Go to the documentation of this file.
1 // Copyright 2018 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // Helper class to perform the Empty Base Optimization.
16 // Ts can contain classes and non-classes, empty or not. For the ones that
17 // are empty classes, we perform the optimization. If all types in Ts are empty
18 // classes, then CompressedTuple<Ts...> is itself an empty class.
19 //
20 // To access the members, use member get<N>() function.
21 //
22 // Eg:
23 // absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2,
24 // t3);
25 // assert(value.get<0>() == 7);
26 // T1& t1 = value.get<1>();
27 // const T2& t2 = value.get<2>();
28 // ...
29 //
30 // https://en.cppreference.com/w/cpp/language/ebo
31 
32 #ifndef ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
33 #define ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
34 
35 #include <tuple>
36 #include <type_traits>
37 #include <utility>
38 
39 #include "absl/utility/utility.h"
40 
41 #if defined(_MSC_VER) && !defined(__NVCC__)
42 // We need to mark these classes with this declspec to ensure that
43 // CompressedTuple happens.
44 #define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases)
45 #else
46 #define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
47 #endif
48 
49 namespace absl {
50 namespace container_internal {
51 
52 template <typename... Ts>
54 
55 namespace internal_compressed_tuple {
56 
57 template <typename D, size_t I>
58 struct Elem;
59 template <typename... B, size_t I>
60 struct Elem<CompressedTuple<B...>, I>
61  : std::tuple_element<I, std::tuple<B...>> {};
62 template <typename D, size_t I>
63 using ElemT = typename Elem<D, I>::type;
64 
65 // Use the __is_final intrinsic if available. Where it's not available, classes
66 // declared with the 'final' specifier cannot be used as CompressedTuple
67 // elements.
68 // TODO(sbenza): Replace this with std::is_final in C++14.
69 template <typename T>
70 constexpr bool IsFinal() {
71 #if defined(__clang__) || defined(__GNUC__)
72  return __is_final(T);
73 #else
74  return false;
75 #endif
76 }
77 
78 template <typename T>
79 constexpr bool ShouldUseBase() {
80  return std::is_class<T>::value && std::is_empty<T>::value && !IsFinal<T>();
81 }
82 
83 // The storage class provides two specializations:
84 // - For empty classes, it stores T as a base class.
85 // - For everything else, it stores T as a member.
86 template <typename D, size_t I, bool = ShouldUseBase<ElemT<D, I>>()>
87 struct Storage {
88  using T = ElemT<D, I>;
90  constexpr Storage() = default;
91  explicit constexpr Storage(T&& v) : value(absl::forward<T>(v)) {}
92  constexpr const T& get() const& { return value; }
93  T& get() & { return value; }
94  constexpr const T&& get() const&& { return absl::move(*this).value; }
95  T&& get() && { return std::move(*this).value; }
96 };
97 
98 template <typename D, size_t I>
100  : ElemT<D, I> {
102  constexpr Storage() = default;
103  explicit constexpr Storage(T&& v) : T(absl::forward<T>(v)) {}
104  constexpr const T& get() const& { return *this; }
105  T& get() & { return *this; }
106  constexpr const T&& get() const&& { return absl::move(*this); }
107  T&& get() && { return std::move(*this); }
108 };
109 
110 template <typename D, typename I>
112 
113 template <typename... Ts, size_t... I>
116  // We use the dummy identity function through std::integral_constant to
117  // convince MSVC of accepting and expanding I in that context. Without it
118  // you would get:
119  // error C3548: 'I': parameter pack cannot be used in this context
120  : Storage<CompressedTuple<Ts...>,
121  std::integral_constant<size_t, I>::value>... {
122  constexpr CompressedTupleImpl() = default;
123  explicit constexpr CompressedTupleImpl(Ts&&... args)
124  : Storage<CompressedTuple<Ts...>, I>(absl::forward<Ts>(args))... {}
125 };
126 
127 } // namespace internal_compressed_tuple
128 
129 // Helper class to perform the Empty Base Class Optimization.
130 // Ts can contain classes and non-classes, empty or not. For the ones that
131 // are empty classes, we perform the CompressedTuple. If all types in Ts are
132 // empty classes, then CompressedTuple<Ts...> is itself an empty class.
133 //
134 // To access the members, use member .get<N>() function.
135 //
136 // Eg:
137 // absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2,
138 // t3);
139 // assert(value.get<0>() == 7);
140 // T1& t1 = value.get<1>();
141 // const T2& t2 = value.get<2>();
142 // ...
143 //
144 // https://en.cppreference.com/w/cpp/language/ebo
145 template <typename... Ts>
146 class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
148  CompressedTuple<Ts...>, absl::index_sequence_for<Ts...>> {
149  private:
150  template <int I>
152 
153  public:
154  constexpr CompressedTuple() = default;
155  explicit constexpr CompressedTuple(Ts... base)
156  : CompressedTuple::CompressedTupleImpl(absl::forward<Ts>(base)...) {}
157 
158  template <int I>
159  ElemT<I>& get() & {
161  }
162 
163  template <int I>
164  constexpr const ElemT<I>& get() const& {
166  }
167 
168  template <int I>
169  ElemT<I>&& get() && {
170  return std::move(*this)
171  .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
172  }
173 
174  template <int I>
175  constexpr const ElemT<I>&& get() const&& {
176  return absl::move(*this)
177  .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
178  }
179 };
180 
181 // Explicit specialization for a zero-element tuple
182 // (needed to avoid ambiguous overloads for the default constructor).
183 template <>
184 class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple<> {};
185 
186 } // namespace container_internal
187 } // namespace absl
188 
189 #undef ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
190 
191 #endif // ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
int v
Definition: variant_test.cc:81
constexpr T && forward(absl::remove_reference_t< T > &t) noexcept
Definition: utility.h:228
Definition: algorithm.h:29
#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
size_t value
struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: utility.h:219


abseil_cpp
Author(s):
autogenerated on Mon Feb 28 2022 21:31:18