/src/abseil-cpp/absl/container/internal/compressed_tuple.h
Line | Count | Source (jump to first uncovered line) |
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 { |
51 | | ABSL_NAMESPACE_BEGIN |
52 | | namespace container_internal { |
53 | | |
54 | | template <typename... Ts> |
55 | | class CompressedTuple; |
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 | | |
68 | | template <typename T> |
69 | 0 | constexpr bool ShouldUseBase() { |
70 | 0 | return std::is_class<T>::value && std::is_empty<T>::value && |
71 | 0 | !std::is_final<T>::value; |
72 | 0 | } Unexecuted instantiation: bool absl::container_internal::internal_compressed_tuple::ShouldUseBase<std::__1::allocator<absl::LogSink*> >() Unexecuted instantiation: bool absl::container_internal::internal_compressed_tuple::ShouldUseBase<unsigned long>() Unexecuted instantiation: bool absl::container_internal::internal_compressed_tuple::ShouldUseBase<absl::LogSink**>() Unexecuted instantiation: bool absl::container_internal::internal_compressed_tuple::ShouldUseBase<std::__1::allocator<absl::str_format_internal::FormatArgImpl> >() Unexecuted instantiation: bool absl::container_internal::internal_compressed_tuple::ShouldUseBase<void (*)(std::__1::basic_string_view<char, std::__1::char_traits<char> >)>() Unexecuted instantiation: bool absl::container_internal::internal_compressed_tuple::ShouldUseBase<std::__1::allocator<char> >() |
73 | | |
74 | | // Tag type used to disambiguate Storage types for different CompresseedTuples. |
75 | | // Without it, CompressedTuple<T, CompressedTuple<T>> would inherit from |
76 | | // Storage<T, 0> twice. |
77 | | template <typename... Ts> |
78 | | struct StorageTag; |
79 | | |
80 | | // The storage class provides two specializations: |
81 | | // - For empty classes, it stores T as a base class. |
82 | | // - For everything else, it stores T as a member. |
83 | | // Tag should be set to StorageTag<Ts...>. |
84 | | template <typename T, size_t I, typename Tag, bool UseBase = ShouldUseBase<T>()> |
85 | | struct Storage { |
86 | | T value; |
87 | | constexpr Storage() = default; |
88 | | template <typename V> |
89 | | explicit constexpr Storage(absl::in_place_t, V&& v) |
90 | 0 | : value(std::forward<V>(v)) {} Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<unsigned long, 1ul, absl::container_internal::internal_compressed_tuple::StorageTag<std::__1::allocator<absl::LogSink*>, unsigned long>, false>::Storage<unsigned int>(std::__1::in_place_t, unsigned int&&) Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<absl::LogSink**, 1ul, absl::container_internal::internal_compressed_tuple::StorageTag<std::__1::allocator<absl::LogSink*>, absl::LogSink**>, false>::Storage<decltype(nullptr)>(std::__1::in_place_t, decltype(nullptr)&&) Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<unsigned long, 0ul, absl::container_internal::internal_compressed_tuple::StorageTag<unsigned long, std::__1::allocator<char> >, false>::Storage<unsigned long&>(std::__1::in_place_t, unsigned long&) Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<unsigned long, 1ul, absl::container_internal::internal_compressed_tuple::StorageTag<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, unsigned long>, false>::Storage<unsigned int>(std::__1::in_place_t, unsigned int&&) |
91 | 0 | constexpr const T& get() const& { return value; } Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<unsigned long, 1ul, absl::container_internal::internal_compressed_tuple::StorageTag<std::__1::allocator<absl::LogSink*>, unsigned long>, false>::get() const & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<unsigned long, 1ul, absl::container_internal::internal_compressed_tuple::StorageTag<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, unsigned long>, false>::get() const & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<unsigned long, 0ul, absl::container_internal::internal_compressed_tuple::StorageTag<unsigned long, std::__1::allocator<char> >, false>::get() const & |
92 | 0 | constexpr T& get() & { return value; } Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<unsigned long, 1ul, absl::container_internal::internal_compressed_tuple::StorageTag<std::__1::allocator<absl::LogSink*>, unsigned long>, false>::get() & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<absl::LogSink**, 1ul, absl::container_internal::internal_compressed_tuple::StorageTag<std::__1::allocator<absl::LogSink*>, absl::LogSink**>, false>::get() & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<unsigned long, 1ul, absl::container_internal::internal_compressed_tuple::StorageTag<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, unsigned long>, false>::get() & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<void (*)(std::__1::basic_string_view<char, std::__1::char_traits<char> >), 0ul, absl::container_internal::internal_compressed_tuple::StorageTag<void (*)(std::__1::basic_string_view<char, std::__1::char_traits<char> >)>, false>::get() & |
93 | | constexpr const T&& get() const&& { return std::move(*this).value; } |
94 | | constexpr T&& get() && { return std::move(*this).value; } |
95 | | }; |
96 | | |
97 | | template <typename T, size_t I, typename Tag> |
98 | | struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage<T, I, Tag, true> : T { |
99 | | constexpr Storage() = default; |
100 | | |
101 | | template <typename V> |
102 | 0 | explicit constexpr Storage(absl::in_place_t, V&& v) : T(std::forward<V>(v)) {} Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<std::__1::allocator<absl::LogSink*>, 0ul, absl::container_internal::internal_compressed_tuple::StorageTag<std::__1::allocator<absl::LogSink*>, unsigned long>, true>::Storage<std::__1::allocator<absl::LogSink*> >(std::__1::in_place_t, std::__1::allocator<absl::LogSink*>&&) Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<std::__1::allocator<absl::LogSink*>, 0ul, absl::container_internal::internal_compressed_tuple::StorageTag<std::__1::allocator<absl::LogSink*>, absl::LogSink**>, true>::Storage<std::__1::allocator<absl::LogSink*>&>(std::__1::in_place_t, std::__1::allocator<absl::LogSink*>&) Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<std::__1::allocator<char>, 1ul, absl::container_internal::internal_compressed_tuple::StorageTag<unsigned long, std::__1::allocator<char> >, true>::Storage<std::__1::allocator<char> const&>(std::__1::in_place_t, std::__1::allocator<char> const&) Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, 0ul, absl::container_internal::internal_compressed_tuple::StorageTag<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, unsigned long>, true>::Storage<std::__1::allocator<absl::str_format_internal::FormatArgImpl> const&>(std::__1::in_place_t, std::__1::allocator<absl::str_format_internal::FormatArgImpl> const&) |
103 | | |
104 | | constexpr const T& get() const& { return *this; } |
105 | 0 | constexpr T& get() & { return *this; } Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<std::__1::allocator<absl::LogSink*>, 0ul, absl::container_internal::internal_compressed_tuple::StorageTag<std::__1::allocator<absl::LogSink*>, unsigned long>, true>::get() & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<std::__1::allocator<absl::LogSink*>, 0ul, absl::container_internal::internal_compressed_tuple::StorageTag<std::__1::allocator<absl::LogSink*>, absl::LogSink**>, true>::get() & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, 0ul, absl::container_internal::internal_compressed_tuple::StorageTag<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, unsigned long>, true>::get() & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Storage<std::__1::allocator<char>, 1ul, absl::container_internal::internal_compressed_tuple::StorageTag<unsigned long, std::__1::allocator<char> >, true>::get() & |
106 | | constexpr const T&& get() const&& { return std::move(*this); } |
107 | | constexpr T&& get() && { return std::move(*this); } |
108 | | }; |
109 | | |
110 | | template <typename D, typename I, bool ShouldAnyUseBase> |
111 | | struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl; |
112 | | |
113 | | template <typename... Ts, size_t... I, bool ShouldAnyUseBase> |
114 | | struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC |
115 | | CompressedTupleImpl<CompressedTuple<Ts...>, absl::index_sequence<I...>, |
116 | | ShouldAnyUseBase> |
117 | | // We use the dummy identity function through std::integral_constant to |
118 | | // convince MSVC of accepting and expanding I in that context. Without it |
119 | | // you would get: |
120 | | // error C3548: 'I': parameter pack cannot be used in this context |
121 | | : Storage<Ts, std::integral_constant<size_t, I>::value, |
122 | | StorageTag<Ts...>>... { |
123 | | constexpr CompressedTupleImpl() = default; |
124 | | template <typename... Vs> |
125 | | explicit constexpr CompressedTupleImpl(absl::in_place_t, Vs&&... args) |
126 | 0 | : Storage<Ts, I, StorageTag<Ts...>>(absl::in_place, |
127 | 0 | std::forward<Vs>(args))... {} Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::CompressedTupleImpl<absl::container_internal::CompressedTuple<std::__1::allocator<absl::LogSink*>, unsigned long>, std::__1::integer_sequence<unsigned long, 0ul, 1ul>, true>::CompressedTupleImpl<std::__1::allocator<absl::LogSink*>, unsigned int>(std::__1::in_place_t, std::__1::allocator<absl::LogSink*>&&, unsigned int&&) Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::CompressedTupleImpl<absl::container_internal::CompressedTuple<std::__1::allocator<absl::LogSink*>, absl::LogSink**>, std::__1::integer_sequence<unsigned long, 0ul, 1ul>, true>::CompressedTupleImpl<std::__1::allocator<absl::LogSink*>&, decltype(nullptr)>(std::__1::in_place_t, std::__1::allocator<absl::LogSink*>&, decltype(nullptr)&&) Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::CompressedTupleImpl<absl::container_internal::CompressedTuple<unsigned long, std::__1::allocator<char> >, std::__1::integer_sequence<unsigned long, 0ul, 1ul>, true>::CompressedTupleImpl<unsigned long&, std::__1::allocator<char> const&>(std::__1::in_place_t, unsigned long&, std::__1::allocator<char> const&) Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::CompressedTupleImpl<absl::container_internal::CompressedTuple<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, unsigned long>, std::__1::integer_sequence<unsigned long, 0ul, 1ul>, true>::CompressedTupleImpl<std::__1::allocator<absl::str_format_internal::FormatArgImpl> const&, unsigned int>(std::__1::in_place_t, std::__1::allocator<absl::str_format_internal::FormatArgImpl> const&, unsigned int&&) |
128 | | friend CompressedTuple<Ts...>; |
129 | | }; |
130 | | |
131 | | template <typename... Ts, size_t... I> |
132 | | struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC |
133 | | CompressedTupleImpl<CompressedTuple<Ts...>, absl::index_sequence<I...>, |
134 | | false> |
135 | | // We use the dummy identity function as above... |
136 | | : Storage<Ts, std::integral_constant<size_t, I>::value, StorageTag<Ts...>, |
137 | | false>... { |
138 | | constexpr CompressedTupleImpl() = default; |
139 | | template <typename... Vs> |
140 | | explicit constexpr CompressedTupleImpl(absl::in_place_t, Vs&&... args) |
141 | | : Storage<Ts, I, StorageTag<Ts...>, false>(absl::in_place, |
142 | | std::forward<Vs>(args))... {} |
143 | | friend CompressedTuple<Ts...>; |
144 | | }; |
145 | | |
146 | | std::false_type Or(std::initializer_list<std::false_type>); |
147 | | std::true_type Or(std::initializer_list<bool>); |
148 | | |
149 | | // MSVC requires this to be done separately rather than within the declaration |
150 | | // of CompressedTuple below. |
151 | | template <typename... Ts> |
152 | 0 | constexpr bool ShouldAnyUseBase() { |
153 | 0 | return decltype( |
154 | 0 | Or({std::integral_constant<bool, ShouldUseBase<Ts>()>()...})){}; |
155 | 0 | } Unexecuted instantiation: bool absl::container_internal::internal_compressed_tuple::ShouldAnyUseBase<std::__1::allocator<absl::LogSink*>, unsigned long>() Unexecuted instantiation: bool absl::container_internal::internal_compressed_tuple::ShouldAnyUseBase<std::__1::allocator<absl::LogSink*>, absl::LogSink**>() Unexecuted instantiation: bool absl::container_internal::internal_compressed_tuple::ShouldAnyUseBase<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, unsigned long>() Unexecuted instantiation: bool absl::container_internal::internal_compressed_tuple::ShouldAnyUseBase<void (*)(std::__1::basic_string_view<char, std::__1::char_traits<char> >)>() Unexecuted instantiation: bool absl::container_internal::internal_compressed_tuple::ShouldAnyUseBase<unsigned long, std::__1::allocator<char> >() |
156 | | |
157 | | template <typename T, typename V> |
158 | | using TupleElementMoveConstructible = |
159 | | typename std::conditional<std::is_reference<T>::value, |
160 | | std::is_convertible<V, T>, |
161 | | std::is_constructible<T, V&&>>::type; |
162 | | |
163 | | template <bool SizeMatches, class T, class... Vs> |
164 | | struct TupleMoveConstructible : std::false_type {}; |
165 | | |
166 | | template <class... Ts, class... Vs> |
167 | | struct TupleMoveConstructible<true, CompressedTuple<Ts...>, Vs...> |
168 | | : std::integral_constant< |
169 | | bool, absl::conjunction< |
170 | | TupleElementMoveConstructible<Ts, Vs&&>...>::value> {}; |
171 | | |
172 | | template <typename T> |
173 | | struct compressed_tuple_size; |
174 | | |
175 | | template <typename... Es> |
176 | | struct compressed_tuple_size<CompressedTuple<Es...>> |
177 | | : public std::integral_constant<std::size_t, sizeof...(Es)> {}; |
178 | | |
179 | | template <class T, class... Vs> |
180 | | struct TupleItemsMoveConstructible |
181 | | : std::integral_constant< |
182 | | bool, TupleMoveConstructible<compressed_tuple_size<T>::value == |
183 | | sizeof...(Vs), |
184 | | T, Vs...>::value> {}; |
185 | | |
186 | | } // namespace internal_compressed_tuple |
187 | | |
188 | | // Helper class to perform the Empty Base Class Optimization. |
189 | | // Ts can contain classes and non-classes, empty or not. For the ones that |
190 | | // are empty classes, we perform the CompressedTuple. If all types in Ts are |
191 | | // empty classes, then CompressedTuple<Ts...> is itself an empty class. |
192 | | // |
193 | | // To access the members, use member .get<N>() function. |
194 | | // |
195 | | // Eg: |
196 | | // absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2, |
197 | | // t3); |
198 | | // assert(value.get<0>() == 7); |
199 | | // T1& t1 = value.get<1>(); |
200 | | // const T2& t2 = value.get<2>(); |
201 | | // ... |
202 | | // |
203 | | // https://en.cppreference.com/w/cpp/language/ebo |
204 | | template <typename... Ts> |
205 | | class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple |
206 | | : private internal_compressed_tuple::CompressedTupleImpl< |
207 | | CompressedTuple<Ts...>, absl::index_sequence_for<Ts...>, |
208 | | internal_compressed_tuple::ShouldAnyUseBase<Ts...>()> { |
209 | | private: |
210 | | template <int I> |
211 | | using ElemT = internal_compressed_tuple::ElemT<CompressedTuple, I>; |
212 | | |
213 | | template <int I> |
214 | | using StorageT = internal_compressed_tuple::Storage< |
215 | | ElemT<I>, I, internal_compressed_tuple::StorageTag<Ts...>>; |
216 | | |
217 | | public: |
218 | | // There seems to be a bug in MSVC dealing in which using '=default' here will |
219 | | // cause the compiler to ignore the body of other constructors. The work- |
220 | | // around is to explicitly implement the default constructor. |
221 | | #if defined(_MSC_VER) |
222 | | constexpr CompressedTuple() : CompressedTuple::CompressedTupleImpl() {} |
223 | | #else |
224 | | constexpr CompressedTuple() = default; |
225 | | #endif |
226 | | explicit constexpr CompressedTuple(const Ts&... base) |
227 | | : CompressedTuple::CompressedTupleImpl(absl::in_place, base...) {} |
228 | | |
229 | | template <typename First, typename... Vs, |
230 | | absl::enable_if_t< |
231 | | absl::conjunction< |
232 | | // Ensure we are not hiding default copy/move constructors. |
233 | | absl::negation<std::is_same<void(CompressedTuple), |
234 | | void(absl::decay_t<First>)>>, |
235 | | internal_compressed_tuple::TupleItemsMoveConstructible< |
236 | | CompressedTuple<Ts...>, First, Vs...>>::value, |
237 | | bool> = true> |
238 | | explicit constexpr CompressedTuple(First&& first, Vs&&... base) |
239 | 0 | : CompressedTuple::CompressedTupleImpl(absl::in_place, |
240 | 0 | std::forward<First>(first), |
241 | 0 | std::forward<Vs>(base)...) {} Unexecuted instantiation: _ZN4absl18container_internal15CompressedTupleIJNSt3__19allocatorIPNS_7LogSinkEEEmEEC2IS6_JjETnNS2_9enable_ifIXsr4absl11conjunctionINS2_8negationINS2_7is_sameIFvS7_EFvu7__decayIT_EEEEEENS0_25internal_compressed_tuple27TupleItemsMoveConstructibleIS7_JSD_DpT0_EEEEE5valueEbE4typeELb1EEEOSD_DpOSK_ Unexecuted instantiation: _ZN4absl18container_internal15CompressedTupleIJNSt3__19allocatorIPNS_7LogSinkEEEPS5_EEC2IRS6_JDnETnNS2_9enable_ifIXsr4absl11conjunctionINS2_8negationINS2_7is_sameIFvS8_EFvu7__decayIT_EEEEEENS0_25internal_compressed_tuple27TupleItemsMoveConstructibleIS8_JSF_DpT0_EEEEE5valueEbE4typeELb1EEEOSF_DpOSM_ Unexecuted instantiation: _ZN4absl18container_internal15CompressedTupleIJmNSt3__19allocatorIcEEEEC2IRmJRKS4_ETnNS2_9enable_ifIXsr4absl11conjunctionINS2_8negationINS2_7is_sameIFvS5_EFvu7__decayIT_EEEEEENS0_25internal_compressed_tuple27TupleItemsMoveConstructibleIS5_JSE_DpT0_EEEEE5valueEbE4typeELb1EEEOSE_DpOSL_ Unexecuted instantiation: _ZN4absl18container_internal15CompressedTupleIJNSt3__19allocatorINS_19str_format_internal13FormatArgImplEEEmEEC2IRKS6_JjETnNS2_9enable_ifIXsr4absl11conjunctionINS2_8negationINS2_7is_sameIFvS7_EFvu7__decayIT_EEEEEENS0_25internal_compressed_tuple27TupleItemsMoveConstructibleIS7_JSF_DpT0_EEEEE5valueEbE4typeELb1EEEOSF_DpOSM_ |
242 | | |
243 | | template <int I> |
244 | 0 | constexpr ElemT<I>& get() & { |
245 | 0 | return StorageT<I>::get(); |
246 | 0 | } Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Elem<absl::container_internal::CompressedTuple<std::__1::allocator<absl::LogSink*>, unsigned long>, 1>::type& absl::container_internal::CompressedTuple<std::__1::allocator<absl::LogSink*>, unsigned long>::get<1>() & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Elem<absl::container_internal::CompressedTuple<std::__1::allocator<absl::LogSink*>, unsigned long>, 0>::type& absl::container_internal::CompressedTuple<std::__1::allocator<absl::LogSink*>, unsigned long>::get<0>() & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Elem<absl::container_internal::CompressedTuple<std::__1::allocator<absl::LogSink*>, absl::LogSink**>, 0>::type& absl::container_internal::CompressedTuple<std::__1::allocator<absl::LogSink*>, absl::LogSink**>::get<0>() & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Elem<absl::container_internal::CompressedTuple<std::__1::allocator<absl::LogSink*>, absl::LogSink**>, 1>::type& absl::container_internal::CompressedTuple<std::__1::allocator<absl::LogSink*>, absl::LogSink**>::get<1>() & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Elem<absl::container_internal::CompressedTuple<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, unsigned long>, 1>::type& absl::container_internal::CompressedTuple<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, unsigned long>::get<1>() & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Elem<absl::container_internal::CompressedTuple<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, unsigned long>, 0>::type& absl::container_internal::CompressedTuple<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, unsigned long>::get<0>() & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Elem<absl::container_internal::CompressedTuple<void (*)(std::__1::basic_string_view<char, std::__1::char_traits<char> >)>, 0>::type& absl::container_internal::CompressedTuple<void (*)(std::__1::basic_string_view<char, std::__1::char_traits<char> >)>::get<0>() & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Elem<absl::container_internal::CompressedTuple<unsigned long, std::__1::allocator<char> >, 1>::type& absl::container_internal::CompressedTuple<unsigned long, std::__1::allocator<char> >::get<1>() & |
247 | | |
248 | | template <int I> |
249 | 0 | constexpr const ElemT<I>& get() const& { |
250 | 0 | return StorageT<I>::get(); |
251 | 0 | } Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Elem<absl::container_internal::CompressedTuple<std::__1::allocator<absl::LogSink*>, unsigned long>, 1>::type const& absl::container_internal::CompressedTuple<std::__1::allocator<absl::LogSink*>, unsigned long>::get<1>() const & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Elem<absl::container_internal::CompressedTuple<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, unsigned long>, 1>::type const& absl::container_internal::CompressedTuple<std::__1::allocator<absl::str_format_internal::FormatArgImpl>, unsigned long>::get<1>() const & Unexecuted instantiation: absl::container_internal::internal_compressed_tuple::Elem<absl::container_internal::CompressedTuple<unsigned long, std::__1::allocator<char> >, 0>::type const& absl::container_internal::CompressedTuple<unsigned long, std::__1::allocator<char> >::get<0>() const & |
252 | | |
253 | | template <int I> |
254 | | constexpr ElemT<I>&& get() && { |
255 | | return std::move(*this).StorageT<I>::get(); |
256 | | } |
257 | | |
258 | | template <int I> |
259 | | constexpr const ElemT<I>&& get() const&& { |
260 | | return std::move(*this).StorageT<I>::get(); |
261 | | } |
262 | | }; |
263 | | |
264 | | // Explicit specialization for a zero-element tuple |
265 | | // (needed to avoid ambiguous overloads for the default constructor). |
266 | | template <> |
267 | | class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple<> {}; |
268 | | |
269 | | } // namespace container_internal |
270 | | ABSL_NAMESPACE_END |
271 | | } // namespace absl |
272 | | |
273 | | #undef ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC |
274 | | |
275 | | #endif // ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_ |