#pragma once #include #include #include #include #include #include #include #include namespace detail { template struct __nth__ { }; template struct __nth__<0, _Tp0, _Rest...> { using type = _Tp0; }; template struct __nth__<1, _Tp0, _Tp1, _Rest...> { using type = _Tp1; }; template struct __nth__<2, _Tp0, _Tp1, _Tp2, _Rest...> { using type = _Tp2; }; template struct __nth__<_Np, _Tp0, _Tp1, _Tp2, _Rest...> : __nth__<_Np - 3, _Rest...> { }; template using _Select_nth_type = typename __nth__<_Idx, _Types...>::type; template struct _Select_int_base; template struct _Select_int_base<_Val, _IntType, _Ints...> : std::conditional_t<(_Val <= std::numeric_limits<_IntType>::max()), std::integral_constant<_IntType, (_IntType)_Val>, _Select_int_base<_Val, _Ints...>> { }; template struct _Select_int_base<_Val> { }; template using _Select_int = typename _Select_int_base<_Val, unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long>::type:: value_type; } // namespace detail namespace impl::variadic { #pragma packed(push, 1) template struct _Index_base { _Index_type __this_; _Index_type __next_; constexpr _Index_base(const _Index_type __i, const _Index_type __j) noexcept : __this_{__i}, __next_{__j} {} }; #pragma packed(pop) template struct _Element : public _Index_base<_Index_type>, public no_unique_address_emulation<_Ty> { template explicit constexpr _Element(const std::size_t __i, _Args&&... __ctors) // noexcept(std::is_nothrow_constructible_v<_Ty, _Args...>) : _Index_base<_Index_type>{static_cast<_Index_type>(__i), std::numeric_limits<_Index_type>::max()}, no_unique_address_emulation<_Ty>(std::forward<_Args>(__ctors)...) { } }; template struct __vtable__ { template > static void _S_invoke(_Visitor&& __visitor, void* __ptr) noexcept(std::is_nothrow_invocable_v<_Visitor, _Ty&>) { auto* __box = std::launder(reinterpret_cast<_Box<_Ty>*>(__ptr)); std::forward<_Visitor>(__visitor)(__box->__val_); } template static constexpr auto _S_make_vtab(std::index_sequence<_Indices...>) noexcept { return std::array{&_S_invoke<_Indices>...}; } static constexpr auto __vtab_ = _S_make_vtab(std::index_sequence_for<_Types...>{}); }; } // namespace impl::variadic template struct variadic { using _Index_type = detail::_Select_int; struct _Idx_base { _Index_type __this_; _Index_type __next_; } __attribute__((__packed__)); template struct _Box : public _Idx_base { [[__no_unique_address__]] _Ty __val_; template explicit constexpr _Box(const std::size_t __i, _Args&&... __ctors) noexcept(std::is_nothrow_constructible_v<_Ty, _Args...>) : _Idx_base{static_cast<_Index_type>(__i), std::numeric_limits<_Index_type>::max()}, __val_(std::forward<_Args>(__ctors)...) { } }; static constexpr std::size_t __max_align_ = std::max({std::alignment_of_v<_Box<_Types>>...}); template struct __vtable__ { template > static void _S_invoke(_Visitor&& __visitor, void* __ptr) noexcept(std::is_nothrow_invocable_v<_Visitor, _Ty&>) { auto* __box = std::launder(reinterpret_cast<_Box<_Ty>*>(__ptr)); std::forward<_Visitor>(__visitor)(__box->__val_); } template static constexpr auto _S_make_vtab(std::index_sequence<_Indices...>) noexcept { return std::array{&_S_invoke<_Indices>...}; } static constexpr auto __vtab_ = _S_make_vtab(std::index_sequence_for<_Types...>{}); }; alignas(__max_align_) std::byte __data_[__Sp_]; void* __p_ = &__data_[0]; std::size_t __sz_ = __Sp_; std::size_t __count_ = 0; _Index_type* __next_ = nullptr; template [[__nodiscard__]] // _Ty* _M_implicit_aligned_alloc(const std::size_t __align = alignof(_Ty)) noexcept { if (std::align(__align, sizeof(_Ty), __p_, __sz_)) [[__likely__]] { _Ty* __result = std::launder(reinterpret_cast<_Ty*>(__p_)); __p_ = static_cast(__p_) + sizeof(_Ty); __sz_ -= sizeof(_Ty); return __result; } return nullptr; } template > _Result& emplace_back(_Args&&... __ctors) { if (__next_) { *__next_ = static_cast<_Index_type>(_Idx); } if (auto* __ptr = _M_implicit_aligned_alloc<_Box<_Result>>()) [[__likely__]] { ::new (__ptr) _Box<_Result>{_Idx, std::forward<_Args>(__ctors)...}; __next_ = &__ptr->__next_; ++__count_; return __ptr->__val_; } throw std::bad_alloc{}; } template void loop(_Visitor&& __visitor) { if (__count_ == 0) [[__unlikely__]] { return; } static constexpr auto& __table_ = __vtable__<_Visitor&&>::__vtab_; void* __current = &__data_[0]; const void* const __end = __p_; while (__current < __end) [[__likely__]] { auto* __base = std::launder(reinterpret_cast<_Idx_base*>(__current)); const auto __i = __base->__this_; const auto __j = __base->__next_; if (__i < sizeof...(_Types)) [[__likely__]] { __table_[__i](std::forward<_Visitor>(__visitor), __current); } __current = _S_advance_ptr(__current, __i, __j); } } private: template static void* _S_advance_ptr_impl(const void* __ptr, const std::size_t __i, const std::size_t __j, std::index_sequence<_Indices...>) noexcept { static constexpr std::array __alignments_ = {std::alignment_of_v<_Box<_Types>>...}; static constexpr std::array __sizes_ = {sizeof(_Box<_Types>)...}; const auto __intptr = reinterpret_cast(__ptr) + __sizes_[__i]; if (__j == std::numeric_limits<_Index_type>::max()) { // NOLINTNEXTLINE return reinterpret_cast(__intptr); } const auto __align = __alignments_[__j]; const auto __result = (__intptr - 1U + __align) & -__align; // NOLINTNEXTLINE return reinterpret_cast(__result); } static void* _S_advance_ptr(const void* __ptr, const std::size_t __i, const std::size_t __j) { return _S_advance_ptr_impl(__ptr, __i, __j, std::index_sequence_for<_Types...>{}); } public: [[__nodiscard__]] std::size_t size() const noexcept { return __count_; } [[__nodiscard__]] bool empty() const noexcept { return __count_ == 0; } [[__nodiscard__]] std::size_t capacity() const noexcept { return __Sp_; } [[__nodiscard__]] std::size_t available() const noexcept { return __sz_; } void clear() noexcept { loop([] [[__gnu__::__always_inline__]] (auto& __obj) noexcept { using _Type = std::decay_t; if constexpr (!std::is_trivially_destructible_v<_Type>) { __obj.~_Type(); } }); __p_ = &__data_[0]; __sz_ = __Sp_; __count_ = 0; } ~variadic() { clear(); } };