160 #ifndef ABSL_CONTAINER_INTERNAL_LAYOUT_H_ 161 #define ABSL_CONTAINER_INTERNAL_LAYOUT_H_ 169 #include <type_traits> 173 #ifdef ADDRESS_SANITIZER 174 #include <sanitizer/asan_interface.h> 182 #if defined(__GXX_RTTI) 183 #define ABSL_INTERNAL_HAS_CXA_DEMANGLE 186 #ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE 191 namespace container_internal {
200 template <
class T,
size_t N>
203 namespace internal_layout {
208 template <
class T,
size_t N>
210 static_assert(
sizeof(T) == 0,
"Aligned<T, N> cannot be const-qualified");
224 template <
class T,
size_t N>
232 template <
class T,
size_t N>
233 struct SizeOf<
Aligned<T, N>> : std::integral_constant<size_t, sizeof(T)> {};
238 static constexpr
size_t value =
alignof(T);
241 template <
class T,
size_t N>
243 static_assert(N %
alignof(T) == 0,
244 "Custom alignment can't be lower than the type's alignment");
249 template <
class T,
class... Ts>
252 template <
class From,
class To>
263 namespace adl_barrier {
265 template <
class Needle,
class... Ts>
266 constexpr
size_t Find(Needle, Needle, Ts...) {
271 template <
class Needle,
class T,
class... Ts>
272 constexpr
size_t Find(Needle, T, Ts...) {
276 constexpr
bool IsPow2(
size_t n) {
return !(n & (n - 1)); }
280 constexpr
size_t Align(
size_t n,
size_t m) {
return (n + m - 1) & ~(m - 1); }
282 constexpr
size_t Min(
size_t a,
size_t b) {
return b < a ?
b :
a; }
284 constexpr
size_t Max(
size_t a) {
return a; }
286 template <
class... Ts>
287 constexpr
size_t Max(
size_t a,
size_t b, Ts... rest) {
295 char* demangled =
nullptr;
296 #ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE 297 demangled = abi::__cxa_demangle(
typeid(T).
name(),
nullptr,
nullptr, &status);
299 if (status == 0 && demangled !=
nullptr) {
303 #if defined(__GXX_RTTI) || defined(_CPPRTTI) 313 using EnableIf =
typename std::enable_if<C, int>::type;
319 !std::is_reference<typename Type<T>::type>
::value &&
320 !std::is_volatile<typename Type<T>::type>
::value &&
323 template <
class Elements,
class SizeSeq,
class OffsetSeq>
337 template <
class... Elements,
size_t... SizeSeq,
size_t... OffsetSeq>
341 static_assert(
sizeof...(Elements) > 0,
"At least one field is required");
343 "Invalid element type (see IsLegalElementType)");
346 NumTypes =
sizeof...(Elements),
347 NumSizes =
sizeof...(SizeSeq),
348 NumOffsets =
sizeof...(OffsetSeq),
354 static_assert(NumTypes > 0,
"Internal error");
368 AlignOf<
typename std::tuple_element<N, std::tuple<Elements...>>::type>;
376 using ElementType =
typename std::tuple_element<N, ElementTypes>::type;
395 template <
size_t N, EnableIf<N == 0> = 0>
400 template <
size_t N, EnableIf<N != 0> = 0>
402 static_assert(N < NumOffsets,
"Index out of bounds");
418 return Offset<ElementIndex<T>()>();
422 constexpr std::array<size_t, NumOffsets>
Offsets()
const {
423 return {{Offset<OffsetSeq>()...}};
436 constexpr
size_t Size()
const {
437 static_assert(N < NumSizes,
"Index out of bounds");
450 constexpr
size_t Size()
const {
451 return Size<ElementIndex<T>()>();
455 constexpr std::array<size_t, NumSizes>
Sizes()
const {
456 return {{Size<SizeSeq>()...}};
471 template <
size_t N,
class Char>
473 using C =
typename std::remove_const<Char>::type;
475 std::is_same<C, char>() || std::is_same<C, unsigned char>() ||
476 std::is_same<C, signed char>(),
477 "The argument must be a pointer to [const] [signed|unsigned] char");
478 constexpr
size_t alignment = Alignment();
480 assert(reinterpret_cast<uintptr_t>(p) % alignment == 0);
497 template <
class T,
class Char>
499 return Pointer<ElementIndex<T>()>(p);
518 template <
class Char>
520 Char,
typename std::tuple_element<OffsetSeq, ElementTypes>::type>*...>
522 return std::tuple<CopyConst<Char, ElementType<OffsetSeq>>*...>(
523 Pointer<OffsetSeq>(p)...);
538 template <
size_t N,
class Char>
555 template <
class T,
class Char>
557 return Slice<ElementIndex<T>()>(p);
576 template <
class Char>
578 Char,
typename std::tuple_element<SizeSeq, ElementTypes>::type>>...>
583 return std::tuple<SliceType<CopyConst<Char, ElementType<SizeSeq>>>...>(
584 Slice<SizeSeq>(p)...);
595 static_assert(NumTypes == NumSizes,
"You must specify sizes of all fields");
596 return Offset<NumTypes - 1>() +
614 static_assert(N < NumOffsets,
"Index out of bounds");
616 #ifdef ADDRESS_SANITIZER 617 PoisonPadding<Char, N - 1>(p);
622 ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start);
644 const auto offsets = Offsets();
646 const std::string types[] = {
647 adl_barrier::TypeName<ElementType<OffsetSeq>>()...};
648 std::string res =
absl::StrCat(
"@0", types[0],
"(", sizes[0],
")");
649 for (
size_t i = 0;
i != NumOffsets - 1; ++
i) {
651 "(", sizes[i + 1],
")");
655 int last =
static_cast<int>(NumSizes) - 1;
656 if (NumTypes == NumSizes && last >= 0) {
664 size_t size_[NumSizes > 0 ? NumSizes : 1];
667 template <
size_t NumSizes,
class... Ts>
680 template <
class... Ts>
683 static_assert(
sizeof...(Ts) > 0,
"At least one field is required");
686 "Invalid element type (see IsLegalElementType)");
689 template <
size_t NumSizes>
718 template <
class... Sizes>
720 static_assert(
sizeof...(Sizes) <=
sizeof...(Ts),
"");
721 return PartialType<
sizeof...(Sizes)>(absl::forward<Sizes>(sizes)...);
733 : internal_layout::LayoutType<sizeof...(Ts), Ts...>(sizes...) {}
739 #endif // ABSL_CONTAINER_INTERNAL_LAYOUT_H_ constexpr std::array< size_t, NumOffsets > Offsets() const
CopyConst< Char, ElementType< N > > * Pointer(Char *p) const
constexpr size_t Find(Needle, Needle, Ts...)
void StrAppend(std::string *dest, const AlphaNum &a)
constexpr std::array< size_t, NumSizes > Sizes() const
SliceType< CopyConst< Char, ElementType< N > > > Slice(Char *p) const
constexpr size_t Max(size_t a, size_t b, Ts... rest)
constexpr size_t Offset() const
constexpr size_t Min(size_t a, size_t b)
std::string DebugString() const
constexpr size_t AllocSize() const
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
constexpr LayoutImpl(IntToSize< SizeSeq >... sizes)
std::integral_constant< bool, !std::is_reference< T >::value &&!std::is_volatile< T >::value &&!std::is_reference< typename Type< T >::type >::value &&!std::is_volatile< typename Type< T >::type >::value &&adl_barrier::IsPow2(AlignOf< T >::value)> IsLegalElementType
make_integer_sequence< size_t, N > make_index_sequence
constexpr size_t Align(size_t n, size_t m)
std::tuple< SliceType< CopyConst< Char, typename std::tuple_element< SizeSeq, ElementTypes >::type > >... > Slices(Char *p) const
constexpr size_t Size() const
constexpr size_t Max(size_t a)
constexpr bool IsPow2(size_t n)
static constexpr size_t ElementIndex()
static constexpr size_t Alignment()
static constexpr PartialType< sizeof...(Sizes)> Partial(Sizes &&... sizes)
constexpr size_t Find(Needle, T, Ts...)
std::tuple< typename Type< Elements >::type... > ElementTypes
void PoisonPadding(const Char *p) const
SliceType< CopyConst< Char, T > > Slice(Char *p) const
std::tuple< CopyConst< Char, typename std::tuple_element< OffsetSeq, ElementTypes >::type > *... > Pointers(Char *p) const
CopyConst< Char, T > * Pointer(Char *p) const
constexpr size_t Offset() const
typename std::tuple_element< N, ElementTypes >::type ElementType
typename std::enable_if< C, int >::type EnableIf
constexpr Layout(internal_layout::TypeToSize< Ts >... sizes)
typename std::conditional< std::is_const< From >::value, const To, To >::type CopyConst