160 #ifndef ABSL_CONTAINER_INTERNAL_LAYOUT_H_
161 #define ABSL_CONTAINER_INTERNAL_LAYOUT_H_
170 #include <type_traits>
174 #include "absl/base/config.h"
175 #include "absl/meta/type_traits.h"
176 #include "absl/strings/str_cat.h"
177 #include "absl/types/span.h"
178 #include "absl/utility/utility.h"
180 #ifdef ABSL_HAVE_ADDRESS_SANITIZER
181 #include <sanitizer/asan_interface.h>
184 #if defined(__GXX_RTTI)
185 #define ABSL_INTERNAL_HAS_CXA_DEMANGLE
188 #ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE
194 namespace container_internal {
203 template <
class T,
size_t N>
206 namespace internal_layout {
211 template <
class T,
size_t N>
213 static_assert(
sizeof(
T) == 0,
"Aligned<T, N> cannot be const-qualified");
227 template <
class T,
size_t N>
235 template <
class T,
size_t N>
241 static constexpr
size_t value =
alignof(
T);
244 template <
class T,
size_t N>
246 static_assert(
N %
alignof(
T) == 0,
247 "Custom alignment can't be lower than the type's alignment");
252 template <
class T,
class... Ts>
255 template <
class From,
class To>
266 namespace adl_barrier {
268 template <
class Needle,
class... Ts>
269 constexpr
size_t Find(Needle, Needle, Ts...) {
274 template <
class Needle,
class T,
class... Ts>
275 constexpr
size_t Find(Needle,
T, Ts...) {
279 constexpr
bool IsPow2(
size_t n) {
return !(
n & (
n - 1)); }
283 constexpr
size_t Align(
size_t n,
size_t m) {
return (
n +
m - 1) & ~(
m - 1); }
285 constexpr
size_t Min(
size_t a,
size_t b) {
return b <
a ?
b :
a; }
287 constexpr
size_t Max(
size_t a) {
return a; }
289 template <
class... Ts>
290 constexpr
size_t Max(
size_t a,
size_t b, Ts... rest) {
298 char* demangled =
nullptr;
299 #ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE
302 if (
status == 0 && demangled !=
nullptr) {
306 #if defined(__GXX_RTTI) || defined(_CPPRTTI)
326 template <
class Elements,
class SizeSeq,
class OffsetSeq>
340 template <
class... Elements,
size_t... SizeSeq,
size_t... OffsetSeq>
344 static_assert(
sizeof...(Elements) > 0,
"At least one field is required");
346 "Invalid element type (see IsLegalElementType)");
349 NumTypes =
sizeof...(Elements),
350 NumSizes =
sizeof...(SizeSeq),
351 NumOffsets =
sizeof...(OffsetSeq),
357 static_assert(NumTypes > 0,
"Internal error");
370 using ElementAlignment =
398 template <
size_t N, EnableIf<N == 0> = 0>
403 template <
size_t N, EnableIf<N != 0> = 0>
405 static_assert(
N < NumOffsets,
"Index out of bounds");
421 return Offset<ElementIndex<T>()>();
425 constexpr std::array<size_t, NumOffsets>
Offsets()
const {
426 return {{Offset<OffsetSeq>()...}};
439 constexpr
size_t Size()
const {
440 static_assert(
N < NumSizes,
"Index out of bounds");
453 constexpr
size_t Size()
const {
454 return Size<ElementIndex<T>()>();
458 constexpr std::array<size_t, NumSizes>
Sizes()
const {
459 return {{Size<SizeSeq>()...}};
474 template <
size_t N,
class Char>
478 std::is_same<C, char>() || std::is_same<C, unsigned char>() ||
479 std::is_same<C, signed char>(),
480 "The argument must be a pointer to [const] [signed|unsigned] char");
481 constexpr
size_t alignment = Alignment();
500 template <
class T,
class Char>
502 return Pointer<ElementIndex<T>()>(p);
521 template <
class Char>
525 return std::tuple<CopyConst<Char, ElementType<OffsetSeq>>*...>(
526 Pointer<OffsetSeq>(p)...);
541 template <
size_t N,
class Char>
558 template <
class T,
class Char>
560 return Slice<ElementIndex<T>()>(p);
579 template <
class Char>
586 return std::tuple<SliceType<CopyConst<Char, ElementType<SizeSeq>>>...>(
587 Slice<SizeSeq>(p)...);
598 static_assert(NumTypes == NumSizes,
"You must specify sizes of all fields");
599 return Offset<NumTypes - 1>() +
617 static_assert(
N < NumOffsets,
"Index out of bounds");
619 #ifdef ABSL_HAVE_ADDRESS_SANITIZER
620 PoisonPadding<
Char,
N - 1>(p);
625 ASAN_POISON_MEMORY_REGION(p +
start, Offset<N>() -
start);
647 const auto offsets = Offsets();
650 adl_barrier::TypeName<ElementType<OffsetSeq>>()...};
652 for (
size_t i = 0;
i != NumOffsets - 1; ++
i) {
654 "(", sizes[
i + 1],
")");
658 int last =
static_cast<int>(NumSizes) - 1;
659 if (NumTypes == NumSizes && last >= 0) {
667 size_t size_[NumSizes > 0 ? NumSizes : 1];
670 template <
size_t NumSizes,
class... Ts>
683 template <
class... Ts>
686 static_assert(
sizeof...(Ts) > 0,
"At least one field is required");
689 "Invalid element type (see IsLegalElementType)");
692 template <
size_t NumSizes>
721 template <
class... Sizes>
723 static_assert(
sizeof...(Sizes) <=
sizeof...(Ts),
"");
724 return PartialType<
sizeof...(Sizes)>(absl::forward<Sizes>(sizes)...);
736 : internal_layout::
LayoutType<sizeof...(Ts), Ts...>(sizes...) {}
743 #endif // ABSL_CONTAINER_INTERNAL_LAYOUT_H_