abseil-cpp/absl/container/internal/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 <initializer_list>
36 #include <tuple>
37 #include <type_traits>
38 #include <utility>
39 
40 #include "absl/utility/utility.h"
41 
42 #if defined(_MSC_VER) && !defined(__NVCC__)
43 // We need to mark these classes with this declspec to ensure that
44 // CompressedTuple happens.
45 #define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases)
46 #else
47 #define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
48 #endif
49 
50 namespace absl {
52 namespace container_internal {
53 
54 template <typename... Ts>
56 
57 namespace internal_compressed_tuple {
58 
59 template <typename D, size_t I>
60 struct Elem;
61 template <typename... B, size_t I>
62 struct Elem<CompressedTuple<B...>, I>
63  : std::tuple_element<I, std::tuple<B...>> {};
64 template <typename D, size_t I>
65 using ElemT = typename Elem<D, I>::type;
66 
67 // Use the __is_final intrinsic if available. Where it's not available, classes
68 // declared with the 'final' specifier cannot be used as CompressedTuple
69 // elements.
70 // TODO(sbenza): Replace this with std::is_final in C++14.
71 template <typename T>
72 constexpr bool IsFinal() {
73 #if defined(__clang__) || defined(__GNUC__)
74  return __is_final(T);
75 #else
76  return false;
77 #endif
78 }
79 
80 // We can't use EBCO on other CompressedTuples because that would mean that we
81 // derive from multiple Storage<> instantiations with the same I parameter,
82 // and potentially from multiple identical Storage<> instantiations. So anytime
83 // we use type inheritance rather than encapsulation, we mark
84 // CompressedTupleImpl, to make this easy to detect.
85 struct uses_inheritance {};
86 
87 template <typename T>
88 constexpr bool ShouldUseBase() {
89  return std::is_class<T>::value && std::is_empty<T>::value && !IsFinal<T>() &&
91 }
92 
93 // The storage class provides two specializations:
94 // - For empty classes, it stores T as a base class.
95 // - For everything else, it stores T as a member.
96 template <typename T, size_t I,
97 #if defined(_MSC_VER)
98  bool UseBase =
100 #else
101  bool UseBase = ShouldUseBase<T>()>
102 #endif
103 struct Storage {
105  constexpr Storage() = default;
106  template <typename V>
107  explicit constexpr Storage(absl::in_place_t, V&& v)
108  : value(absl::forward<V>(v)) {}
109  constexpr const T& get() const& { return value; }
110  T& get() & { return value; }
111  constexpr const T&& get() const&& { return absl::move(*this).value; }
112  T&& get() && { return std::move(*this).value; }
113 };
114 
115 template <typename T, size_t I>
117  constexpr Storage() = default;
118 
119  template <typename V>
120  explicit constexpr Storage(absl::in_place_t, V&& v)
121  : T(absl::forward<V>(v)) {}
122 
123  constexpr const T& get() const& { return *this; }
124  T& get() & { return *this; }
125  constexpr const T&& get() const&& { return absl::move(*this); }
126  T&& get() && { return std::move(*this); }
127 };
128 
129 template <typename D, typename I, bool ShouldAnyUseBase>
131 
132 template <typename... Ts, size_t... I, bool ShouldAnyUseBase>
135  // We use the dummy identity function through std::integral_constant to
136  // convince MSVC of accepting and expanding I in that context. Without it
137  // you would get:
138  // error C3548: 'I': parameter pack cannot be used in this context
140  Storage<Ts, std::integral_constant<size_t, I>::value>... {
141  constexpr CompressedTupleImpl() = default;
142  template <typename... Vs>
143  explicit constexpr CompressedTupleImpl(absl::in_place_t, Vs&&... args)
144  : Storage<Ts, I>(absl::in_place, absl::forward<Vs>(args))... {}
145  friend CompressedTuple<Ts...>;
146 };
147 
148 template <typename... Ts, size_t... I>
150  CompressedTuple<Ts...>, absl::index_sequence<I...>, false>
151  // We use the dummy identity function as above...
152  : Storage<Ts, std::integral_constant<size_t, I>::value, false>... {
153  constexpr CompressedTupleImpl() = default;
154  template <typename... Vs>
155  explicit constexpr CompressedTupleImpl(absl::in_place_t, Vs&&... args)
156  : Storage<Ts, I, false>(absl::in_place, absl::forward<Vs>(args))... {}
157  friend CompressedTuple<Ts...>;
158 };
159 
160 std::false_type Or(std::initializer_list<std::false_type>);
161 std::true_type Or(std::initializer_list<bool>);
162 
163 // MSVC requires this to be done separately rather than within the declaration
164 // of CompressedTuple below.
165 template <typename... Ts>
166 constexpr bool ShouldAnyUseBase() {
167  return decltype(
168  Or({std::integral_constant<bool, ShouldUseBase<Ts>()>()...})){};
169 }
170 
171 template <typename T, typename V>
174  std::is_convertible<V, T>,
175  std::is_constructible<T, V&&>>::type;
176 
177 template <bool SizeMatches, class T, class... Vs>
179 
180 template <class... Ts, class... Vs>
182  : std::integral_constant<
183  bool, absl::conjunction<
184  TupleElementMoveConstructible<Ts, Vs&&>...>::value> {};
185 
186 template <typename T>
188 
189 template <typename... Es>
191  : public std::integral_constant<std::size_t, sizeof...(Es)> {};
192 
193 template <class T, class... Vs>
195  : std::integral_constant<
196  bool, TupleMoveConstructible<compressed_tuple_size<T>::value ==
197  sizeof...(Vs),
198  T, Vs...>::value> {};
199 
200 } // namespace internal_compressed_tuple
201 
202 // Helper class to perform the Empty Base Class Optimization.
203 // Ts can contain classes and non-classes, empty or not. For the ones that
204 // are empty classes, we perform the CompressedTuple. If all types in Ts are
205 // empty classes, then CompressedTuple<Ts...> is itself an empty class. (This
206 // does not apply when one or more of those empty classes is itself an empty
207 // CompressedTuple.)
208 //
209 // To access the members, use member .get<N>() function.
210 //
211 // Eg:
212 // absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2,
213 // t3);
214 // assert(value.get<0>() == 7);
215 // T1& t1 = value.get<1>();
216 // const T2& t2 = value.get<2>();
217 // ...
218 //
219 // https://en.cppreference.com/w/cpp/language/ebo
220 template <typename... Ts>
223  CompressedTuple<Ts...>, absl::index_sequence_for<Ts...>,
224  internal_compressed_tuple::ShouldAnyUseBase<Ts...>()> {
225  private:
226  template <int I>
228 
229  template <int I>
231 
232  public:
233  // There seems to be a bug in MSVC dealing in which using '=default' here will
234  // cause the compiler to ignore the body of other constructors. The work-
235  // around is to explicitly implement the default constructor.
236 #if defined(_MSC_VER)
238 #else
239  constexpr CompressedTuple() = default;
240 #endif
241  explicit constexpr CompressedTuple(const Ts&... base)
242  : CompressedTuple::CompressedTupleImpl(absl::in_place, base...) {}
243 
244  template <typename First, typename... Vs,
247  // Ensure we are not hiding default copy/move constructors.
248  absl::negation<std::is_same<void(CompressedTuple),
249  void(absl::decay_t<First>)>>,
251  CompressedTuple<Ts...>, First, Vs...>>::value,
252  bool> = true>
253  explicit constexpr CompressedTuple(First&& first, Vs&&... base)
255  absl::forward<First>(first),
256  absl::forward<Vs>(base)...) {}
257 
258  template <int I>
259  ElemT<I>& get() & {
260  return StorageT<I>::get();
261  }
262 
263  template <int I>
264  constexpr const ElemT<I>& get() const& {
265  return StorageT<I>::get();
266  }
267 
268  template <int I>
269  ElemT<I>&& get() && {
270  return std::move(*this).StorageT<I>::get();
271  }
272 
273  template <int I>
274  constexpr const ElemT<I>&& get() const&& {
275  return absl::move(*this).StorageT<I>::get();
276  }
277 };
278 
279 // Explicit specialization for a zero-element tuple
280 // (needed to avoid ambiguous overloads for the default constructor).
281 template <>
283 
284 } // namespace container_internal
286 } // namespace absl
287 
288 #undef ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
289 
290 #endif // ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
absl::decay_t
typename std::decay< T >::type decay_t
Definition: abseil-cpp/absl/meta/type_traits.h:628
absl::container_internal::internal_compressed_tuple::CompressedTupleImpl< CompressedTuple< Ts... >, absl::index_sequence< I... >, ShouldAnyUseBase >::CompressedTupleImpl
constexpr CompressedTupleImpl(absl::in_place_t, Vs &&... args)
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:143
absl::container_internal::internal_compressed_tuple::IsFinal
constexpr bool IsFinal()
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:72
absl::container_internal::CompressedTuple::get
ElemT< I > && get() &&
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:269
get
absl::string_view get(const Cont &c)
Definition: abseil-cpp/absl/strings/str_replace_test.cc:185
absl::container_internal::internal_compressed_tuple::Storage::value
T value
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:104
const
#define const
Definition: bloaty/third_party/zlib/zconf.h:230
absl::conjunction
Definition: abseil-cpp/absl/meta/type_traits.h:230
false
#define false
Definition: setup_once.h:323
absl::container_internal::internal_compressed_tuple::Storage::Storage
constexpr Storage()=default
absl::container_internal::internal_compressed_tuple::Storage< T, I, true >::get
T & get() &
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:124
google::protobuf.internal::true_type
integral_constant< bool, true > true_type
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/template_util.h:89
google::protobuf.internal::false_type
integral_constant< bool, false > false_type
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/template_util.h:90
absl::container_internal::internal_compressed_tuple::compressed_tuple_size
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:187
absl::container_internal::internal_compressed_tuple::Storage::get
T & get() &
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:110
absl::negation
Definition: abseil-cpp/absl/meta/type_traits.h:266
absl::enable_if_t
typename std::enable_if< B, T >::type enable_if_t
Definition: abseil-cpp/absl/meta/type_traits.h:631
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
T
#define T(upbtypeconst, upbtype, ctype, default_value)
true
#define true
Definition: setup_once.h:324
absl::container_internal::internal_compressed_tuple::TupleItemsMoveConstructible
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:194
absl::container_internal::CompressedTuple::get
ElemT< I > & get() &
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:259
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
absl::container_internal::internal_compressed_tuple::CompressedTupleImpl< CompressedTuple< Ts... >, absl::index_sequence< I... >, false >::CompressedTupleImpl
constexpr CompressedTupleImpl(absl::in_place_t, Vs &&... args)
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:155
absl::integer_sequence
Definition: abseil-cpp/absl/utility/utility.h:76
absl::container_internal::CompressedTuple::get
constexpr const ElemT< I > & get() const &
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:264
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
absl::container_internal::internal_compressed_tuple::TupleElementMoveConstructible
typename std::conditional< std::is_reference< T >::value, std::is_convertible< V, T >, std::is_constructible< T, V && > >::type TupleElementMoveConstructible
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:175
absl::container_internal::internal_compressed_tuple::uses_inheritance
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:85
absl::container_internal::internal_compressed_tuple::Or
std::false_type Or(std::initializer_list< std::false_type >)
gen_synthetic_protos.base
base
Definition: gen_synthetic_protos.py:31
absl::container_internal::CompressedTuple
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:55
absl::container_internal::internal_compressed_tuple::ShouldAnyUseBase
constexpr bool ShouldAnyUseBase()
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:166
absl::container_internal::internal_compressed_tuple::Storage
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:103
value
const char * value
Definition: hpack_parser_table.cc:165
absl::container_internal::internal_compressed_tuple::CompressedTupleImpl
struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:130
absl::container_internal::CompressedTuple::get
constexpr const ElemT< I > && get() const &&
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:274
absl::container_internal::internal_compressed_tuple::Storage< T, I, true >::get
constexpr const T & get() const &
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:123
I
#define I(b, c, d)
Definition: md5.c:120
absl::container_internal::internal_compressed_tuple::Elem
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:60
absl::container_internal::internal_compressed_tuple::Storage::get
constexpr const T && get() const &&
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:111
absl::container_internal::CompressedTuple<>
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:282
first
StrT first
Definition: cxa_demangle.cpp:4884
absl::container_internal::internal_compressed_tuple::TupleMoveConstructible
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:178
absl::container_internal::internal_compressed_tuple::Storage< T, I, true >::get
constexpr const T && get() const &&
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:125
absl::container_internal::internal_compressed_tuple::ElemT
typename Elem< D, I >::type ElemT
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:65
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::container_internal::CompressedTuple::CompressedTuple
constexpr CompressedTuple(const Ts &... base)
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:241
absl::in_place_t
Definition: abseil-cpp/absl/utility/utility.h:174
ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:47
absl::forward
constexpr T && forward(absl::remove_reference_t< T > &t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:230
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
absl::container_internal::internal_compressed_tuple::Storage::get
constexpr const T & get() const &
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:109
absl::container_internal::CompressedTuple::CompressedTuple
constexpr CompressedTuple(First &&first, Vs &&... base)
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:253
absl::container_internal::CompressedTuple< std::allocator< grpc_metadata >, SizeType< std::allocator< grpc_metadata > > >::ElemT
internal_compressed_tuple::ElemT< CompressedTuple, I > ElemT
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:227
absl::container_internal::internal_compressed_tuple::Storage< T, I, true >::Storage
constexpr Storage(absl::in_place_t, V &&v)
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:120
absl::container_internal::internal_compressed_tuple::ShouldUseBase
constexpr bool ShouldUseBase()
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:88
absl::container_internal::internal_compressed_tuple::Storage::Storage
constexpr Storage(absl::in_place_t, V &&v)
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:107
absl::container_internal::internal_compressed_tuple::Storage::get
T && get() &&
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:112
absl::container_internal::internal_compressed_tuple::Storage< T, I, true >::get
T && get() &&
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:126


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:00