xref: /aosp_15_r20/external/abseil-cpp/absl/container/internal/layout.h (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker // Copyright 2018 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker //      https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker //
15*9356374aSAndroid Build Coastguard Worker //                           MOTIVATION AND TUTORIAL
16*9356374aSAndroid Build Coastguard Worker //
17*9356374aSAndroid Build Coastguard Worker // If you want to put in a single heap allocation N doubles followed by M ints,
18*9356374aSAndroid Build Coastguard Worker // it's easy if N and M are known at compile time.
19*9356374aSAndroid Build Coastguard Worker //
20*9356374aSAndroid Build Coastguard Worker //   struct S {
21*9356374aSAndroid Build Coastguard Worker //     double a[N];
22*9356374aSAndroid Build Coastguard Worker //     int b[M];
23*9356374aSAndroid Build Coastguard Worker //   };
24*9356374aSAndroid Build Coastguard Worker //
25*9356374aSAndroid Build Coastguard Worker //   S* p = new S;
26*9356374aSAndroid Build Coastguard Worker //
27*9356374aSAndroid Build Coastguard Worker // But what if N and M are known only in run time? Class template Layout to the
28*9356374aSAndroid Build Coastguard Worker // rescue! It's a portable generalization of the technique known as struct hack.
29*9356374aSAndroid Build Coastguard Worker //
30*9356374aSAndroid Build Coastguard Worker //   // This object will tell us everything we need to know about the memory
31*9356374aSAndroid Build Coastguard Worker //   // layout of double[N] followed by int[M]. It's structurally identical to
32*9356374aSAndroid Build Coastguard Worker //   // size_t[2] that stores N and M. It's very cheap to create.
33*9356374aSAndroid Build Coastguard Worker //   const Layout<double, int> layout(N, M);
34*9356374aSAndroid Build Coastguard Worker //
35*9356374aSAndroid Build Coastguard Worker //   // Allocate enough memory for both arrays. `AllocSize()` tells us how much
36*9356374aSAndroid Build Coastguard Worker //   // memory is needed. We are free to use any allocation function we want as
37*9356374aSAndroid Build Coastguard Worker //   // long as it returns aligned memory.
38*9356374aSAndroid Build Coastguard Worker //   std::unique_ptr<unsigned char[]> p(new unsigned char[layout.AllocSize()]);
39*9356374aSAndroid Build Coastguard Worker //
40*9356374aSAndroid Build Coastguard Worker //   // Obtain the pointer to the array of doubles.
41*9356374aSAndroid Build Coastguard Worker //   // Equivalent to `reinterpret_cast<double*>(p.get())`.
42*9356374aSAndroid Build Coastguard Worker //   //
43*9356374aSAndroid Build Coastguard Worker //   // We could have written layout.Pointer<0>(p) instead. If all the types are
44*9356374aSAndroid Build Coastguard Worker //   // unique you can use either form, but if some types are repeated you must
45*9356374aSAndroid Build Coastguard Worker //   // use the index form.
46*9356374aSAndroid Build Coastguard Worker //   double* a = layout.Pointer<double>(p.get());
47*9356374aSAndroid Build Coastguard Worker //
48*9356374aSAndroid Build Coastguard Worker //   // Obtain the pointer to the array of ints.
49*9356374aSAndroid Build Coastguard Worker //   // Equivalent to `reinterpret_cast<int*>(p.get() + N * 8)`.
50*9356374aSAndroid Build Coastguard Worker //   int* b = layout.Pointer<int>(p);
51*9356374aSAndroid Build Coastguard Worker //
52*9356374aSAndroid Build Coastguard Worker // If we are unable to specify sizes of all fields, we can pass as many sizes as
53*9356374aSAndroid Build Coastguard Worker // we can to `Partial()`. In return, it'll allow us to access the fields whose
54*9356374aSAndroid Build Coastguard Worker // locations and sizes can be computed from the provided information.
55*9356374aSAndroid Build Coastguard Worker // `Partial()` comes in handy when the array sizes are embedded into the
56*9356374aSAndroid Build Coastguard Worker // allocation.
57*9356374aSAndroid Build Coastguard Worker //
58*9356374aSAndroid Build Coastguard Worker //   // size_t[0] containing N, size_t[1] containing M, double[N], int[M].
59*9356374aSAndroid Build Coastguard Worker //   using L = Layout<size_t, size_t, double, int>;
60*9356374aSAndroid Build Coastguard Worker //
61*9356374aSAndroid Build Coastguard Worker //   unsigned char* Allocate(size_t n, size_t m) {
62*9356374aSAndroid Build Coastguard Worker //     const L layout(1, 1, n, m);
63*9356374aSAndroid Build Coastguard Worker //     unsigned char* p = new unsigned char[layout.AllocSize()];
64*9356374aSAndroid Build Coastguard Worker //     *layout.Pointer<0>(p) = n;
65*9356374aSAndroid Build Coastguard Worker //     *layout.Pointer<1>(p) = m;
66*9356374aSAndroid Build Coastguard Worker //     return p;
67*9356374aSAndroid Build Coastguard Worker //   }
68*9356374aSAndroid Build Coastguard Worker //
69*9356374aSAndroid Build Coastguard Worker //   void Use(unsigned char* p) {
70*9356374aSAndroid Build Coastguard Worker //     // First, extract N and M.
71*9356374aSAndroid Build Coastguard Worker //     // Specify that the first array has only one element. Using `prefix` we
72*9356374aSAndroid Build Coastguard Worker //     // can access the first two arrays but not more.
73*9356374aSAndroid Build Coastguard Worker //     constexpr auto prefix = L::Partial(1);
74*9356374aSAndroid Build Coastguard Worker //     size_t n = *prefix.Pointer<0>(p);
75*9356374aSAndroid Build Coastguard Worker //     size_t m = *prefix.Pointer<1>(p);
76*9356374aSAndroid Build Coastguard Worker //
77*9356374aSAndroid Build Coastguard Worker //     // Now we can get pointers to the payload.
78*9356374aSAndroid Build Coastguard Worker //     const L layout(1, 1, n, m);
79*9356374aSAndroid Build Coastguard Worker //     double* a = layout.Pointer<double>(p);
80*9356374aSAndroid Build Coastguard Worker //     int* b = layout.Pointer<int>(p);
81*9356374aSAndroid Build Coastguard Worker //   }
82*9356374aSAndroid Build Coastguard Worker //
83*9356374aSAndroid Build Coastguard Worker // The layout we used above combines fixed-size with dynamically-sized fields.
84*9356374aSAndroid Build Coastguard Worker // This is quite common. Layout is optimized for this use case and attempts to
85*9356374aSAndroid Build Coastguard Worker // generate optimal code. To help the compiler do that in more cases, you can
86*9356374aSAndroid Build Coastguard Worker // specify the fixed sizes using `WithStaticSizes`. This ensures that all
87*9356374aSAndroid Build Coastguard Worker // computations that can be performed at compile time are indeed performed at
88*9356374aSAndroid Build Coastguard Worker // compile time. Note that sometimes the `template` keyword is needed. E.g.:
89*9356374aSAndroid Build Coastguard Worker //
90*9356374aSAndroid Build Coastguard Worker //   using SL = L::template WithStaticSizes<1, 1>;
91*9356374aSAndroid Build Coastguard Worker //
92*9356374aSAndroid Build Coastguard Worker //   void Use(unsigned char* p) {
93*9356374aSAndroid Build Coastguard Worker //     // First, extract N and M.
94*9356374aSAndroid Build Coastguard Worker //     // Using `prefix` we can access the first three arrays but not more.
95*9356374aSAndroid Build Coastguard Worker //     //
96*9356374aSAndroid Build Coastguard Worker //     // More details: The first element always has offset 0. `SL`
97*9356374aSAndroid Build Coastguard Worker //     // has offsets for the second and third array based on sizes of
98*9356374aSAndroid Build Coastguard Worker //     // the first and second array, specified via `WithStaticSizes`.
99*9356374aSAndroid Build Coastguard Worker //     constexpr auto prefix = SL::Partial();
100*9356374aSAndroid Build Coastguard Worker //     size_t n = *prefix.Pointer<0>(p);
101*9356374aSAndroid Build Coastguard Worker //     size_t m = *prefix.Pointer<1>(p);
102*9356374aSAndroid Build Coastguard Worker //
103*9356374aSAndroid Build Coastguard Worker //     // Now we can get a pointer to the final payload.
104*9356374aSAndroid Build Coastguard Worker //     const SL layout(n, m);
105*9356374aSAndroid Build Coastguard Worker //     double* a = layout.Pointer<double>(p);
106*9356374aSAndroid Build Coastguard Worker //     int* b = layout.Pointer<int>(p);
107*9356374aSAndroid Build Coastguard Worker //   }
108*9356374aSAndroid Build Coastguard Worker //
109*9356374aSAndroid Build Coastguard Worker // Efficiency tip: The order of fields matters. In `Layout<T1, ..., TN>` try to
110*9356374aSAndroid Build Coastguard Worker // ensure that `alignof(T1) >= ... >= alignof(TN)`. This way you'll have no
111*9356374aSAndroid Build Coastguard Worker // padding in between arrays.
112*9356374aSAndroid Build Coastguard Worker //
113*9356374aSAndroid Build Coastguard Worker // You can manually override the alignment of an array by wrapping the type in
114*9356374aSAndroid Build Coastguard Worker // `Aligned<T, N>`. `Layout<..., Aligned<T, N>, ...>` has exactly the same API
115*9356374aSAndroid Build Coastguard Worker // and behavior as `Layout<..., T, ...>` except that the first element of the
116*9356374aSAndroid Build Coastguard Worker // array of `T` is aligned to `N` (the rest of the elements follow without
117*9356374aSAndroid Build Coastguard Worker // padding). `N` cannot be less than `alignof(T)`.
118*9356374aSAndroid Build Coastguard Worker //
119*9356374aSAndroid Build Coastguard Worker // `AllocSize()` and `Pointer()` are the most basic methods for dealing with
120*9356374aSAndroid Build Coastguard Worker // memory layouts. Check out the reference or code below to discover more.
121*9356374aSAndroid Build Coastguard Worker //
122*9356374aSAndroid Build Coastguard Worker //                            EXAMPLE
123*9356374aSAndroid Build Coastguard Worker //
124*9356374aSAndroid Build Coastguard Worker //   // Immutable move-only string with sizeof equal to sizeof(void*). The
125*9356374aSAndroid Build Coastguard Worker //   // string size and the characters are kept in the same heap allocation.
126*9356374aSAndroid Build Coastguard Worker //   class CompactString {
127*9356374aSAndroid Build Coastguard Worker //    public:
128*9356374aSAndroid Build Coastguard Worker //     CompactString(const char* s = "") {
129*9356374aSAndroid Build Coastguard Worker //       const size_t size = strlen(s);
130*9356374aSAndroid Build Coastguard Worker //       // size_t[1] followed by char[size + 1].
131*9356374aSAndroid Build Coastguard Worker //       const L layout(size + 1);
132*9356374aSAndroid Build Coastguard Worker //       p_.reset(new unsigned char[layout.AllocSize()]);
133*9356374aSAndroid Build Coastguard Worker //       // If running under ASAN, mark the padding bytes, if any, to catch
134*9356374aSAndroid Build Coastguard Worker //       // memory errors.
135*9356374aSAndroid Build Coastguard Worker //       layout.PoisonPadding(p_.get());
136*9356374aSAndroid Build Coastguard Worker //       // Store the size in the allocation.
137*9356374aSAndroid Build Coastguard Worker //       *layout.Pointer<size_t>(p_.get()) = size;
138*9356374aSAndroid Build Coastguard Worker //       // Store the characters in the allocation.
139*9356374aSAndroid Build Coastguard Worker //       memcpy(layout.Pointer<char>(p_.get()), s, size + 1);
140*9356374aSAndroid Build Coastguard Worker //     }
141*9356374aSAndroid Build Coastguard Worker //
142*9356374aSAndroid Build Coastguard Worker //     size_t size() const {
143*9356374aSAndroid Build Coastguard Worker //       // Equivalent to reinterpret_cast<size_t&>(*p).
144*9356374aSAndroid Build Coastguard Worker //       return *L::Partial().Pointer<size_t>(p_.get());
145*9356374aSAndroid Build Coastguard Worker //     }
146*9356374aSAndroid Build Coastguard Worker //
147*9356374aSAndroid Build Coastguard Worker //     const char* c_str() const {
148*9356374aSAndroid Build Coastguard Worker //       // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)).
149*9356374aSAndroid Build Coastguard Worker //       return L::Partial().Pointer<char>(p_.get());
150*9356374aSAndroid Build Coastguard Worker //     }
151*9356374aSAndroid Build Coastguard Worker //
152*9356374aSAndroid Build Coastguard Worker //    private:
153*9356374aSAndroid Build Coastguard Worker //     // Our heap allocation contains a single size_t followed by an array of
154*9356374aSAndroid Build Coastguard Worker //     // chars.
155*9356374aSAndroid Build Coastguard Worker //     using L = Layout<size_t, char>::WithStaticSizes<1>;
156*9356374aSAndroid Build Coastguard Worker //     std::unique_ptr<unsigned char[]> p_;
157*9356374aSAndroid Build Coastguard Worker //   };
158*9356374aSAndroid Build Coastguard Worker //
159*9356374aSAndroid Build Coastguard Worker //   int main() {
160*9356374aSAndroid Build Coastguard Worker //     CompactString s = "hello";
161*9356374aSAndroid Build Coastguard Worker //     assert(s.size() == 5);
162*9356374aSAndroid Build Coastguard Worker //     assert(strcmp(s.c_str(), "hello") == 0);
163*9356374aSAndroid Build Coastguard Worker //   }
164*9356374aSAndroid Build Coastguard Worker //
165*9356374aSAndroid Build Coastguard Worker //                               DOCUMENTATION
166*9356374aSAndroid Build Coastguard Worker //
167*9356374aSAndroid Build Coastguard Worker // The interface exported by this file consists of:
168*9356374aSAndroid Build Coastguard Worker // - class `Layout<>` and its public members.
169*9356374aSAndroid Build Coastguard Worker // - The public members of classes `internal_layout::LayoutWithStaticSizes<>`
170*9356374aSAndroid Build Coastguard Worker //   and `internal_layout::LayoutImpl<>`. Those classes aren't intended to be
171*9356374aSAndroid Build Coastguard Worker //   used directly, and their name and template parameter list are internal
172*9356374aSAndroid Build Coastguard Worker //   implementation details, but the classes themselves provide most of the
173*9356374aSAndroid Build Coastguard Worker //   functionality in this file. See comments on their members for detailed
174*9356374aSAndroid Build Coastguard Worker //   documentation.
175*9356374aSAndroid Build Coastguard Worker //
176*9356374aSAndroid Build Coastguard Worker // `Layout<T1,... Tn>::Partial(count1,..., countm)` (where `m` <= `n`) returns a
177*9356374aSAndroid Build Coastguard Worker // `LayoutImpl<>` object. `Layout<T1,..., Tn> layout(count1,..., countn)`
178*9356374aSAndroid Build Coastguard Worker // creates a `Layout` object, which exposes the same functionality by inheriting
179*9356374aSAndroid Build Coastguard Worker // from `LayoutImpl<>`.
180*9356374aSAndroid Build Coastguard Worker 
181*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_CONTAINER_INTERNAL_LAYOUT_H_
182*9356374aSAndroid Build Coastguard Worker #define ABSL_CONTAINER_INTERNAL_LAYOUT_H_
183*9356374aSAndroid Build Coastguard Worker 
184*9356374aSAndroid Build Coastguard Worker #include <assert.h>
185*9356374aSAndroid Build Coastguard Worker #include <stddef.h>
186*9356374aSAndroid Build Coastguard Worker #include <stdint.h>
187*9356374aSAndroid Build Coastguard Worker 
188*9356374aSAndroid Build Coastguard Worker #include <array>
189*9356374aSAndroid Build Coastguard Worker #include <string>
190*9356374aSAndroid Build Coastguard Worker #include <tuple>
191*9356374aSAndroid Build Coastguard Worker #include <type_traits>
192*9356374aSAndroid Build Coastguard Worker #include <typeinfo>
193*9356374aSAndroid Build Coastguard Worker #include <utility>
194*9356374aSAndroid Build Coastguard Worker 
195*9356374aSAndroid Build Coastguard Worker #include "absl/base/attributes.h"
196*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
197*9356374aSAndroid Build Coastguard Worker #include "absl/debugging/internal/demangle.h"
198*9356374aSAndroid Build Coastguard Worker #include "absl/meta/type_traits.h"
199*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_cat.h"
200*9356374aSAndroid Build Coastguard Worker #include "absl/types/span.h"
201*9356374aSAndroid Build Coastguard Worker #include "absl/utility/utility.h"
202*9356374aSAndroid Build Coastguard Worker 
203*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_HAVE_ADDRESS_SANITIZER
204*9356374aSAndroid Build Coastguard Worker #include <sanitizer/asan_interface.h>
205*9356374aSAndroid Build Coastguard Worker #endif
206*9356374aSAndroid Build Coastguard Worker 
207*9356374aSAndroid Build Coastguard Worker namespace absl {
208*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
209*9356374aSAndroid Build Coastguard Worker namespace container_internal {
210*9356374aSAndroid Build Coastguard Worker 
211*9356374aSAndroid Build Coastguard Worker // A type wrapper that instructs `Layout` to use the specific alignment for the
212*9356374aSAndroid Build Coastguard Worker // array. `Layout<..., Aligned<T, N>, ...>` has exactly the same API
213*9356374aSAndroid Build Coastguard Worker // and behavior as `Layout<..., T, ...>` except that the first element of the
214*9356374aSAndroid Build Coastguard Worker // array of `T` is aligned to `N` (the rest of the elements follow without
215*9356374aSAndroid Build Coastguard Worker // padding).
216*9356374aSAndroid Build Coastguard Worker //
217*9356374aSAndroid Build Coastguard Worker // Requires: `N >= alignof(T)` and `N` is a power of 2.
218*9356374aSAndroid Build Coastguard Worker template <class T, size_t N>
219*9356374aSAndroid Build Coastguard Worker struct Aligned;
220*9356374aSAndroid Build Coastguard Worker 
221*9356374aSAndroid Build Coastguard Worker namespace internal_layout {
222*9356374aSAndroid Build Coastguard Worker 
223*9356374aSAndroid Build Coastguard Worker template <class T>
224*9356374aSAndroid Build Coastguard Worker struct NotAligned {};
225*9356374aSAndroid Build Coastguard Worker 
226*9356374aSAndroid Build Coastguard Worker template <class T, size_t N>
227*9356374aSAndroid Build Coastguard Worker struct NotAligned<const Aligned<T, N>> {
228*9356374aSAndroid Build Coastguard Worker   static_assert(sizeof(T) == 0, "Aligned<T, N> cannot be const-qualified");
229*9356374aSAndroid Build Coastguard Worker };
230*9356374aSAndroid Build Coastguard Worker 
231*9356374aSAndroid Build Coastguard Worker template <size_t>
232*9356374aSAndroid Build Coastguard Worker using IntToSize = size_t;
233*9356374aSAndroid Build Coastguard Worker 
234*9356374aSAndroid Build Coastguard Worker template <class T>
235*9356374aSAndroid Build Coastguard Worker struct Type : NotAligned<T> {
236*9356374aSAndroid Build Coastguard Worker   using type = T;
237*9356374aSAndroid Build Coastguard Worker };
238*9356374aSAndroid Build Coastguard Worker 
239*9356374aSAndroid Build Coastguard Worker template <class T, size_t N>
240*9356374aSAndroid Build Coastguard Worker struct Type<Aligned<T, N>> {
241*9356374aSAndroid Build Coastguard Worker   using type = T;
242*9356374aSAndroid Build Coastguard Worker };
243*9356374aSAndroid Build Coastguard Worker 
244*9356374aSAndroid Build Coastguard Worker template <class T>
245*9356374aSAndroid Build Coastguard Worker struct SizeOf : NotAligned<T>, std::integral_constant<size_t, sizeof(T)> {};
246*9356374aSAndroid Build Coastguard Worker 
247*9356374aSAndroid Build Coastguard Worker template <class T, size_t N>
248*9356374aSAndroid Build Coastguard Worker struct SizeOf<Aligned<T, N>> : std::integral_constant<size_t, sizeof(T)> {};
249*9356374aSAndroid Build Coastguard Worker 
250*9356374aSAndroid Build Coastguard Worker // Note: workaround for https://gcc.gnu.org/PR88115
251*9356374aSAndroid Build Coastguard Worker template <class T>
252*9356374aSAndroid Build Coastguard Worker struct AlignOf : NotAligned<T> {
253*9356374aSAndroid Build Coastguard Worker   static constexpr size_t value = alignof(T);
254*9356374aSAndroid Build Coastguard Worker };
255*9356374aSAndroid Build Coastguard Worker 
256*9356374aSAndroid Build Coastguard Worker template <class T, size_t N>
257*9356374aSAndroid Build Coastguard Worker struct AlignOf<Aligned<T, N>> {
258*9356374aSAndroid Build Coastguard Worker   static_assert(N % alignof(T) == 0,
259*9356374aSAndroid Build Coastguard Worker                 "Custom alignment can't be lower than the type's alignment");
260*9356374aSAndroid Build Coastguard Worker   static constexpr size_t value = N;
261*9356374aSAndroid Build Coastguard Worker };
262*9356374aSAndroid Build Coastguard Worker 
263*9356374aSAndroid Build Coastguard Worker // Does `Ts...` contain `T`?
264*9356374aSAndroid Build Coastguard Worker template <class T, class... Ts>
265*9356374aSAndroid Build Coastguard Worker using Contains = absl::disjunction<std::is_same<T, Ts>...>;
266*9356374aSAndroid Build Coastguard Worker 
267*9356374aSAndroid Build Coastguard Worker template <class From, class To>
268*9356374aSAndroid Build Coastguard Worker using CopyConst =
269*9356374aSAndroid Build Coastguard Worker     typename std::conditional<std::is_const<From>::value, const To, To>::type;
270*9356374aSAndroid Build Coastguard Worker 
271*9356374aSAndroid Build Coastguard Worker // Note: We're not qualifying this with absl:: because it doesn't compile under
272*9356374aSAndroid Build Coastguard Worker // MSVC.
273*9356374aSAndroid Build Coastguard Worker template <class T>
274*9356374aSAndroid Build Coastguard Worker using SliceType = Span<T>;
275*9356374aSAndroid Build Coastguard Worker 
276*9356374aSAndroid Build Coastguard Worker // This namespace contains no types. It prevents functions defined in it from
277*9356374aSAndroid Build Coastguard Worker // being found by ADL.
278*9356374aSAndroid Build Coastguard Worker namespace adl_barrier {
279*9356374aSAndroid Build Coastguard Worker 
280*9356374aSAndroid Build Coastguard Worker template <class Needle, class... Ts>
281*9356374aSAndroid Build Coastguard Worker constexpr size_t Find(Needle, Needle, Ts...) {
282*9356374aSAndroid Build Coastguard Worker   static_assert(!Contains<Needle, Ts...>(), "Duplicate element type");
283*9356374aSAndroid Build Coastguard Worker   return 0;
284*9356374aSAndroid Build Coastguard Worker }
285*9356374aSAndroid Build Coastguard Worker 
286*9356374aSAndroid Build Coastguard Worker template <class Needle, class T, class... Ts>
287*9356374aSAndroid Build Coastguard Worker constexpr size_t Find(Needle, T, Ts...) {
288*9356374aSAndroid Build Coastguard Worker   return adl_barrier::Find(Needle(), Ts()...) + 1;
289*9356374aSAndroid Build Coastguard Worker }
290*9356374aSAndroid Build Coastguard Worker 
291*9356374aSAndroid Build Coastguard Worker constexpr bool IsPow2(size_t n) { return !(n & (n - 1)); }
292*9356374aSAndroid Build Coastguard Worker 
293*9356374aSAndroid Build Coastguard Worker // Returns `q * m` for the smallest `q` such that `q * m >= n`.
294*9356374aSAndroid Build Coastguard Worker // Requires: `m` is a power of two. It's enforced by IsLegalElementType below.
295*9356374aSAndroid Build Coastguard Worker constexpr size_t Align(size_t n, size_t m) { return (n + m - 1) & ~(m - 1); }
296*9356374aSAndroid Build Coastguard Worker 
297*9356374aSAndroid Build Coastguard Worker constexpr size_t Min(size_t a, size_t b) { return b < a ? b : a; }
298*9356374aSAndroid Build Coastguard Worker 
299*9356374aSAndroid Build Coastguard Worker constexpr size_t Max(size_t a) { return a; }
300*9356374aSAndroid Build Coastguard Worker 
301*9356374aSAndroid Build Coastguard Worker template <class... Ts>
302*9356374aSAndroid Build Coastguard Worker constexpr size_t Max(size_t a, size_t b, Ts... rest) {
303*9356374aSAndroid Build Coastguard Worker   return adl_barrier::Max(b < a ? a : b, rest...);
304*9356374aSAndroid Build Coastguard Worker }
305*9356374aSAndroid Build Coastguard Worker 
306*9356374aSAndroid Build Coastguard Worker template <class T>
307*9356374aSAndroid Build Coastguard Worker std::string TypeName() {
308*9356374aSAndroid Build Coastguard Worker   std::string out;
309*9356374aSAndroid Build Coastguard Worker #if ABSL_INTERNAL_HAS_RTTI
310*9356374aSAndroid Build Coastguard Worker   absl::StrAppend(&out, "<",
311*9356374aSAndroid Build Coastguard Worker                   absl::debugging_internal::DemangleString(typeid(T).name()),
312*9356374aSAndroid Build Coastguard Worker                   ">");
313*9356374aSAndroid Build Coastguard Worker #endif
314*9356374aSAndroid Build Coastguard Worker   return out;
315*9356374aSAndroid Build Coastguard Worker }
316*9356374aSAndroid Build Coastguard Worker 
317*9356374aSAndroid Build Coastguard Worker }  // namespace adl_barrier
318*9356374aSAndroid Build Coastguard Worker 
319*9356374aSAndroid Build Coastguard Worker template <bool C>
320*9356374aSAndroid Build Coastguard Worker using EnableIf = typename std::enable_if<C, int>::type;
321*9356374aSAndroid Build Coastguard Worker 
322*9356374aSAndroid Build Coastguard Worker // Can `T` be a template argument of `Layout`?
323*9356374aSAndroid Build Coastguard Worker template <class T>
324*9356374aSAndroid Build Coastguard Worker using IsLegalElementType = std::integral_constant<
325*9356374aSAndroid Build Coastguard Worker     bool, !std::is_reference<T>::value && !std::is_volatile<T>::value &&
326*9356374aSAndroid Build Coastguard Worker               !std::is_reference<typename Type<T>::type>::value &&
327*9356374aSAndroid Build Coastguard Worker               !std::is_volatile<typename Type<T>::type>::value &&
328*9356374aSAndroid Build Coastguard Worker               adl_barrier::IsPow2(AlignOf<T>::value)>;
329*9356374aSAndroid Build Coastguard Worker 
330*9356374aSAndroid Build Coastguard Worker template <class Elements, class StaticSizeSeq, class RuntimeSizeSeq,
331*9356374aSAndroid Build Coastguard Worker           class SizeSeq, class OffsetSeq>
332*9356374aSAndroid Build Coastguard Worker class LayoutImpl;
333*9356374aSAndroid Build Coastguard Worker 
334*9356374aSAndroid Build Coastguard Worker // Public base class of `Layout` and the result type of `Layout::Partial()`.
335*9356374aSAndroid Build Coastguard Worker //
336*9356374aSAndroid Build Coastguard Worker // `Elements...` contains all template arguments of `Layout` that created this
337*9356374aSAndroid Build Coastguard Worker // instance.
338*9356374aSAndroid Build Coastguard Worker //
339*9356374aSAndroid Build Coastguard Worker // `StaticSizeSeq...` is an index_sequence containing the sizes specified at
340*9356374aSAndroid Build Coastguard Worker // compile-time.
341*9356374aSAndroid Build Coastguard Worker //
342*9356374aSAndroid Build Coastguard Worker // `RuntimeSizeSeq...` is `[0, NumRuntimeSizes)`, where `NumRuntimeSizes` is the
343*9356374aSAndroid Build Coastguard Worker // number of arguments passed to `Layout::Partial()` or `Layout::Layout()`.
344*9356374aSAndroid Build Coastguard Worker //
345*9356374aSAndroid Build Coastguard Worker // `SizeSeq...` is `[0, NumSizes)` where `NumSizes` is `NumRuntimeSizes` plus
346*9356374aSAndroid Build Coastguard Worker // the number of sizes in `StaticSizeSeq`.
347*9356374aSAndroid Build Coastguard Worker //
348*9356374aSAndroid Build Coastguard Worker // `OffsetSeq...` is `[0, NumOffsets)` where `NumOffsets` is
349*9356374aSAndroid Build Coastguard Worker // `Min(sizeof...(Elements), NumSizes + 1)` (the number of arrays for which we
350*9356374aSAndroid Build Coastguard Worker // can compute offsets).
351*9356374aSAndroid Build Coastguard Worker template <class... Elements, size_t... StaticSizeSeq, size_t... RuntimeSizeSeq,
352*9356374aSAndroid Build Coastguard Worker           size_t... SizeSeq, size_t... OffsetSeq>
353*9356374aSAndroid Build Coastguard Worker class LayoutImpl<
354*9356374aSAndroid Build Coastguard Worker     std::tuple<Elements...>, absl::index_sequence<StaticSizeSeq...>,
355*9356374aSAndroid Build Coastguard Worker     absl::index_sequence<RuntimeSizeSeq...>, absl::index_sequence<SizeSeq...>,
356*9356374aSAndroid Build Coastguard Worker     absl::index_sequence<OffsetSeq...>> {
357*9356374aSAndroid Build Coastguard Worker  private:
358*9356374aSAndroid Build Coastguard Worker   static_assert(sizeof...(Elements) > 0, "At least one field is required");
359*9356374aSAndroid Build Coastguard Worker   static_assert(absl::conjunction<IsLegalElementType<Elements>...>::value,
360*9356374aSAndroid Build Coastguard Worker                 "Invalid element type (see IsLegalElementType)");
361*9356374aSAndroid Build Coastguard Worker   static_assert(sizeof...(StaticSizeSeq) <= sizeof...(Elements),
362*9356374aSAndroid Build Coastguard Worker                 "Too many static sizes specified");
363*9356374aSAndroid Build Coastguard Worker 
364*9356374aSAndroid Build Coastguard Worker   enum {
365*9356374aSAndroid Build Coastguard Worker     NumTypes = sizeof...(Elements),
366*9356374aSAndroid Build Coastguard Worker     NumStaticSizes = sizeof...(StaticSizeSeq),
367*9356374aSAndroid Build Coastguard Worker     NumRuntimeSizes = sizeof...(RuntimeSizeSeq),
368*9356374aSAndroid Build Coastguard Worker     NumSizes = sizeof...(SizeSeq),
369*9356374aSAndroid Build Coastguard Worker     NumOffsets = sizeof...(OffsetSeq),
370*9356374aSAndroid Build Coastguard Worker   };
371*9356374aSAndroid Build Coastguard Worker 
372*9356374aSAndroid Build Coastguard Worker   // These are guaranteed by `Layout`.
373*9356374aSAndroid Build Coastguard Worker   static_assert(NumStaticSizes + NumRuntimeSizes == NumSizes, "Internal error");
374*9356374aSAndroid Build Coastguard Worker   static_assert(NumSizes <= NumTypes, "Internal error");
375*9356374aSAndroid Build Coastguard Worker   static_assert(NumOffsets == adl_barrier::Min(NumTypes, NumSizes + 1),
376*9356374aSAndroid Build Coastguard Worker                 "Internal error");
377*9356374aSAndroid Build Coastguard Worker   static_assert(NumTypes > 0, "Internal error");
378*9356374aSAndroid Build Coastguard Worker 
379*9356374aSAndroid Build Coastguard Worker   static constexpr std::array<size_t, sizeof...(StaticSizeSeq)> kStaticSizes = {
380*9356374aSAndroid Build Coastguard Worker       StaticSizeSeq...};
381*9356374aSAndroid Build Coastguard Worker 
382*9356374aSAndroid Build Coastguard Worker   // Returns the index of `T` in `Elements...`. Results in a compilation error
383*9356374aSAndroid Build Coastguard Worker   // if `Elements...` doesn't contain exactly one instance of `T`.
384*9356374aSAndroid Build Coastguard Worker   template <class T>
385*9356374aSAndroid Build Coastguard Worker   static constexpr size_t ElementIndex() {
386*9356374aSAndroid Build Coastguard Worker     static_assert(Contains<Type<T>, Type<typename Type<Elements>::type>...>(),
387*9356374aSAndroid Build Coastguard Worker                   "Type not found");
388*9356374aSAndroid Build Coastguard Worker     return adl_barrier::Find(Type<T>(),
389*9356374aSAndroid Build Coastguard Worker                              Type<typename Type<Elements>::type>()...);
390*9356374aSAndroid Build Coastguard Worker   }
391*9356374aSAndroid Build Coastguard Worker 
392*9356374aSAndroid Build Coastguard Worker   template <size_t N>
393*9356374aSAndroid Build Coastguard Worker   using ElementAlignment =
394*9356374aSAndroid Build Coastguard Worker       AlignOf<typename std::tuple_element<N, std::tuple<Elements...>>::type>;
395*9356374aSAndroid Build Coastguard Worker 
396*9356374aSAndroid Build Coastguard Worker  public:
397*9356374aSAndroid Build Coastguard Worker   // Element types of all arrays packed in a tuple.
398*9356374aSAndroid Build Coastguard Worker   using ElementTypes = std::tuple<typename Type<Elements>::type...>;
399*9356374aSAndroid Build Coastguard Worker 
400*9356374aSAndroid Build Coastguard Worker   // Element type of the Nth array.
401*9356374aSAndroid Build Coastguard Worker   template <size_t N>
402*9356374aSAndroid Build Coastguard Worker   using ElementType = typename std::tuple_element<N, ElementTypes>::type;
403*9356374aSAndroid Build Coastguard Worker 
404*9356374aSAndroid Build Coastguard Worker   constexpr explicit LayoutImpl(IntToSize<RuntimeSizeSeq>... sizes)
405*9356374aSAndroid Build Coastguard Worker       : size_{sizes...} {}
406*9356374aSAndroid Build Coastguard Worker 
407*9356374aSAndroid Build Coastguard Worker   // Alignment of the layout, equal to the strictest alignment of all elements.
408*9356374aSAndroid Build Coastguard Worker   // All pointers passed to the methods of layout must be aligned to this value.
409*9356374aSAndroid Build Coastguard Worker   static constexpr size_t Alignment() {
410*9356374aSAndroid Build Coastguard Worker     return adl_barrier::Max(AlignOf<Elements>::value...);
411*9356374aSAndroid Build Coastguard Worker   }
412*9356374aSAndroid Build Coastguard Worker 
413*9356374aSAndroid Build Coastguard Worker   // Offset in bytes of the Nth array.
414*9356374aSAndroid Build Coastguard Worker   //
415*9356374aSAndroid Build Coastguard Worker   //   // int[3], 4 bytes of padding, double[4].
416*9356374aSAndroid Build Coastguard Worker   //   Layout<int, double> x(3, 4);
417*9356374aSAndroid Build Coastguard Worker   //   assert(x.Offset<0>() == 0);   // The ints starts from 0.
418*9356374aSAndroid Build Coastguard Worker   //   assert(x.Offset<1>() == 16);  // The doubles starts from 16.
419*9356374aSAndroid Build Coastguard Worker   //
420*9356374aSAndroid Build Coastguard Worker   // Requires: `N <= NumSizes && N < sizeof...(Ts)`.
421*9356374aSAndroid Build Coastguard Worker   template <size_t N, EnableIf<N == 0> = 0>
422*9356374aSAndroid Build Coastguard Worker   constexpr size_t Offset() const {
423*9356374aSAndroid Build Coastguard Worker     return 0;
424*9356374aSAndroid Build Coastguard Worker   }
425*9356374aSAndroid Build Coastguard Worker 
426*9356374aSAndroid Build Coastguard Worker   template <size_t N, EnableIf<N != 0> = 0>
427*9356374aSAndroid Build Coastguard Worker   constexpr size_t Offset() const {
428*9356374aSAndroid Build Coastguard Worker     static_assert(N < NumOffsets, "Index out of bounds");
429*9356374aSAndroid Build Coastguard Worker     return adl_barrier::Align(
430*9356374aSAndroid Build Coastguard Worker         Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * Size<N - 1>(),
431*9356374aSAndroid Build Coastguard Worker         ElementAlignment<N>::value);
432*9356374aSAndroid Build Coastguard Worker   }
433*9356374aSAndroid Build Coastguard Worker 
434*9356374aSAndroid Build Coastguard Worker   // Offset in bytes of the array with the specified element type. There must
435*9356374aSAndroid Build Coastguard Worker   // be exactly one such array and its zero-based index must be at most
436*9356374aSAndroid Build Coastguard Worker   // `NumSizes`.
437*9356374aSAndroid Build Coastguard Worker   //
438*9356374aSAndroid Build Coastguard Worker   //   // int[3], 4 bytes of padding, double[4].
439*9356374aSAndroid Build Coastguard Worker   //   Layout<int, double> x(3, 4);
440*9356374aSAndroid Build Coastguard Worker   //   assert(x.Offset<int>() == 0);      // The ints starts from 0.
441*9356374aSAndroid Build Coastguard Worker   //   assert(x.Offset<double>() == 16);  // The doubles starts from 16.
442*9356374aSAndroid Build Coastguard Worker   template <class T>
443*9356374aSAndroid Build Coastguard Worker   constexpr size_t Offset() const {
444*9356374aSAndroid Build Coastguard Worker     return Offset<ElementIndex<T>()>();
445*9356374aSAndroid Build Coastguard Worker   }
446*9356374aSAndroid Build Coastguard Worker 
447*9356374aSAndroid Build Coastguard Worker   // Offsets in bytes of all arrays for which the offsets are known.
448*9356374aSAndroid Build Coastguard Worker   constexpr std::array<size_t, NumOffsets> Offsets() const {
449*9356374aSAndroid Build Coastguard Worker     return {{Offset<OffsetSeq>()...}};
450*9356374aSAndroid Build Coastguard Worker   }
451*9356374aSAndroid Build Coastguard Worker 
452*9356374aSAndroid Build Coastguard Worker   // The number of elements in the Nth array (zero-based).
453*9356374aSAndroid Build Coastguard Worker   //
454*9356374aSAndroid Build Coastguard Worker   //   // int[3], 4 bytes of padding, double[4].
455*9356374aSAndroid Build Coastguard Worker   //   Layout<int, double> x(3, 4);
456*9356374aSAndroid Build Coastguard Worker   //   assert(x.Size<0>() == 3);
457*9356374aSAndroid Build Coastguard Worker   //   assert(x.Size<1>() == 4);
458*9356374aSAndroid Build Coastguard Worker   //
459*9356374aSAndroid Build Coastguard Worker   // Requires: `N < NumSizes`.
460*9356374aSAndroid Build Coastguard Worker   template <size_t N, EnableIf<(N < NumStaticSizes)> = 0>
461*9356374aSAndroid Build Coastguard Worker   constexpr size_t Size() const {
462*9356374aSAndroid Build Coastguard Worker     return kStaticSizes[N];
463*9356374aSAndroid Build Coastguard Worker   }
464*9356374aSAndroid Build Coastguard Worker 
465*9356374aSAndroid Build Coastguard Worker   template <size_t N, EnableIf<(N >= NumStaticSizes)> = 0>
466*9356374aSAndroid Build Coastguard Worker   constexpr size_t Size() const {
467*9356374aSAndroid Build Coastguard Worker     static_assert(N < NumSizes, "Index out of bounds");
468*9356374aSAndroid Build Coastguard Worker     return size_[N - NumStaticSizes];
469*9356374aSAndroid Build Coastguard Worker   }
470*9356374aSAndroid Build Coastguard Worker 
471*9356374aSAndroid Build Coastguard Worker   // The number of elements in the array with the specified element type.
472*9356374aSAndroid Build Coastguard Worker   // There must be exactly one such array and its zero-based index must be
473*9356374aSAndroid Build Coastguard Worker   // at most `NumSizes`.
474*9356374aSAndroid Build Coastguard Worker   //
475*9356374aSAndroid Build Coastguard Worker   //   // int[3], 4 bytes of padding, double[4].
476*9356374aSAndroid Build Coastguard Worker   //   Layout<int, double> x(3, 4);
477*9356374aSAndroid Build Coastguard Worker   //   assert(x.Size<int>() == 3);
478*9356374aSAndroid Build Coastguard Worker   //   assert(x.Size<double>() == 4);
479*9356374aSAndroid Build Coastguard Worker   template <class T>
480*9356374aSAndroid Build Coastguard Worker   constexpr size_t Size() const {
481*9356374aSAndroid Build Coastguard Worker     return Size<ElementIndex<T>()>();
482*9356374aSAndroid Build Coastguard Worker   }
483*9356374aSAndroid Build Coastguard Worker 
484*9356374aSAndroid Build Coastguard Worker   // The number of elements of all arrays for which they are known.
485*9356374aSAndroid Build Coastguard Worker   constexpr std::array<size_t, NumSizes> Sizes() const {
486*9356374aSAndroid Build Coastguard Worker     return {{Size<SizeSeq>()...}};
487*9356374aSAndroid Build Coastguard Worker   }
488*9356374aSAndroid Build Coastguard Worker 
489*9356374aSAndroid Build Coastguard Worker   // Pointer to the beginning of the Nth array.
490*9356374aSAndroid Build Coastguard Worker   //
491*9356374aSAndroid Build Coastguard Worker   // `Char` must be `[const] [signed|unsigned] char`.
492*9356374aSAndroid Build Coastguard Worker   //
493*9356374aSAndroid Build Coastguard Worker   //   // int[3], 4 bytes of padding, double[4].
494*9356374aSAndroid Build Coastguard Worker   //   Layout<int, double> x(3, 4);
495*9356374aSAndroid Build Coastguard Worker   //   unsigned char* p = new unsigned char[x.AllocSize()];
496*9356374aSAndroid Build Coastguard Worker   //   int* ints = x.Pointer<0>(p);
497*9356374aSAndroid Build Coastguard Worker   //   double* doubles = x.Pointer<1>(p);
498*9356374aSAndroid Build Coastguard Worker   //
499*9356374aSAndroid Build Coastguard Worker   // Requires: `N <= NumSizes && N < sizeof...(Ts)`.
500*9356374aSAndroid Build Coastguard Worker   // Requires: `p` is aligned to `Alignment()`.
501*9356374aSAndroid Build Coastguard Worker   template <size_t N, class Char>
502*9356374aSAndroid Build Coastguard Worker   CopyConst<Char, ElementType<N>>* Pointer(Char* p) const {
503*9356374aSAndroid Build Coastguard Worker     using C = typename std::remove_const<Char>::type;
504*9356374aSAndroid Build Coastguard Worker     static_assert(
505*9356374aSAndroid Build Coastguard Worker         std::is_same<C, char>() || std::is_same<C, unsigned char>() ||
506*9356374aSAndroid Build Coastguard Worker             std::is_same<C, signed char>(),
507*9356374aSAndroid Build Coastguard Worker         "The argument must be a pointer to [const] [signed|unsigned] char");
508*9356374aSAndroid Build Coastguard Worker     constexpr size_t alignment = Alignment();
509*9356374aSAndroid Build Coastguard Worker     (void)alignment;
510*9356374aSAndroid Build Coastguard Worker     assert(reinterpret_cast<uintptr_t>(p) % alignment == 0);
511*9356374aSAndroid Build Coastguard Worker     return reinterpret_cast<CopyConst<Char, ElementType<N>>*>(p + Offset<N>());
512*9356374aSAndroid Build Coastguard Worker   }
513*9356374aSAndroid Build Coastguard Worker 
514*9356374aSAndroid Build Coastguard Worker   // Pointer to the beginning of the array with the specified element type.
515*9356374aSAndroid Build Coastguard Worker   // There must be exactly one such array and its zero-based index must be at
516*9356374aSAndroid Build Coastguard Worker   // most `NumSizes`.
517*9356374aSAndroid Build Coastguard Worker   //
518*9356374aSAndroid Build Coastguard Worker   // `Char` must be `[const] [signed|unsigned] char`.
519*9356374aSAndroid Build Coastguard Worker   //
520*9356374aSAndroid Build Coastguard Worker   //   // int[3], 4 bytes of padding, double[4].
521*9356374aSAndroid Build Coastguard Worker   //   Layout<int, double> x(3, 4);
522*9356374aSAndroid Build Coastguard Worker   //   unsigned char* p = new unsigned char[x.AllocSize()];
523*9356374aSAndroid Build Coastguard Worker   //   int* ints = x.Pointer<int>(p);
524*9356374aSAndroid Build Coastguard Worker   //   double* doubles = x.Pointer<double>(p);
525*9356374aSAndroid Build Coastguard Worker   //
526*9356374aSAndroid Build Coastguard Worker   // Requires: `p` is aligned to `Alignment()`.
527*9356374aSAndroid Build Coastguard Worker   template <class T, class Char>
528*9356374aSAndroid Build Coastguard Worker   CopyConst<Char, T>* Pointer(Char* p) const {
529*9356374aSAndroid Build Coastguard Worker     return Pointer<ElementIndex<T>()>(p);
530*9356374aSAndroid Build Coastguard Worker   }
531*9356374aSAndroid Build Coastguard Worker 
532*9356374aSAndroid Build Coastguard Worker   // Pointers to all arrays for which pointers are known.
533*9356374aSAndroid Build Coastguard Worker   //
534*9356374aSAndroid Build Coastguard Worker   // `Char` must be `[const] [signed|unsigned] char`.
535*9356374aSAndroid Build Coastguard Worker   //
536*9356374aSAndroid Build Coastguard Worker   //   // int[3], 4 bytes of padding, double[4].
537*9356374aSAndroid Build Coastguard Worker   //   Layout<int, double> x(3, 4);
538*9356374aSAndroid Build Coastguard Worker   //   unsigned char* p = new unsigned char[x.AllocSize()];
539*9356374aSAndroid Build Coastguard Worker   //
540*9356374aSAndroid Build Coastguard Worker   //   int* ints;
541*9356374aSAndroid Build Coastguard Worker   //   double* doubles;
542*9356374aSAndroid Build Coastguard Worker   //   std::tie(ints, doubles) = x.Pointers(p);
543*9356374aSAndroid Build Coastguard Worker   //
544*9356374aSAndroid Build Coastguard Worker   // Requires: `p` is aligned to `Alignment()`.
545*9356374aSAndroid Build Coastguard Worker   template <class Char>
546*9356374aSAndroid Build Coastguard Worker   auto Pointers(Char* p) const {
547*9356374aSAndroid Build Coastguard Worker     return std::tuple<CopyConst<Char, ElementType<OffsetSeq>>*...>(
548*9356374aSAndroid Build Coastguard Worker         Pointer<OffsetSeq>(p)...);
549*9356374aSAndroid Build Coastguard Worker   }
550*9356374aSAndroid Build Coastguard Worker 
551*9356374aSAndroid Build Coastguard Worker   // The Nth array.
552*9356374aSAndroid Build Coastguard Worker   //
553*9356374aSAndroid Build Coastguard Worker   // `Char` must be `[const] [signed|unsigned] char`.
554*9356374aSAndroid Build Coastguard Worker   //
555*9356374aSAndroid Build Coastguard Worker   //   // int[3], 4 bytes of padding, double[4].
556*9356374aSAndroid Build Coastguard Worker   //   Layout<int, double> x(3, 4);
557*9356374aSAndroid Build Coastguard Worker   //   unsigned char* p = new unsigned char[x.AllocSize()];
558*9356374aSAndroid Build Coastguard Worker   //   Span<int> ints = x.Slice<0>(p);
559*9356374aSAndroid Build Coastguard Worker   //   Span<double> doubles = x.Slice<1>(p);
560*9356374aSAndroid Build Coastguard Worker   //
561*9356374aSAndroid Build Coastguard Worker   // Requires: `N < NumSizes`.
562*9356374aSAndroid Build Coastguard Worker   // Requires: `p` is aligned to `Alignment()`.
563*9356374aSAndroid Build Coastguard Worker   template <size_t N, class Char>
564*9356374aSAndroid Build Coastguard Worker   SliceType<CopyConst<Char, ElementType<N>>> Slice(Char* p) const {
565*9356374aSAndroid Build Coastguard Worker     return SliceType<CopyConst<Char, ElementType<N>>>(Pointer<N>(p), Size<N>());
566*9356374aSAndroid Build Coastguard Worker   }
567*9356374aSAndroid Build Coastguard Worker 
568*9356374aSAndroid Build Coastguard Worker   // The array with the specified element type. There must be exactly one
569*9356374aSAndroid Build Coastguard Worker   // such array and its zero-based index must be less than `NumSizes`.
570*9356374aSAndroid Build Coastguard Worker   //
571*9356374aSAndroid Build Coastguard Worker   // `Char` must be `[const] [signed|unsigned] char`.
572*9356374aSAndroid Build Coastguard Worker   //
573*9356374aSAndroid Build Coastguard Worker   //   // int[3], 4 bytes of padding, double[4].
574*9356374aSAndroid Build Coastguard Worker   //   Layout<int, double> x(3, 4);
575*9356374aSAndroid Build Coastguard Worker   //   unsigned char* p = new unsigned char[x.AllocSize()];
576*9356374aSAndroid Build Coastguard Worker   //   Span<int> ints = x.Slice<int>(p);
577*9356374aSAndroid Build Coastguard Worker   //   Span<double> doubles = x.Slice<double>(p);
578*9356374aSAndroid Build Coastguard Worker   //
579*9356374aSAndroid Build Coastguard Worker   // Requires: `p` is aligned to `Alignment()`.
580*9356374aSAndroid Build Coastguard Worker   template <class T, class Char>
581*9356374aSAndroid Build Coastguard Worker   SliceType<CopyConst<Char, T>> Slice(Char* p) const {
582*9356374aSAndroid Build Coastguard Worker     return Slice<ElementIndex<T>()>(p);
583*9356374aSAndroid Build Coastguard Worker   }
584*9356374aSAndroid Build Coastguard Worker 
585*9356374aSAndroid Build Coastguard Worker   // All arrays with known sizes.
586*9356374aSAndroid Build Coastguard Worker   //
587*9356374aSAndroid Build Coastguard Worker   // `Char` must be `[const] [signed|unsigned] char`.
588*9356374aSAndroid Build Coastguard Worker   //
589*9356374aSAndroid Build Coastguard Worker   //   // int[3], 4 bytes of padding, double[4].
590*9356374aSAndroid Build Coastguard Worker   //   Layout<int, double> x(3, 4);
591*9356374aSAndroid Build Coastguard Worker   //   unsigned char* p = new unsigned char[x.AllocSize()];
592*9356374aSAndroid Build Coastguard Worker   //
593*9356374aSAndroid Build Coastguard Worker   //   Span<int> ints;
594*9356374aSAndroid Build Coastguard Worker   //   Span<double> doubles;
595*9356374aSAndroid Build Coastguard Worker   //   std::tie(ints, doubles) = x.Slices(p);
596*9356374aSAndroid Build Coastguard Worker   //
597*9356374aSAndroid Build Coastguard Worker   // Requires: `p` is aligned to `Alignment()`.
598*9356374aSAndroid Build Coastguard Worker   //
599*9356374aSAndroid Build Coastguard Worker   // Note: We mark the parameter as unused because GCC detects it is not used
600*9356374aSAndroid Build Coastguard Worker   // when `SizeSeq` is empty [-Werror=unused-but-set-parameter].
601*9356374aSAndroid Build Coastguard Worker   template <class Char>
602*9356374aSAndroid Build Coastguard Worker   auto Slices(ABSL_ATTRIBUTE_UNUSED Char* p) const {
603*9356374aSAndroid Build Coastguard Worker     return std::tuple<SliceType<CopyConst<Char, ElementType<SizeSeq>>>...>(
604*9356374aSAndroid Build Coastguard Worker         Slice<SizeSeq>(p)...);
605*9356374aSAndroid Build Coastguard Worker   }
606*9356374aSAndroid Build Coastguard Worker 
607*9356374aSAndroid Build Coastguard Worker   // The size of the allocation that fits all arrays.
608*9356374aSAndroid Build Coastguard Worker   //
609*9356374aSAndroid Build Coastguard Worker   //   // int[3], 4 bytes of padding, double[4].
610*9356374aSAndroid Build Coastguard Worker   //   Layout<int, double> x(3, 4);
611*9356374aSAndroid Build Coastguard Worker   //   unsigned char* p = new unsigned char[x.AllocSize()];  // 48 bytes
612*9356374aSAndroid Build Coastguard Worker   //
613*9356374aSAndroid Build Coastguard Worker   // Requires: `NumSizes == sizeof...(Ts)`.
614*9356374aSAndroid Build Coastguard Worker   constexpr size_t AllocSize() const {
615*9356374aSAndroid Build Coastguard Worker     static_assert(NumTypes == NumSizes, "You must specify sizes of all fields");
616*9356374aSAndroid Build Coastguard Worker     return Offset<NumTypes - 1>() +
617*9356374aSAndroid Build Coastguard Worker            SizeOf<ElementType<NumTypes - 1>>::value * Size<NumTypes - 1>();
618*9356374aSAndroid Build Coastguard Worker   }
619*9356374aSAndroid Build Coastguard Worker 
620*9356374aSAndroid Build Coastguard Worker   // If built with --config=asan, poisons padding bytes (if any) in the
621*9356374aSAndroid Build Coastguard Worker   // allocation. The pointer must point to a memory block at least
622*9356374aSAndroid Build Coastguard Worker   // `AllocSize()` bytes in length.
623*9356374aSAndroid Build Coastguard Worker   //
624*9356374aSAndroid Build Coastguard Worker   // `Char` must be `[const] [signed|unsigned] char`.
625*9356374aSAndroid Build Coastguard Worker   //
626*9356374aSAndroid Build Coastguard Worker   // Requires: `p` is aligned to `Alignment()`.
627*9356374aSAndroid Build Coastguard Worker   template <class Char, size_t N = NumOffsets - 1, EnableIf<N == 0> = 0>
628*9356374aSAndroid Build Coastguard Worker   void PoisonPadding(const Char* p) const {
629*9356374aSAndroid Build Coastguard Worker     Pointer<0>(p);  // verify the requirements on `Char` and `p`
630*9356374aSAndroid Build Coastguard Worker   }
631*9356374aSAndroid Build Coastguard Worker 
632*9356374aSAndroid Build Coastguard Worker   template <class Char, size_t N = NumOffsets - 1, EnableIf<N != 0> = 0>
633*9356374aSAndroid Build Coastguard Worker   void PoisonPadding(const Char* p) const {
634*9356374aSAndroid Build Coastguard Worker     static_assert(N < NumOffsets, "Index out of bounds");
635*9356374aSAndroid Build Coastguard Worker     (void)p;
636*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_HAVE_ADDRESS_SANITIZER
637*9356374aSAndroid Build Coastguard Worker     PoisonPadding<Char, N - 1>(p);
638*9356374aSAndroid Build Coastguard Worker     // The `if` is an optimization. It doesn't affect the observable behaviour.
639*9356374aSAndroid Build Coastguard Worker     if (ElementAlignment<N - 1>::value % ElementAlignment<N>::value) {
640*9356374aSAndroid Build Coastguard Worker       size_t start =
641*9356374aSAndroid Build Coastguard Worker           Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * Size<N - 1>();
642*9356374aSAndroid Build Coastguard Worker       ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start);
643*9356374aSAndroid Build Coastguard Worker     }
644*9356374aSAndroid Build Coastguard Worker #endif
645*9356374aSAndroid Build Coastguard Worker   }
646*9356374aSAndroid Build Coastguard Worker 
647*9356374aSAndroid Build Coastguard Worker   // Human-readable description of the memory layout. Useful for debugging.
648*9356374aSAndroid Build Coastguard Worker   // Slow.
649*9356374aSAndroid Build Coastguard Worker   //
650*9356374aSAndroid Build Coastguard Worker   //   // char[5], 3 bytes of padding, int[3], 4 bytes of padding, followed
651*9356374aSAndroid Build Coastguard Worker   //   // by an unknown number of doubles.
652*9356374aSAndroid Build Coastguard Worker   //   auto x = Layout<char, int, double>::Partial(5, 3);
653*9356374aSAndroid Build Coastguard Worker   //   assert(x.DebugString() ==
654*9356374aSAndroid Build Coastguard Worker   //          "@0<char>(1)[5]; @8<int>(4)[3]; @24<double>(8)");
655*9356374aSAndroid Build Coastguard Worker   //
656*9356374aSAndroid Build Coastguard Worker   // Each field is in the following format: @offset<type>(sizeof)[size] (<type>
657*9356374aSAndroid Build Coastguard Worker   // may be missing depending on the target platform). For example,
658*9356374aSAndroid Build Coastguard Worker   // @8<int>(4)[3] means that at offset 8 we have an array of ints, where each
659*9356374aSAndroid Build Coastguard Worker   // int is 4 bytes, and we have 3 of those ints. The size of the last field may
660*9356374aSAndroid Build Coastguard Worker   // be missing (as in the example above). Only fields with known offsets are
661*9356374aSAndroid Build Coastguard Worker   // described. Type names may differ across platforms: one compiler might
662*9356374aSAndroid Build Coastguard Worker   // produce "unsigned*" where another produces "unsigned int *".
663*9356374aSAndroid Build Coastguard Worker   std::string DebugString() const {
664*9356374aSAndroid Build Coastguard Worker     const auto offsets = Offsets();
665*9356374aSAndroid Build Coastguard Worker     const size_t sizes[] = {SizeOf<ElementType<OffsetSeq>>::value...};
666*9356374aSAndroid Build Coastguard Worker     const std::string types[] = {
667*9356374aSAndroid Build Coastguard Worker         adl_barrier::TypeName<ElementType<OffsetSeq>>()...};
668*9356374aSAndroid Build Coastguard Worker     std::string res = absl::StrCat("@0", types[0], "(", sizes[0], ")");
669*9356374aSAndroid Build Coastguard Worker     for (size_t i = 0; i != NumOffsets - 1; ++i) {
670*9356374aSAndroid Build Coastguard Worker       absl::StrAppend(&res, "[", DebugSize(i), "]; @", offsets[i + 1],
671*9356374aSAndroid Build Coastguard Worker                       types[i + 1], "(", sizes[i + 1], ")");
672*9356374aSAndroid Build Coastguard Worker     }
673*9356374aSAndroid Build Coastguard Worker     // NumSizes is a constant that may be zero. Some compilers cannot see that
674*9356374aSAndroid Build Coastguard Worker     // inside the if statement "size_[NumSizes - 1]" must be valid.
675*9356374aSAndroid Build Coastguard Worker     int last = static_cast<int>(NumSizes) - 1;
676*9356374aSAndroid Build Coastguard Worker     if (NumTypes == NumSizes && last >= 0) {
677*9356374aSAndroid Build Coastguard Worker       absl::StrAppend(&res, "[", DebugSize(static_cast<size_t>(last)), "]");
678*9356374aSAndroid Build Coastguard Worker     }
679*9356374aSAndroid Build Coastguard Worker     return res;
680*9356374aSAndroid Build Coastguard Worker   }
681*9356374aSAndroid Build Coastguard Worker 
682*9356374aSAndroid Build Coastguard Worker  private:
683*9356374aSAndroid Build Coastguard Worker   size_t DebugSize(size_t n) const {
684*9356374aSAndroid Build Coastguard Worker     if (n < NumStaticSizes) {
685*9356374aSAndroid Build Coastguard Worker       return kStaticSizes[n];
686*9356374aSAndroid Build Coastguard Worker     } else {
687*9356374aSAndroid Build Coastguard Worker       return size_[n - NumStaticSizes];
688*9356374aSAndroid Build Coastguard Worker     }
689*9356374aSAndroid Build Coastguard Worker   }
690*9356374aSAndroid Build Coastguard Worker 
691*9356374aSAndroid Build Coastguard Worker   // Arguments of `Layout::Partial()` or `Layout::Layout()`.
692*9356374aSAndroid Build Coastguard Worker   size_t size_[NumRuntimeSizes > 0 ? NumRuntimeSizes : 1];
693*9356374aSAndroid Build Coastguard Worker };
694*9356374aSAndroid Build Coastguard Worker 
695*9356374aSAndroid Build Coastguard Worker // Defining a constexpr static class member variable is redundant and deprecated
696*9356374aSAndroid Build Coastguard Worker // in C++17, but required in C++14.
697*9356374aSAndroid Build Coastguard Worker template <class... Elements, size_t... StaticSizeSeq, size_t... RuntimeSizeSeq,
698*9356374aSAndroid Build Coastguard Worker           size_t... SizeSeq, size_t... OffsetSeq>
699*9356374aSAndroid Build Coastguard Worker constexpr std::array<size_t, sizeof...(StaticSizeSeq)> LayoutImpl<
700*9356374aSAndroid Build Coastguard Worker     std::tuple<Elements...>, absl::index_sequence<StaticSizeSeq...>,
701*9356374aSAndroid Build Coastguard Worker     absl::index_sequence<RuntimeSizeSeq...>, absl::index_sequence<SizeSeq...>,
702*9356374aSAndroid Build Coastguard Worker     absl::index_sequence<OffsetSeq...>>::kStaticSizes;
703*9356374aSAndroid Build Coastguard Worker 
704*9356374aSAndroid Build Coastguard Worker template <class StaticSizeSeq, size_t NumRuntimeSizes, class... Ts>
705*9356374aSAndroid Build Coastguard Worker using LayoutType = LayoutImpl<
706*9356374aSAndroid Build Coastguard Worker     std::tuple<Ts...>, StaticSizeSeq,
707*9356374aSAndroid Build Coastguard Worker     absl::make_index_sequence<NumRuntimeSizes>,
708*9356374aSAndroid Build Coastguard Worker     absl::make_index_sequence<NumRuntimeSizes + StaticSizeSeq::size()>,
709*9356374aSAndroid Build Coastguard Worker     absl::make_index_sequence<adl_barrier::Min(
710*9356374aSAndroid Build Coastguard Worker         sizeof...(Ts), NumRuntimeSizes + StaticSizeSeq::size() + 1)>>;
711*9356374aSAndroid Build Coastguard Worker 
712*9356374aSAndroid Build Coastguard Worker template <class StaticSizeSeq, class... Ts>
713*9356374aSAndroid Build Coastguard Worker class LayoutWithStaticSizes
714*9356374aSAndroid Build Coastguard Worker     : public LayoutType<StaticSizeSeq,
715*9356374aSAndroid Build Coastguard Worker                         sizeof...(Ts) - adl_barrier::Min(sizeof...(Ts),
716*9356374aSAndroid Build Coastguard Worker                                                          StaticSizeSeq::size()),
717*9356374aSAndroid Build Coastguard Worker                         Ts...> {
718*9356374aSAndroid Build Coastguard Worker  private:
719*9356374aSAndroid Build Coastguard Worker   using Super =
720*9356374aSAndroid Build Coastguard Worker       LayoutType<StaticSizeSeq,
721*9356374aSAndroid Build Coastguard Worker                  sizeof...(Ts) -
722*9356374aSAndroid Build Coastguard Worker                      adl_barrier::Min(sizeof...(Ts), StaticSizeSeq::size()),
723*9356374aSAndroid Build Coastguard Worker                  Ts...>;
724*9356374aSAndroid Build Coastguard Worker 
725*9356374aSAndroid Build Coastguard Worker  public:
726*9356374aSAndroid Build Coastguard Worker   // The result type of `Partial()` with `NumSizes` arguments.
727*9356374aSAndroid Build Coastguard Worker   template <size_t NumSizes>
728*9356374aSAndroid Build Coastguard Worker   using PartialType =
729*9356374aSAndroid Build Coastguard Worker       internal_layout::LayoutType<StaticSizeSeq, NumSizes, Ts...>;
730*9356374aSAndroid Build Coastguard Worker 
731*9356374aSAndroid Build Coastguard Worker   // `Layout` knows the element types of the arrays we want to lay out in
732*9356374aSAndroid Build Coastguard Worker   // memory but not the number of elements in each array.
733*9356374aSAndroid Build Coastguard Worker   // `Partial(size1, ..., sizeN)` allows us to specify the latter. The
734*9356374aSAndroid Build Coastguard Worker   // resulting immutable object can be used to obtain pointers to the
735*9356374aSAndroid Build Coastguard Worker   // individual arrays.
736*9356374aSAndroid Build Coastguard Worker   //
737*9356374aSAndroid Build Coastguard Worker   // It's allowed to pass fewer array sizes than the number of arrays. E.g.,
738*9356374aSAndroid Build Coastguard Worker   // if all you need is to the offset of the second array, you only need to
739*9356374aSAndroid Build Coastguard Worker   // pass one argument -- the number of elements in the first array.
740*9356374aSAndroid Build Coastguard Worker   //
741*9356374aSAndroid Build Coastguard Worker   //   // int[3] followed by 4 bytes of padding and an unknown number of
742*9356374aSAndroid Build Coastguard Worker   //   // doubles.
743*9356374aSAndroid Build Coastguard Worker   //   auto x = Layout<int, double>::Partial(3);
744*9356374aSAndroid Build Coastguard Worker   //   // doubles start at byte 16.
745*9356374aSAndroid Build Coastguard Worker   //   assert(x.Offset<1>() == 16);
746*9356374aSAndroid Build Coastguard Worker   //
747*9356374aSAndroid Build Coastguard Worker   // If you know the number of elements in all arrays, you can still call
748*9356374aSAndroid Build Coastguard Worker   // `Partial()` but it's more convenient to use the constructor of `Layout`.
749*9356374aSAndroid Build Coastguard Worker   //
750*9356374aSAndroid Build Coastguard Worker   //   Layout<int, double> x(3, 5);
751*9356374aSAndroid Build Coastguard Worker   //
752*9356374aSAndroid Build Coastguard Worker   // Note: The sizes of the arrays must be specified in number of elements,
753*9356374aSAndroid Build Coastguard Worker   // not in bytes.
754*9356374aSAndroid Build Coastguard Worker   //
755*9356374aSAndroid Build Coastguard Worker   // Requires: `sizeof...(Sizes) + NumStaticSizes <= sizeof...(Ts)`.
756*9356374aSAndroid Build Coastguard Worker   // Requires: all arguments are convertible to `size_t`.
757*9356374aSAndroid Build Coastguard Worker   template <class... Sizes>
758*9356374aSAndroid Build Coastguard Worker   static constexpr PartialType<sizeof...(Sizes)> Partial(Sizes&&... sizes) {
759*9356374aSAndroid Build Coastguard Worker     static_assert(sizeof...(Sizes) + StaticSizeSeq::size() <= sizeof...(Ts),
760*9356374aSAndroid Build Coastguard Worker                   "");
761*9356374aSAndroid Build Coastguard Worker     return PartialType<sizeof...(Sizes)>(
762*9356374aSAndroid Build Coastguard Worker         static_cast<size_t>(std::forward<Sizes>(sizes))...);
763*9356374aSAndroid Build Coastguard Worker   }
764*9356374aSAndroid Build Coastguard Worker 
765*9356374aSAndroid Build Coastguard Worker   // Inherit LayoutType's constructor.
766*9356374aSAndroid Build Coastguard Worker   //
767*9356374aSAndroid Build Coastguard Worker   // Creates a layout with the sizes of all arrays specified. If you know
768*9356374aSAndroid Build Coastguard Worker   // only the sizes of the first N arrays (where N can be zero), you can use
769*9356374aSAndroid Build Coastguard Worker   // `Partial()` defined above. The constructor is essentially equivalent to
770*9356374aSAndroid Build Coastguard Worker   // calling `Partial()` and passing in all array sizes; the constructor is
771*9356374aSAndroid Build Coastguard Worker   // provided as a convenient abbreviation.
772*9356374aSAndroid Build Coastguard Worker   //
773*9356374aSAndroid Build Coastguard Worker   // Note: The sizes of the arrays must be specified in number of elements,
774*9356374aSAndroid Build Coastguard Worker   // not in bytes.
775*9356374aSAndroid Build Coastguard Worker   //
776*9356374aSAndroid Build Coastguard Worker   // Implementation note: we do this via a `using` declaration instead of
777*9356374aSAndroid Build Coastguard Worker   // defining our own explicit constructor because the signature of LayoutType's
778*9356374aSAndroid Build Coastguard Worker   // constructor depends on RuntimeSizeSeq, which we don't have access to here.
779*9356374aSAndroid Build Coastguard Worker   // If we defined our own constructor here, it would have to use a parameter
780*9356374aSAndroid Build Coastguard Worker   // pack and then cast the arguments to size_t when calling the superclass
781*9356374aSAndroid Build Coastguard Worker   // constructor, similar to what Partial() does. But that would suffer from the
782*9356374aSAndroid Build Coastguard Worker   // same problem that Partial() has, which is that the parameter types are
783*9356374aSAndroid Build Coastguard Worker   // inferred from the arguments, which may be signed types, which must then be
784*9356374aSAndroid Build Coastguard Worker   // cast to size_t. This can lead to negative values being silently (i.e. with
785*9356374aSAndroid Build Coastguard Worker   // no compiler warnings) cast to an unsigned type. Having a constructor with
786*9356374aSAndroid Build Coastguard Worker   // size_t parameters helps the compiler generate better warnings about
787*9356374aSAndroid Build Coastguard Worker   // potential bad casts, while avoiding false warnings when positive literal
788*9356374aSAndroid Build Coastguard Worker   // arguments are used. If an argument is a positive literal integer (e.g.
789*9356374aSAndroid Build Coastguard Worker   // `1`), the compiler will understand that it can be safely converted to
790*9356374aSAndroid Build Coastguard Worker   // size_t, and hence not generate a warning. But if a negative literal (e.g.
791*9356374aSAndroid Build Coastguard Worker   // `-1`) or a variable with signed type is used, then it can generate a
792*9356374aSAndroid Build Coastguard Worker   // warning about a potentially unsafe implicit cast. It would be great if we
793*9356374aSAndroid Build Coastguard Worker   // could do this for Partial() too, but unfortunately as of C++23 there seems
794*9356374aSAndroid Build Coastguard Worker   // to be no way to define a function with a variable number of parameters of a
795*9356374aSAndroid Build Coastguard Worker   // certain type, a.k.a. homogeneous function parameter packs. So we're forced
796*9356374aSAndroid Build Coastguard Worker   // to choose between explicitly casting the arguments to size_t, which
797*9356374aSAndroid Build Coastguard Worker   // suppresses all warnings, even potentially valid ones, or implicitly casting
798*9356374aSAndroid Build Coastguard Worker   // them to size_t, which generates bogus warnings whenever literal arguments
799*9356374aSAndroid Build Coastguard Worker   // are used, even if they're positive.
800*9356374aSAndroid Build Coastguard Worker   using Super::Super;
801*9356374aSAndroid Build Coastguard Worker };
802*9356374aSAndroid Build Coastguard Worker 
803*9356374aSAndroid Build Coastguard Worker }  // namespace internal_layout
804*9356374aSAndroid Build Coastguard Worker 
805*9356374aSAndroid Build Coastguard Worker // Descriptor of arrays of various types and sizes laid out in memory one after
806*9356374aSAndroid Build Coastguard Worker // another. See the top of the file for documentation.
807*9356374aSAndroid Build Coastguard Worker //
808*9356374aSAndroid Build Coastguard Worker // Check out the public API of internal_layout::LayoutWithStaticSizes and
809*9356374aSAndroid Build Coastguard Worker // internal_layout::LayoutImpl above. Those types are internal to the library
810*9356374aSAndroid Build Coastguard Worker // but their methods are public, and they are inherited by `Layout`.
811*9356374aSAndroid Build Coastguard Worker template <class... Ts>
812*9356374aSAndroid Build Coastguard Worker class Layout : public internal_layout::LayoutWithStaticSizes<
813*9356374aSAndroid Build Coastguard Worker                    absl::make_index_sequence<0>, Ts...> {
814*9356374aSAndroid Build Coastguard Worker  private:
815*9356374aSAndroid Build Coastguard Worker   using Super =
816*9356374aSAndroid Build Coastguard Worker       internal_layout::LayoutWithStaticSizes<absl::make_index_sequence<0>,
817*9356374aSAndroid Build Coastguard Worker                                              Ts...>;
818*9356374aSAndroid Build Coastguard Worker 
819*9356374aSAndroid Build Coastguard Worker  public:
820*9356374aSAndroid Build Coastguard Worker   // If you know the sizes of some or all of the arrays at compile time, you can
821*9356374aSAndroid Build Coastguard Worker   // use `WithStaticSizes` or `WithStaticSizeSequence` to create a `Layout` type
822*9356374aSAndroid Build Coastguard Worker   // with those sizes baked in. This can help the compiler generate optimal code
823*9356374aSAndroid Build Coastguard Worker   // for calculating array offsets and AllocSize().
824*9356374aSAndroid Build Coastguard Worker   //
825*9356374aSAndroid Build Coastguard Worker   // Like `Partial()`, the N sizes you specify are for the first N arrays, and
826*9356374aSAndroid Build Coastguard Worker   // they specify the number of elements in each array, not the number of bytes.
827*9356374aSAndroid Build Coastguard Worker   template <class StaticSizeSeq>
828*9356374aSAndroid Build Coastguard Worker   using WithStaticSizeSequence =
829*9356374aSAndroid Build Coastguard Worker       internal_layout::LayoutWithStaticSizes<StaticSizeSeq, Ts...>;
830*9356374aSAndroid Build Coastguard Worker 
831*9356374aSAndroid Build Coastguard Worker   template <size_t... StaticSizes>
832*9356374aSAndroid Build Coastguard Worker   using WithStaticSizes =
833*9356374aSAndroid Build Coastguard Worker       WithStaticSizeSequence<std::index_sequence<StaticSizes...>>;
834*9356374aSAndroid Build Coastguard Worker 
835*9356374aSAndroid Build Coastguard Worker   // Inherit LayoutWithStaticSizes's constructor, which requires you to specify
836*9356374aSAndroid Build Coastguard Worker   // all the array sizes.
837*9356374aSAndroid Build Coastguard Worker   using Super::Super;
838*9356374aSAndroid Build Coastguard Worker };
839*9356374aSAndroid Build Coastguard Worker 
840*9356374aSAndroid Build Coastguard Worker }  // namespace container_internal
841*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
842*9356374aSAndroid Build Coastguard Worker }  // namespace absl
843*9356374aSAndroid Build Coastguard Worker 
844*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_CONTAINER_INTERNAL_LAYOUT_H_
845