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