File indexing completed on 2026-05-03 08:13:45
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef _LIBCPP___CXX03___UTILITY_SMALL_BUFFER_H
0010 #define _LIBCPP___CXX03___UTILITY_SMALL_BUFFER_H
0011
0012 #include <__cxx03/__config>
0013 #include <__cxx03/__memory/construct_at.h>
0014 #include <__cxx03/__type_traits/decay.h>
0015 #include <__cxx03/__type_traits/is_trivially_constructible.h>
0016 #include <__cxx03/__type_traits/is_trivially_destructible.h>
0017 #include <__cxx03/__utility/exception_guard.h>
0018 #include <__cxx03/__utility/forward.h>
0019 #include <__cxx03/cstddef>
0020 #include <__cxx03/new>
0021
0022 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0023 # pragma GCC system_header
0024 #endif
0025
0026 #if _LIBCPP_STD_VER >= 23
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 _LIBCPP_BEGIN_NAMESPACE_STD
0037
0038 template <size_t _BufferSize, size_t _BufferAlignment>
0039 requires(_BufferSize > 0 && _BufferAlignment > 0)
0040 class __small_buffer {
0041 public:
0042 template <class _Tp, class _Decayed = decay_t<_Tp>>
0043 static constexpr bool __fits_in_buffer =
0044 is_trivially_move_constructible_v<_Decayed> && is_trivially_destructible_v<_Decayed> &&
0045 sizeof(_Decayed) <= _BufferSize && alignof(_Decayed) <= _BufferAlignment;
0046
0047 _LIBCPP_HIDE_FROM_ABI __small_buffer() = default;
0048 __small_buffer(const __small_buffer&) = delete;
0049 __small_buffer& operator=(const __small_buffer&) = delete;
0050 _LIBCPP_HIDE_FROM_ABI ~__small_buffer() = default;
0051
0052
0053 _LIBCPP_HIDE_FROM_ABI __small_buffer(__small_buffer&&) = default;
0054 _LIBCPP_HIDE_FROM_ABI __small_buffer& operator=(__small_buffer&&) = default;
0055
0056 template <class _Stored>
0057 _LIBCPP_HIDE_FROM_ABI _Stored* __get() {
0058 if constexpr (__fits_in_buffer<_Stored>)
0059 return std::launder(reinterpret_cast<_Stored*>(__buffer_));
0060 else
0061 return *std::launder(reinterpret_cast<_Stored**>(__buffer_));
0062 }
0063
0064 template <class _Stored>
0065 _LIBCPP_HIDE_FROM_ABI _Stored* __alloc() {
0066 if constexpr (__fits_in_buffer<_Stored>) {
0067 return std::launder(reinterpret_cast<_Stored*>(__buffer_));
0068 } else {
0069 byte* __allocation = static_cast<byte*>(::operator new[](sizeof(_Stored), align_val_t{alignof(_Stored)}));
0070 std::construct_at(reinterpret_cast<byte**>(__buffer_), __allocation);
0071 return std::launder(reinterpret_cast<_Stored*>(__allocation));
0072 }
0073 }
0074
0075 template <class _Stored>
0076 _LIBCPP_HIDE_FROM_ABI void __dealloc() noexcept {
0077 if constexpr (!__fits_in_buffer<_Stored>)
0078 ::operator delete[](*reinterpret_cast<void**>(__buffer_), sizeof(_Stored), align_val_t{alignof(_Stored)});
0079 }
0080
0081 template <class _Stored, class... _Args>
0082 _LIBCPP_HIDE_FROM_ABI void __construct(_Args&&... __args) {
0083 _Stored* __buffer = __alloc<_Stored>();
0084 auto __guard = std::__make_exception_guard([&] { __dealloc<_Stored>(); });
0085 std::construct_at(__buffer, std::forward<_Args>(__args)...);
0086 __guard.__complete();
0087 }
0088
0089 private:
0090 alignas(_BufferAlignment) byte __buffer_[_BufferSize];
0091 };
0092
0093 # undef _LIBCPP_SMALL_BUFFER_TRIVIAL_ABI
0094
0095 _LIBCPP_END_NAMESPACE_STD
0096
0097 #endif
0098
0099 #endif