// sol2 // The MIT License (MIT) // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of // the Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef SOL_STACK_CORE_HPP #define SOL_STACK_CORE_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace sol { namespace detail { struct with_function_tag { }; struct as_reference_tag { }; template struct as_pointer_tag { }; template struct as_value_tag { }; template struct as_unique_tag { }; template struct as_table_tag { }; template inline constexpr bool is_tagged_v = meta::is_specialization_of_v || meta::is_specialization_of_v || meta::is_specialization_of_v || meta::is_specialization_of_v || std::is_same_v || std::is_same_v; using lua_reg_table = luaL_Reg[64]; using unique_destructor = void (*)(void*); using unique_tag = detail::inheritance_unique_cast_function; inline void* alloc_newuserdata(lua_State* L, std::size_t bytesize) { #if SOL_LUA_VERSION_I_ >= 504 return lua_newuserdatauv(L, bytesize, 1); #else return lua_newuserdata(L, bytesize); #endif } constexpr std::uintptr_t align(std::size_t alignment, std::uintptr_t ptr, std::size_t& space) { // this handles arbitrary alignments... // make this into a power-of-2-only? // actually can't: this is a C++14-compatible framework, // power of 2 alignment is C++17 std::uintptr_t offby = static_cast(ptr % alignment); std::uintptr_t padding = (alignment - offby) % alignment; ptr += padding; space -= padding; return ptr; } inline void* align(std::size_t alignment, void* ptr, std::size_t& space) { return reinterpret_cast(align(alignment, reinterpret_cast(ptr), space)); } constexpr std::uintptr_t align_one(std::size_t alignment, std::size_t size, std::uintptr_t ptr) { std::size_t space = (std::numeric_limits::max)(); return align(alignment, ptr, space) + size; } template constexpr std::size_t aligned_space_for(std::uintptr_t ptr) { std::uintptr_t end = ptr; ((end = align_one(alignof(Args), sizeof(Args), end)), ...); return static_cast(end - ptr); } template constexpr std::size_t aligned_space_for() { static_assert(sizeof...(Args) > 0); constexpr std::size_t max_arg_alignment = (std::max)({ alignof(Args)... }); if constexpr (max_arg_alignment <= alignof(std::max_align_t)) { // If all types are `good enough`, simply calculate alignment in case of the worst allocator std::size_t worst_required_size = 0; for (std::size_t ptr = 0; ptr < max_arg_alignment; ptr++) { worst_required_size = (std::max)(worst_required_size, aligned_space_for(ptr)); } return worst_required_size; } else { // For over-aligned types let's assume that every Arg in Args starts at the worst aligned address return (aligned_space_for(0x1) + ...); } } inline void* align_usertype_pointer(void* ptr) { using use_align = std::integral_constant::value > 1) #endif >; if (!use_align::value) { return ptr; } std::size_t space = (std::numeric_limits::max)(); return align(std::alignment_of::value, ptr, space); } template void* align_usertype_unique_destructor(void* ptr) { using use_align = std::integral_constant::value > 1) #endif >; if (!pre_aligned) { ptr = align_usertype_pointer(ptr); } if (!pre_shifted) { ptr = static_cast(static_cast(ptr) + sizeof(void*)); } if (!use_align::value) { return static_cast(static_cast(ptr) + 1); } std::size_t space = (std::numeric_limits::max)(); return align(std::alignment_of::value, ptr, space); } template void* align_usertype_unique_tag(void* ptr) { using use_align = std::integral_constant::value > 1) #endif >; if (!pre_aligned) { ptr = align_usertype_unique_destructor(ptr); } if (!pre_shifted) { ptr = static_cast(static_cast(ptr) + sizeof(unique_destructor)); } if (!use_align::value) { return ptr; } std::size_t space = (std::numeric_limits::max)(); return align(std::alignment_of::value, ptr, space); } template void* align_usertype_unique(void* ptr) { typedef std::integral_constant > 1) #endif > use_align; if (!pre_aligned) { ptr = align_usertype_unique_tag(ptr); } if (!pre_shifted) { ptr = static_cast(static_cast(ptr) + sizeof(unique_tag)); } if (!use_align::value) { return ptr; } std::size_t space = (std::numeric_limits::max)(); return align(std::alignment_of_v, ptr, space); } template void* align_user(void* ptr) { typedef std::integral_constant > 1) #endif > use_align; if (!use_align::value) { return ptr; } std::size_t space = (std::numeric_limits::max)(); return align(std::alignment_of_v, ptr, space); } template T** usertype_allocate_pointer(lua_State* L) { typedef std::integral_constant::value > 1) #endif > use_align; if (!use_align::value) { T** pointerpointer = static_cast(alloc_newuserdata(L, sizeof(T*))); return pointerpointer; } constexpr std::size_t initial_size = aligned_space_for(); std::size_t allocated_size = initial_size; void* unadjusted = alloc_newuserdata(L, initial_size); void* adjusted = align(std::alignment_of::value, unadjusted, allocated_size); if (adjusted == nullptr) { // trash allocator can burn in hell lua_pop(L, 1); // luaL_error(L, "if you are the one that wrote this allocator you should feel bad for doing a // worse job than malloc/realloc and should go read some books, yeah?"); luaL_error(L, "cannot properly align memory for '%s'", detail::demangle().data()); } return static_cast(adjusted); } inline bool attempt_alloc(lua_State* L, std::size_t ptr_align, std::size_t ptr_size, std::size_t value_align, std::size_t allocated_size, void*& pointer_adjusted, void*& data_adjusted) { void* adjusted = alloc_newuserdata(L, allocated_size); pointer_adjusted = align(ptr_align, adjusted, allocated_size); if (pointer_adjusted == nullptr) { lua_pop(L, 1); return false; } // subtract size of what we're going to allocate there allocated_size -= ptr_size; adjusted = static_cast(static_cast(pointer_adjusted) + ptr_size); data_adjusted = align(value_align, adjusted, allocated_size); if (data_adjusted == nullptr) { lua_pop(L, 1); return false; } return true; } inline bool attempt_alloc_unique(lua_State* L, std::size_t ptr_align, std::size_t ptr_size, std::size_t real_align, std::size_t allocated_size, void*& pointer_adjusted, void*& dx_adjusted, void*& id_adjusted, void*& data_adjusted) { void* adjusted = alloc_newuserdata(L, allocated_size); pointer_adjusted = align(ptr_align, adjusted, allocated_size); if (pointer_adjusted == nullptr) { lua_pop(L, 1); return false; } allocated_size -= ptr_size; adjusted = static_cast(static_cast(pointer_adjusted) + ptr_size); dx_adjusted = align(std::alignment_of_v, adjusted, allocated_size); if (dx_adjusted == nullptr) { lua_pop(L, 1); return false; } allocated_size -= sizeof(unique_destructor); adjusted = static_cast(static_cast(dx_adjusted) + sizeof(unique_destructor)); id_adjusted = align(std::alignment_of_v, adjusted, allocated_size); if (id_adjusted == nullptr) { lua_pop(L, 1); return false; } allocated_size -= sizeof(unique_tag); adjusted = static_cast(static_cast(id_adjusted) + sizeof(unique_tag)); data_adjusted = align(real_align, adjusted, allocated_size); if (data_adjusted == nullptr) { lua_pop(L, 1); return false; } return true; } template T* usertype_allocate(lua_State* L) { typedef std::integral_constant::value > 1 || std::alignment_of_v > 1) #endif > use_align; if (!use_align::value) { T** pointerpointer = static_cast(alloc_newuserdata(L, sizeof(T*) + sizeof(T))); T*& pointerreference = *pointerpointer; T* allocationtarget = reinterpret_cast(pointerpointer + 1); pointerreference = allocationtarget; return allocationtarget; } constexpr std::size_t initial_size = aligned_space_for(); void* pointer_adjusted; void* data_adjusted; bool result = attempt_alloc(L, std::alignment_of_v, sizeof(T*), std::alignment_of_v, initial_size, pointer_adjusted, data_adjusted); if (!result) { if (pointer_adjusted == nullptr) { luaL_error(L, "aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle().c_str()); } else { luaL_error(L, "aligned allocation of userdata block (data section) for '%s' failed", detail::demangle().c_str()); } return nullptr; } T** pointerpointer = reinterpret_cast(pointer_adjusted); T*& pointerreference = *pointerpointer; T* allocationtarget = reinterpret_cast(data_adjusted); pointerreference = allocationtarget; return allocationtarget; } template Real* usertype_unique_allocate(lua_State* L, T**& pref, unique_destructor*& dx, unique_tag*& id) { typedef std::integral_constant::value > 1 || std::alignment_of::value > 1 || std::alignment_of::value > 1 || std::alignment_of::value > 1) #endif > use_align; if (!use_align::value) { pref = static_cast(alloc_newuserdata(L, sizeof(T*) + sizeof(detail::unique_destructor) + sizeof(unique_tag) + sizeof(Real))); dx = static_cast(static_cast(pref + 1)); id = static_cast(static_cast(dx + 1)); Real* mem = static_cast(static_cast(id + 1)); return mem; } constexpr std::size_t initial_size = aligned_space_for(); void* pointer_adjusted = nullptr; void* dx_adjusted = nullptr; void* id_adjusted = nullptr; void* data_adjusted = nullptr; bool result = attempt_alloc_unique(L, std::alignment_of_v, sizeof(T*), std::alignment_of_v, initial_size, pointer_adjusted, dx_adjusted, id_adjusted, data_adjusted); if (!result) { if (pointer_adjusted == nullptr) { luaL_error(L, "aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle().c_str()); } else if (dx_adjusted == nullptr) { luaL_error(L, "aligned allocation of userdata block (deleter section) for '%s' failed", detail::demangle().c_str()); } else { luaL_error(L, "aligned allocation of userdata block (data section) for '%s' failed", detail::demangle().c_str()); } return nullptr; } pref = static_cast(pointer_adjusted); dx = static_cast(dx_adjusted); id = static_cast(id_adjusted); Real* mem = static_cast(data_adjusted); return mem; } template T* user_allocate(lua_State* L) { typedef std::integral_constant > 1) #endif > use_align; if (!use_align::value) { T* pointer = static_cast(alloc_newuserdata(L, sizeof(T))); return pointer; } constexpr std::size_t initial_size = aligned_space_for(); std::size_t allocated_size = initial_size; void* unadjusted = alloc_newuserdata(L, allocated_size); void* adjusted = align(std::alignment_of_v, unadjusted, allocated_size); if (adjusted == nullptr) { lua_pop(L, 1); luaL_error(L, "cannot properly align memory for '%s'", detail::demangle().data()); } return static_cast(adjusted); } template int usertype_alloc_destroy(lua_State* L) noexcept { void* memory = lua_touserdata(L, 1); memory = align_usertype_pointer(memory); T** pdata = static_cast(memory); T* data = *pdata; std::allocator alloc {}; std::allocator_traits>::destroy(alloc, data); return 0; } template int unique_destroy(lua_State* L) noexcept { void* memory = lua_touserdata(L, 1); memory = align_usertype_unique_destructor(memory); unique_destructor& dx = *static_cast(memory); memory = align_usertype_unique_tag(memory); (dx)(memory); return 0; } template int user_alloc_destroy(lua_State* L) noexcept { void* memory = lua_touserdata(L, 1); void* aligned_memory = align_user(memory); T* typed_memory = static_cast(aligned_memory); std::allocator alloc; std::allocator_traits>::destroy(alloc, typed_memory); return 0; } template void usertype_unique_alloc_destroy(void* memory) { void* aligned_memory = align_usertype_unique(memory); Real* typed_memory = static_cast(aligned_memory); std::allocator alloc; std::allocator_traits>::destroy(alloc, typed_memory); } template int cannot_destroy(lua_State* L) { return luaL_error(L, "cannot call the destructor for '%s': it is either hidden (protected/private) or removed with '= " "delete' and thusly this type is being destroyed without properly destroying, invoking undefined " "behavior: please bind a usertype and specify a custom destructor to define the behavior properly", detail::demangle().data()); } template void reserve(T&, std::size_t) { } template void reserve(std::vector& vec, std::size_t hint) { vec.reserve(hint); } template void reserve(std::basic_string& str, std::size_t hint) { str.reserve(hint); } inline bool property_always_true(meta_function) { return true; } struct properties_enrollment_allowed { int& times_through; std::bitset<64>& properties; automagic_enrollments& enrollments; properties_enrollment_allowed(int& times_through_, std::bitset<64>& properties_, automagic_enrollments& enrollments_) : times_through(times_through_), properties(properties_), enrollments(enrollments_) { } bool operator()(meta_function mf) const { bool p = properties[static_cast(mf)]; if (times_through > 0) { return p; } switch (mf) { case meta_function::length: return enrollments.length_operator && !p; case meta_function::pairs: return enrollments.pairs_operator && !p; case meta_function::call: return enrollments.call_operator && !p; case meta_function::less_than: return enrollments.less_than_operator && !p; case meta_function::less_than_or_equal_to: return enrollments.less_than_or_equal_to_operator && !p; case meta_function::equal_to: return enrollments.equal_to_operator && !p; default: break; } return !p; } }; struct indexed_insert { lua_reg_table& registration_table; int& index; indexed_insert(lua_reg_table& registration_table_, int& index_ref_) : registration_table(registration_table_), index(index_ref_) { } void operator()(meta_function meta_function_name_, lua_CFunction c_function_) { registration_table[index] = luaL_Reg { to_string(meta_function_name_).c_str(), c_function_ }; ++index; } }; } // namespace detail namespace stack { template struct field_getter; template struct probe_field_getter; template struct field_setter; template struct unqualified_getter; template struct qualified_getter; template struct qualified_interop_getter; template struct unqualified_interop_getter; template struct popper; template struct unqualified_pusher; template struct unqualified_checker; template struct qualified_checker; template struct unqualified_check_getter; template struct qualified_check_getter; struct probe { bool success; int levels; probe(bool s, int l) : success(s), levels(l) { } operator bool() const { return success; }; }; struct record { int last; int used; record() noexcept : last(), used() { } void use(int count) noexcept { last = count; used += count; } }; namespace stack_detail { template Function* get_function_pointer(lua_State*, int, record&) noexcept; template bool check_function_pointer(lua_State* L, int index, Handler&& handler, record& tracking) noexcept; } // namespace stack_detail } // namespace stack namespace meta { namespace meta_detail { template using adl_sol_lua_get_test_t = decltype(sol_lua_get(types(), static_cast(nullptr), -1, std::declval())); template using adl_sol_lua_interop_get_test_t = decltype(sol_lua_interop_get(types(), static_cast(nullptr), -1, static_cast(nullptr), std::declval())); template using adl_sol_lua_check_test_t = decltype(sol_lua_check(types(), static_cast(nullptr), -1, &no_panic, std::declval())); template using adl_sol_lua_interop_check_test_t = decltype(sol_lua_interop_check(types(), static_cast(nullptr), -1, type::none, &no_panic, std::declval())); template using adl_sol_lua_check_get_test_t = decltype(sol_lua_check_get(types(), static_cast(nullptr), -1, &no_panic, std::declval())); template using adl_sol_lua_push_test_t = decltype(sol_lua_push(static_cast(nullptr), std::declval()...)); template using adl_sol_lua_push_exact_test_t = decltype(sol_lua_push(types(), static_cast(nullptr), std::declval()...)); template inline constexpr bool is_adl_sol_lua_get_v = meta::is_detected_v; template inline constexpr bool is_adl_sol_lua_interop_get_v = meta::is_detected_v; template inline constexpr bool is_adl_sol_lua_check_v = meta::is_detected_v; template inline constexpr bool is_adl_sol_lua_interop_check_v = meta::is_detected_v; template inline constexpr bool is_adl_sol_lua_check_get_v = meta::is_detected_v; template inline constexpr bool is_adl_sol_lua_push_v = meta::is_detected_v; template inline constexpr bool is_adl_sol_lua_push_exact_v = meta::is_detected_v; }} // namespace meta::meta_detail namespace stack { namespace stack_detail { constexpr const char* not_enough_stack_space = "not enough space left on Lua stack"; constexpr const char* not_enough_stack_space_floating = "not enough space left on Lua stack for a floating point number"; constexpr const char* not_enough_stack_space_integral = "not enough space left on Lua stack for an integral number"; constexpr const char* not_enough_stack_space_string = "not enough space left on Lua stack for a string"; constexpr const char* not_enough_stack_space_meta_function_name = "not enough space left on Lua stack for the name of a meta_function"; constexpr const char* not_enough_stack_space_userdata = "not enough space left on Lua stack to create a sol2 userdata"; constexpr const char* not_enough_stack_space_generic = "not enough space left on Lua stack to push valuees"; constexpr const char* not_enough_stack_space_environment = "not enough space left on Lua stack to retrieve environment"; template struct strip { typedef T type; }; template struct strip> { typedef T& type; }; template struct strip> { typedef T& type; }; template struct strip> { typedef T type; }; template using strip_t = typename strip::type; template static int get_size_hint(C& c) { return static_cast(c.size()); } template static int get_size_hint(const std::forward_list&) { // forward_list makes me sad return static_cast(32); } template decltype(auto) unchecked_unqualified_get(lua_State* L, int index, record& tracking) { using Tu = meta::unqualified_t; if constexpr (meta::meta_detail::is_adl_sol_lua_get_v) { return sol_lua_get(types(), L, index, tracking); } else { unqualified_getter g {}; return g.get(L, index, tracking); } } template decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) { if constexpr (meta::meta_detail::is_adl_sol_lua_get_v) { return sol_lua_get(types(), L, index, tracking); } else { qualified_getter g {}; return g.get(L, index, tracking); } } template decltype(auto) unqualified_interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) { using Tu = meta::unqualified_t; if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v) { return sol_lua_interop_get(types(), L, index, unadjusted_pointer, tracking); } else { (void)L; (void)index; (void)unadjusted_pointer; (void)tracking; using Ti = stack_detail::strip_t; return std::pair { false, nullptr }; } } template decltype(auto) interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) { if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v) { return sol_lua_interop_get(types(), L, index, unadjusted_pointer, tracking); } else { return unqualified_interop_get(L, index, unadjusted_pointer, tracking); } } template bool unqualified_interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) { using Tu = meta::unqualified_t; if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v) { return sol_lua_interop_check(types(), L, index, index_type, std::forward(handler), tracking); } else { (void)L; (void)index; (void)index_type; (void)handler; (void)tracking; return false; } } template bool interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) { if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v) { return sol_lua_interop_check(types(), L, index, index_type, std::forward(handler), tracking); } else { return unqualified_interop_check(L, index, index_type, std::forward(handler), tracking); } } using undefined_method_func = void (*)(stack_reference); struct undefined_metatable { lua_State* L; const char* key; undefined_method_func on_new_table; undefined_metatable(lua_State* l, const char* k, undefined_method_func umf) : L(l), key(k), on_new_table(umf) { } void operator()() const { if (luaL_newmetatable(L, key) == 1) { on_new_table(stack_reference(L, -1)); } lua_setmetatable(L, -2); } }; } // namespace stack_detail inline bool maybe_indexable(lua_State* L, int index = -1) { type t = type_of(L, index); return t == type::userdata || t == type::table; } inline int top(lua_State* L) { return lua_gettop(L); } inline bool is_main_thread(lua_State* L) { int ismainthread = lua_pushthread(L); lua_pop(L, 1); return ismainthread == 1; } inline void coroutine_create_guard(lua_State* L) { if (is_main_thread(L)) { return; } int stacksize = lua_gettop(L); if (stacksize < 1) { return; } if (type_of(L, 1) != type::function) { return; } // well now we're screwed... // we can clean the stack and pray it doesn't destroy anything? lua_pop(L, stacksize); } inline void clear(lua_State* L, int table_index) { lua_pushnil(L); while (lua_next(L, table_index) != 0) { // remove value lua_pop(L, 1); // duplicate key to protect form rawset lua_pushvalue(L, -1); // push new value lua_pushnil(L); // table_index%[key] = nil lua_rawset(L, table_index); } } inline void clear(reference& r) { auto pp = push_pop(r); int stack_index = pp.index_of(r); clear(r.lua_state(), stack_index); } inline void clear(stack_reference& r) { clear(r.lua_state(), r.stack_index()); } inline void clear(lua_State* L_, stateless_reference& r) { r.push(L_); int stack_index = absolute_index(L_, -1); clear(L_, stack_index); r.pop(L_); } inline void clear(lua_State* L_, stateless_stack_reference& r) { clear(L_, r.stack_index()); } template int push(lua_State* L, T&& t, Args&&... args) { using Tu = meta::unqualified_t; if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v) { return sol_lua_push(types(), L, std::forward(t), std::forward(args)...); } else if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v) { return sol_lua_push(types(), L, std::forward(t), std::forward(args)...); } else if constexpr (meta::meta_detail::is_adl_sol_lua_push_v) { return sol_lua_push(L, std::forward(t), std::forward(args)...); } else { unqualified_pusher p {}; return p.push(L, std::forward(t), std::forward(args)...); } } // overload allows to use a pusher of a specific type, but pass in any kind of args template ::value>> int push(lua_State* L, Arg&& arg, Args&&... args) { using Tu = meta::unqualified_t; if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v) { return sol_lua_push(types(), L, std::forward(arg), std::forward(args)...); } else if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v) { return sol_lua_push(types(), L, std::forward(arg), std::forward(args)...); } else if constexpr (meta::meta_detail::is_adl_sol_lua_push_v && !detail::is_tagged_v) { return sol_lua_push(L, std::forward(arg), std::forward(args)...); } else { unqualified_pusher p {}; return p.push(L, std::forward(arg), std::forward(args)...); } } template int push_userdata(lua_State* L, T&& t, Args&&... args) { using U = meta::unqualified_t; using Tr = meta::conditional_t, detail::as_pointer_tag>, meta::conditional_t, detail::as_unique_tag, detail::as_value_tag>>; return stack::push(L, std::forward(t), std::forward(args)...); } template int push_userdata(lua_State* L, Arg&& arg, Args&&... args) { using U = meta::unqualified_t; using Tr = meta::conditional_t, detail::as_pointer_tag>, meta::conditional_t, detail::as_unique_tag, detail::as_value_tag>>; return stack::push(L, std::forward(arg), std::forward(args)...); } namespace stack_detail { template int push_reference(lua_State* L, Arg&& arg, Args&&... args) { // clang-format off using use_reference_tag = meta::all< meta::neg> #if SOL_IS_OFF(SOL_FUNCTION_CALL_VALUE_SEMANTICS) , std::is_lvalue_reference, meta::neg>>, meta::neg>>, meta::neg>> #endif >; // clang-format on using Tr = meta::conditional_t>; return stack::push(L, std::forward(arg), std::forward(args)...); } } // namespace stack_detail template int push_reference(lua_State* L, T&& t, Args&&... args) { return stack_detail::push_reference(L, std::forward(t), std::forward(args)...); } template int push_reference(lua_State* L, Arg&& arg, Args&&... args) { return stack_detail::push_reference(L, std::forward(arg), std::forward(args)...); } inline int multi_push(lua_State*) { // do nothing return 0; } template int multi_push(lua_State* L, T&& t, Args&&... args) { int pushcount = push(L, std::forward(t)); void(detail::swallow { (pushcount += stack::push(L, std::forward(args)), 0)... }); return pushcount; } inline int multi_push_reference(lua_State*) { // do nothing return 0; } template int multi_push_reference(lua_State* L, T&& t, Args&&... args) { int pushcount = stack::push_reference(L, std::forward(t)); void(detail::swallow { (pushcount += stack::push_reference(L, std::forward(args)), 0)... }); return pushcount; } template bool unqualified_check(lua_State* L, int index, Handler&& handler, record& tracking) { using Tu = meta::unqualified_t; if constexpr (meta::meta_detail::is_adl_sol_lua_check_v) { return sol_lua_check(types(), L, index, std::forward(handler), tracking); } else { unqualified_checker> c{}; return c.check(L, index, std::forward(handler), tracking); } } template bool unqualified_check(lua_State* L, int index, Handler&& handler) { record tracking {}; return unqualified_check(L, index, std::forward(handler), tracking); } template bool unqualified_check(lua_State* L, int index = -lua_size>::value) { auto handler = &no_panic; return unqualified_check(L, index, handler); } template bool check(lua_State* L, int index, Handler&& handler, record& tracking) { if constexpr (meta::meta_detail::is_adl_sol_lua_check_v) { return sol_lua_check(types(), L, index, std::forward(handler), tracking); } else { using Tu = meta::unqualified_t; qualified_checker> c{}; return c.check(L, index, std::forward(handler), tracking); } } template bool check(lua_State* L, int index, Handler&& handler) { record tracking {}; return check(L, index, std::forward(handler), tracking); } template bool check(lua_State* L, int index = -lua_size>::value) { auto handler = &no_panic; return check(L, index, handler); } template bool check_usertype(lua_State* L, int index, type, Handler&& handler, record& tracking) { using Tu = meta::unqualified_t; using detail_t = meta::conditional_t, detail::as_pointer_tag, detail::as_value_tag>; return check(L, index, std::forward(handler), tracking); } template bool check_usertype(lua_State* L, int index, Handler&& handler, record& tracking) { using Tu = meta::unqualified_t; using detail_t = meta::conditional_t, detail::as_pointer_tag, detail::as_value_tag>; return check(L, index, std::forward(handler), tracking); } template bool check_usertype(lua_State* L, int index, Handler&& handler) { record tracking {}; return check_usertype(L, index, std::forward(handler), tracking); } template bool check_usertype(lua_State* L, int index = -lua_size>::value) { auto handler = &no_panic; return check_usertype(L, index, handler); } template decltype(auto) unqualified_check_get(lua_State* L, int index, Handler&& handler, record& tracking) { using Tu = meta::unqualified_t; if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v) { return sol_lua_check_get(types(), L, index, std::forward(handler), tracking); } else if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v) { return sol_lua_check_get(types(), L, index, std::forward(handler), tracking); } else { unqualified_check_getter cg {}; return cg.get(L, index, std::forward(handler), tracking); } } template decltype(auto) unqualified_check_get(lua_State* L, int index, Handler&& handler) { record tracking {}; return unqualified_check_get(L, index, handler, tracking); } template decltype(auto) unqualified_check_get(lua_State* L, int index = -lua_size>::value) { auto handler = &no_panic; return unqualified_check_get(L, index, handler); } template decltype(auto) check_get(lua_State* L, int index, Handler&& handler, record& tracking) { if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v) { return sol_lua_check_get(types(), L, index, std::forward(handler), tracking); } else { qualified_check_getter cg {}; return cg.get(L, index, std::forward(handler), tracking); } } template decltype(auto) check_get(lua_State* L, int index, Handler&& handler) { record tracking {}; return check_get(L, index, handler, tracking); } template decltype(auto) check_get(lua_State* L, int index = -lua_size>::value) { auto handler = &no_panic; return check_get(L, index, handler); } namespace stack_detail { template bool check_types(lua_State*, int, Handler&&, record&) { return true; } template bool check_types(lua_State* L, int firstargument, Handler&& handler, record& tracking) { if (!stack::check(L, firstargument + tracking.used, handler, tracking)) return false; return check_types(L, firstargument, std::forward(handler), tracking); } template bool check_types(types, lua_State* L, int index, Handler&& handler, record& tracking) { return check_types(L, index, std::forward(handler), tracking); } } // namespace stack_detail template bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { return stack_detail::check_types(L, index, std::forward(handler), tracking); } template bool multi_check(lua_State* L, int index, Handler&& handler) { record tracking {}; return multi_check(L, index, std::forward(handler), tracking); } template bool multi_check(lua_State* L, int index) { return multi_check(L, index); } template auto unqualified_get(lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_unqualified_get(L, index, tracking)) { #if SOL_IS_ON(SOL_SAFE_GETTER) static constexpr bool is_op = meta::is_optional_v; if constexpr (is_op) { return stack_detail::unchecked_unqualified_get(L, index, tracking); } else { if (is_lua_reference::value) { return stack_detail::unchecked_unqualified_get(L, index, tracking); } auto op = unqualified_check_get(L, index, type_panic_c_str, tracking); return *std::move(op); } #else return stack_detail::unchecked_unqualified_get(L, index, tracking); #endif } template decltype(auto) unqualified_get(lua_State* L, int index = -lua_size>::value) { record tracking {}; return unqualified_get(L, index, tracking); } template auto get(lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get(L, index, tracking)) { #if SOL_IS_ON(SOL_SAFE_GETTER) static constexpr bool is_op = meta::is_optional_v; if constexpr (is_op) { return stack_detail::unchecked_get(L, index, tracking); } else { if (is_lua_reference::value) { return stack_detail::unchecked_get(L, index, tracking); } auto op = check_get(L, index, type_panic_c_str, tracking); return *std::move(op); } #else return stack_detail::unchecked_get(L, index, tracking); #endif } template decltype(auto) get(lua_State* L, int index = -lua_size>::value) { record tracking {}; return get(L, index, tracking); } template decltype(auto) get_usertype(lua_State* L, int index, record& tracking) { using UT = meta::conditional_t::value, detail::as_pointer_tag>, detail::as_value_tag>; return get(L, index, tracking); } template decltype(auto) get_usertype(lua_State* L, int index = -lua_size_v>) { record tracking {}; return get_usertype(L, index, tracking); } template decltype(auto) pop(lua_State* L) { return popper {}.pop(L); } template void get_field(lua_State* L, Key&& key) { field_getter, global, raw> {}.get(L, std::forward(key)); } template void get_field(lua_State* L, Key&& key, int tableindex) { field_getter, global, raw> {}.get(L, std::forward(key), tableindex); } template void raw_get_field(lua_State* L, Key&& key) { get_field(L, std::forward(key)); } template void raw_get_field(lua_State* L, Key&& key, int tableindex) { get_field(L, std::forward(key), tableindex); } template probe probe_get_field(lua_State* L, Key&& key) { return probe_field_getter, C, global, raw> {}.get(L, std::forward(key)); } template probe probe_get_field(lua_State* L, Key&& key, int tableindex) { return probe_field_getter, C, global, raw> {}.get(L, std::forward(key), tableindex); } template probe probe_raw_get_field(lua_State* L, Key&& key) { return probe_get_field(L, std::forward(key)); } template probe probe_raw_get_field(lua_State* L, Key&& key, int tableindex) { return probe_get_field(L, std::forward(key), tableindex); } template void set_field(lua_State* L, Key&& key, Value&& value) { field_setter, global, raw> {}.set(L, std::forward(key), std::forward(value)); } template void set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { field_setter, global, raw> {}.set(L, std::forward(key), std::forward(value), tableindex); } template void raw_set_field(lua_State* L, Key&& key, Value&& value) { set_field(L, std::forward(key), std::forward(value)); } template void raw_set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { set_field(L, std::forward(key), std::forward(value), tableindex); } template void modify_unique_usertype_as(const stack_reference& obj, F&& f) { void* raw = lua_touserdata(obj.lua_state(), obj.stack_index()); void* ptr_memory = detail::align_usertype_pointer(raw); void* uu_memory = detail::align_usertype_unique(raw); T& uu = *static_cast(uu_memory); f(uu); *static_cast(ptr_memory) = static_cast(detail::unique_get(obj.lua_state(), uu)); } template void modify_unique_usertype(const stack_reference& obj, F&& f) { using bt = meta::bind_traits>; using T = typename bt::template arg_at<0>; using Tu = meta::unqualified_t; modify_unique_usertype_as(obj, std::forward(f)); } namespace stack_detail { template decltype(auto) check_get_arg(lua_State* L_, int index_, Handler&& handler_, record& tracking_) { if constexpr (meta::meta_detail::is_adl_sol_lua_check_access_v) { sol_lua_check_access(types>(), L_, index_, tracking_); } return check_get(L_, index_, std::forward(handler_), tracking_); } template decltype(auto) unchecked_get_arg(lua_State* L_, int index_, record& tracking_) { if constexpr (meta::meta_detail::is_adl_sol_lua_check_access_v) { sol_lua_check_access(types>(), L_, index_, tracking_); } return unchecked_get(L_, index_, tracking_); } } // namespace stack_detail } // namespace stack namespace detail { template lua_CFunction make_destructor(std::true_type) { if constexpr (is_unique_usertype_v) { return &unique_destroy; } else if constexpr (!std::is_pointer_v) { return &usertype_alloc_destroy; } else { return &cannot_destroy; } } template lua_CFunction make_destructor(std::false_type) { return &cannot_destroy; } template lua_CFunction make_destructor() { return make_destructor(std::is_destructible()); } struct no_comp { template bool operator()(A&&, B&&) const { return false; } }; template int is_check(lua_State* L) { return stack::push(L, stack::check(L, 1, &no_panic)); } template int member_default_to_string(std::true_type, lua_State* L) { decltype(auto) ts = stack::get(L, 1).to_string(); return stack::push(L, std::forward(ts)); } template int member_default_to_string(std::false_type, lua_State* L) { return luaL_error(L, "cannot perform to_string on '%s': no 'to_string' overload in namespace, 'to_string' member " "function, or operator<<(ostream&, ...) present", detail::demangle().data()); } template int adl_default_to_string(std::true_type, lua_State* L) { using namespace std; decltype(auto) ts = to_string(stack::get(L, 1)); return stack::push(L, std::forward(ts)); } template int adl_default_to_string(std::false_type, lua_State* L) { return member_default_to_string(meta::supports_to_string_member(), L); } template int oss_default_to_string(std::true_type, lua_State* L) { std::ostringstream oss; oss << stack::unqualified_get(L, 1); return stack::push(L, oss.str()); } template int oss_default_to_string(std::false_type, lua_State* L) { return adl_default_to_string(meta::supports_adl_to_string(), L); } template int default_to_string(lua_State* L) { return oss_default_to_string(meta::supports_op_left_shift(), L); } template int default_size(lua_State* L) { decltype(auto) self = stack::unqualified_get(L, 1); return stack::push(L, self.size()); } template int comparsion_operator_wrap(lua_State* L) { if constexpr (std::is_void_v) { return stack::push(L, false); } else { auto maybel = stack::unqualified_check_get(L, 1); if (!maybel) { return stack::push(L, false); } auto mayber = stack::unqualified_check_get(L, 2); if (!mayber) { return stack::push(L, false); } decltype(auto) l = *maybel; decltype(auto) r = *mayber; if constexpr (std::is_same_v) { std::equal_to<> op; return stack::push(L, op(detail::ptr(l), detail::ptr(r))); } else { if constexpr (std::is_same_v, Op> // clang-format hack || std::is_same_v, Op> // || std::is_same_v, Op>) { // if (detail::ptr(l) == detail::ptr(r)) { return stack::push(L, true); } } Op op; return stack::push(L, op(detail::deref(l), detail::deref(r))); } } } template void insert_default_registrations(IFx&& ifx, Fx&& fx); template struct get_is_primitive : is_lua_primitive { }; template struct get_is_primitive : meta::neg(), nullptr, -1, std::declval()))>> { }; template struct get_is_primitive : meta::neg>(), nullptr, -1, std::declval()))>> { }; template struct get_is_primitive : get_is_primitive { }; } // namespace detail template struct is_proxy_primitive : detail::get_is_primitive, meta::meta_detail::is_adl_sol_lua_get_v>> { }; } // namespace sol #endif // SOL_STACK_CORE_HPP // sol2 // The MIT License (MIT) // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of // the Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef SOL_TIE_HPP #define SOL_TIE_HPP #include namespace sol { namespace detail { template struct is_speshul : std::false_type { }; } // namespace detail template struct tie_size : std::tuple_size { }; template struct is_tieable : std::integral_constant::value > 0)> { }; template struct tie_t : public std::tuple...> { private: typedef std::tuple...> base_t; template void set(std::false_type, T&& target) { std::get<0>(*this) = std::forward(target); } template void set(std::true_type, T&& target) { typedef tie_size> value_size; typedef tie_size> tie_size; typedef meta::conditional_t<(value_size::value < tie_size::value), value_size, tie_size> indices_size; typedef std::make_index_sequence indices; set_extra(detail::is_speshul>(), indices(), std::forward(target)); } template void set_extra(std::true_type, std::index_sequence, T&& target) { using std::get; (void)detail::swallow { 0, (get(static_cast(*this)) = get(types(), target), 0)..., 0 }; } template void set_extra(std::false_type, std::index_sequence, T&& target) { using std::get; (void)detail::swallow { 0, (get(static_cast(*this)) = get(target), 0)..., 0 }; } public: using base_t::base_t; template tie_t& operator=(T&& value) { typedef is_tieable> tieable; set(tieable(), std::forward(value)); return *this; } }; template struct tie_size> : std::tuple_size> { }; namespace adl_barrier_detail { template inline tie_t...> tie(Tn&&... argn) { return tie_t...>(std::forward(argn)...); } } // namespace adl_barrier_detail using namespace adl_barrier_detail; } // namespace sol #endif // SOL_TIE_HPP // sol2 // The MIT License (MIT) // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of // the Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef SOL_USERTYPE_CONTAINER_HPP #define SOL_USERTYPE_CONTAINER_HPP #include #include #include namespace sol { template struct usertype_container; namespace container_detail { template struct has_clear_test { private: template static meta::sfinae_yes_t test(decltype(&C::clear)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_empty_test { private: template static meta::sfinae_yes_t test(decltype(&C::empty)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_erase_after_test { private: template static meta::sfinae_yes_t test( decltype(std::declval().erase_after(std::declval>()))*); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_find_test { private: template static meta::sfinae_yes_t test(decltype(std::declval().find(std::declval>()))*); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_find_test::value>> { private: template static meta::sfinae_yes_t test(decltype(std::declval().find(std::declval>()))*); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_erase_test { private: template static meta::sfinae_yes_t test(decltype(std::declval().erase(std::declval()))*); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_erase_key_test { private: template static meta::sfinae_yes_t test(decltype(std::declval().erase(std::declval()))*); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_traits_find_test { private: template static meta::sfinae_yes_t test(decltype(&C::find)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_traits_index_of_test { private: template static meta::sfinae_yes_t test(decltype(&C::index_of)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_traits_insert_test { private: template static meta::sfinae_yes_t test(decltype(&C::insert)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_traits_erase_test { private: template static meta::sfinae_yes_t test(decltype(&C::erase)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_traits_index_set_test { private: template static meta::sfinae_yes_t test(decltype(&C::index_set)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_traits_index_get_test { private: template static meta::sfinae_yes_t test(decltype(&C::index_get)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_traits_set_test { private: template static meta::sfinae_yes_t test(decltype(&C::set)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_traits_get_test { private: template static meta::sfinae_yes_t test(decltype(&C::get)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_traits_at_test { private: template static meta::sfinae_yes_t test(decltype(&C::at)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_traits_pairs_test { private: template static meta::sfinae_yes_t test(decltype(&C::pairs)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_traits_ipairs_test { private: template static meta::sfinae_yes_t test(decltype(&C::ipairs)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_traits_next_test { private: template static meta::sfinae_yes_t test(decltype(&C::next)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_traits_add_test { private: template static meta::sfinae_yes_t test(decltype(&C::add)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template struct has_traits_size_test { private: template static meta::sfinae_yes_t test(decltype(&C::size)); template static meta::sfinae_no_t test(...); public: static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; template using has_clear = meta::boolean::value>; template using has_empty = meta::boolean::value>; template using has_find = meta::boolean::value>; template using has_erase = meta::boolean::value>; template using has_erase_key = meta::boolean::value>; template using has_erase_after = meta::boolean::value>; template using has_traits_get = meta::boolean::value>; template using has_traits_at = meta::boolean::value>; template using has_traits_set = meta::boolean::value>; template using has_traits_index_get = meta::boolean::value>; template using has_traits_index_set = meta::boolean::value>; template using has_traits_pairs = meta::boolean::value>; template using has_traits_ipairs = meta::boolean::value>; template using has_traits_next = meta::boolean::value>; template using has_traits_add = meta::boolean::value>; template using has_traits_size = meta::boolean::value>; template using has_traits_clear = has_clear; template using has_traits_empty = has_empty; template using has_traits_find = meta::boolean::value>; template using has_traits_index_of = meta::boolean::value>; template using has_traits_insert = meta::boolean::value>; template using has_traits_erase = meta::boolean::value>; template struct is_forced_container : is_container { }; template struct is_forced_container> : std::true_type { }; template struct container_decay { typedef T type; }; template struct container_decay> { typedef T type; }; template using container_decay_t = typename container_decay>::type; template decltype(auto) get_key(std::false_type, T&& t) { return std::forward(t); } template decltype(auto) get_key(std::true_type, T&& t) { return t.first; } template decltype(auto) get_value(std::false_type, T&& t) { return std::forward(t); } template decltype(auto) get_value(std::true_type, T&& t) { return t.second; } template struct usertype_container_default { private: typedef std::remove_pointer_t> T; public: typedef lua_nil_t iterator; typedef iterator sentinel; typedef lua_nil_t value_type; static int at(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'at(index)' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int get(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'get(key)' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int index_get(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'container[key]' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int set(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'set(key, value)' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int index_set(lua_State* L_) { return luaL_error( L_, "sol: cannot call 'container[key] = value' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int add(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'add' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int insert(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'insert' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int find(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'find' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int index_of(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'index_of' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int size(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'end' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int clear(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'clear' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int empty(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'empty' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int erase(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'erase' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int next(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'next' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int pairs(lua_State* L_) { return luaL_error(L_, "sol: cannot call '__pairs/pairs' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int ipairs(lua_State* L_) { return luaL_error(L_, "sol: cannot call '__ipairs' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static iterator begin(lua_State* L_, T&) { luaL_error(L_, "sol: cannot call 'being' on type '%s': it is not recognized as a container", detail::demangle().c_str()); return lua_nil; } static sentinel end(lua_State* L_, T&) { luaL_error(L_, "sol: cannot call 'end' on type '%s': it is not recognized as a container", detail::demangle().c_str()); return lua_nil; } }; template struct usertype_container_default>, meta::has_value_type>>, meta::has_iterator>>>::value>> { private: using T = std::remove_pointer_t>>; private: using deferred_uc = usertype_container; using is_associative = meta::is_associative; using is_lookup = meta::is_lookup; using is_ordered = meta::is_ordered; using is_matched_lookup = meta::is_matched_lookup; using iterator = typename T::iterator; using sentinel = meta::sentinel_or_t; using value_type = typename T::value_type; typedef meta::conditional_t, meta::conditional_t>> KV; typedef typename KV::first_type K; typedef typename KV::second_type V; typedef meta::conditional_t next_K; typedef decltype(*std::declval()) iterator_return; typedef meta::conditional_t, meta::conditional_t> captured_type; typedef typename meta::iterator_tag::type iterator_category; typedef std::is_same is_input_iterator; typedef meta::conditional_t()))> push_type; typedef std::is_copy_assignable is_copyable; typedef meta::neg, std::is_const>, meta::neg>> is_writable; typedef meta::unqualified_t>()))> key_type; typedef meta::all, meta::neg>> is_linear_integral; struct iter : detail::ebco, detail::ebco { using it_base = detail::ebco; using sen_base = detail::ebco; main_reference keep_alive; std::size_t index; iter(lua_State* L_, int stack_index_, iterator it_, sentinel sen_) noexcept : it_base(std::move(it_)), sen_base(std::move(sen_)), keep_alive(L_, stack_index_), index(0) { } iterator& it() noexcept { return it_base::value(); } const iterator& it() const noexcept { return it_base::value(); } sentinel& sen() noexcept { return sen_base::value(); } const sentinel& sen() const noexcept { return sen_base::value(); } }; static auto& get_src(lua_State* L_) { #if SOL_IS_ON(SOL_SAFE_USERTYPE) auto p = stack::unqualified_check_get(L_, 1); if (!p) { luaL_error(L_, "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", detail::demangle().c_str()); } if (p.value() == nullptr) { luaL_error( L_, "sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a '%s' type)", detail::demangle().c_str()); } return *p.value(); #else return stack::unqualified_get(L_, 1); #endif // Safe getting with error } static detail::error_result at_category(std::input_iterator_tag, lua_State* L_, T& self, std::ptrdiff_t pos) { pos += deferred_uc::index_adjustment(L_, self); if (pos < 0) { return stack::push(L_, lua_nil); } auto it = deferred_uc::begin(L_, self); auto e = deferred_uc::end(L_, self); if (it == e) { return stack::push(L_, lua_nil); } while (pos > 0) { --pos; ++it; if (it == e) { return stack::push(L_, lua_nil); } } return get_associative(is_associative(), L_, it); } static detail::error_result at_category(std::random_access_iterator_tag, lua_State* L_, T& self, std::ptrdiff_t pos) { std::ptrdiff_t len = static_cast(size_start(L_, self)); pos += deferred_uc::index_adjustment(L_, self); if (pos < 0 || pos >= len) { return stack::push(L_, lua_nil); } auto it = std::next(deferred_uc::begin(L_, self), pos); return get_associative(is_associative(), L_, it); } static detail::error_result at_start(lua_State* L_, T& self, std::ptrdiff_t pos) { return at_category(iterator_category(), L_, self, pos); } template static detail::error_result get_associative(std::true_type, lua_State* L_, Iter& it) { decltype(auto) v = *it; return stack::stack_detail::push_reference(L_, detail::deref_move_only(v.second)); } template static detail::error_result get_associative(std::false_type, lua_State* L_, Iter& it) { return stack::stack_detail::push_reference(L_, detail::deref_move_only(*it)); } static detail::error_result get_category(std::input_iterator_tag, lua_State* L_, T& self, K& key) { key = static_cast(key + deferred_uc::index_adjustment(L_, self)); if (key < 0) { return stack::push(L_, lua_nil); } auto it = deferred_uc::begin(L_, self); auto e = deferred_uc::end(L_, self); if (it == e) { return stack::push(L_, lua_nil); } while (key > 0) { --key; ++it; if (it == e) { return stack::push(L_, lua_nil); } } return get_associative(is_associative(), L_, it); } static detail::error_result get_category(std::random_access_iterator_tag, lua_State* L_, T& self, K& key) { std::ptrdiff_t len = static_cast(size_start(L_, self)); key = static_cast(static_cast(key) + deferred_uc::index_adjustment(L_, self)); if (key < 0 || key >= len) { return stack::push(L_, lua_nil); } auto it = std::next(deferred_uc::begin(L_, self), key); return get_associative(is_associative(), L_, it); } static detail::error_result get_it(std::true_type, lua_State* L_, T& self, K& key) { return get_category(iterator_category(), L_, self, key); } static detail::error_result get_comparative(std::true_type, lua_State* L_, T& self, K& key) { auto fx = [&](const value_type& r) -> bool { return key == get_key(is_associative(), r); }; auto e = deferred_uc::end(L_, self); auto it = std::find_if(deferred_uc::begin(L_, self), e, std::ref(fx)); if (it == e) { return stack::push(L_, lua_nil); } return get_associative(is_associative(), L_, it); } static detail::error_result get_comparative(std::false_type, lua_State*, T&, K&) { return detail::error_result("cannot get this key on '%s': no suitable way to increment iterator and compare to key value '%s'", detail::demangle().data(), detail::demangle().data()); } static detail::error_result get_it(std::false_type, lua_State* L_, T& self, K& key) { return get_comparative(meta::supports_op_equal(), L_, self, key); } static detail::error_result set_associative(std::true_type, iterator& it, stack_object value) { decltype(auto) v = *it; v.second = value.as(); return {}; } static detail::error_result set_associative(std::false_type, iterator& it, stack_object value) { decltype(auto) v = *it; v = value.as(); return {}; } static detail::error_result set_writable(std::true_type, lua_State*, T&, iterator& it, stack_object value) { return set_associative(is_associative(), it, std::move(value)); } static detail::error_result set_writable(std::false_type, lua_State*, T&, iterator&, stack_object) { return detail::error_result( "cannot perform a 'set': '%s's iterator reference is not writable (non-copy-assignable or const)", detail::demangle().data()); } static detail::error_result set_category(std::input_iterator_tag, lua_State* L_, T& self, stack_object okey, stack_object value) { decltype(auto) key = okey.as(); key = static_cast(static_cast(key) + deferred_uc::index_adjustment(L_, self)); auto e = deferred_uc::end(L_, self); auto it = deferred_uc::begin(L_, self); auto backit = it; for (; key > 0 && it != e; --key, ++it) { backit = it; } if (it == e) { if (key == 0) { return add_copyable(is_copyable(), L_, self, std::move(value), meta::has_insert_after::value ? backit : it); } return detail::error_result("out of bounds (too big) for set on '%s'", detail::demangle().c_str()); } return set_writable(is_writable(), L_, self, it, std::move(value)); } static detail::error_result set_category(std::random_access_iterator_tag, lua_State* L_, T& self, stack_object okey, stack_object value) { decltype(auto) key = okey.as(); key = static_cast(static_cast(key) + deferred_uc::index_adjustment(L_, self)); if (key < 0) { return detail::error_result("sol: out of bounds (too small) for set on '%s'", detail::demangle().c_str()); } std::ptrdiff_t len = static_cast(size_start(L_, self)); if (key == len) { return add_copyable(is_copyable(), L_, self, std::move(value)); } else if (key >= len) { return detail::error_result("sol: out of bounds (too big) for set on '%s'", detail::demangle().c_str()); } auto it = std::next(deferred_uc::begin(L_, self), key); return set_writable(is_writable(), L_, self, it, std::move(value)); } static detail::error_result set_comparative(std::true_type, lua_State* L_, T& self, stack_object okey, stack_object value) { decltype(auto) key = okey.as(); if (!is_writable::value) { return detail::error_result( "cannot perform a 'set': '%s's iterator reference is not writable (non-copy-assignable or const)", detail::demangle().data()); } auto fx = [&](const value_type& r) -> bool { return key == get_key(is_associative(), r); }; auto e = deferred_uc::end(L_, self); auto it = std::find_if(deferred_uc::begin(L_, self), e, std::ref(fx)); if (it == e) { return {}; } return set_writable(is_writable(), L_, self, it, std::move(value)); } static detail::error_result set_comparative(std::false_type, lua_State*, T&, stack_object, stack_object) { return detail::error_result("cannot set this value on '%s': no suitable way to increment iterator or compare to '%s' key", detail::demangle().data(), detail::demangle().data()); } template static detail::error_result set_associative_insert(std::true_type, lua_State*, T& self, Iter& it, K& key, stack_object value) { if constexpr (meta::has_insert_with_iterator::value) { self.insert(it, value_type(key, value.as())); return {}; } else if constexpr (meta::has_insert::value) { self.insert(value_type(key, value.as())); return {}; } else { (void)self; (void)it; (void)key; return detail::error_result( "cannot call 'set' on '%s': there is no 'insert' function on this associative type", detail::demangle().c_str()); } } template static detail::error_result set_associative_insert(std::false_type, lua_State*, T& self, Iter& it, K& key, stack_object) { if constexpr (meta::has_insert_with_iterator::value) { self.insert(it, key); return {}; } else if constexpr (meta::has_insert::value) { self.insert(key); return {}; } else { (void)self; (void)it; (void)key; return detail::error_result( "cannot call 'set' on '%s': there is no 'insert' function on this non-associative type", detail::demangle().c_str()); } } static detail::error_result set_associative_find(std::true_type, lua_State* L_, T& self, stack_object okey, stack_object value) { decltype(auto) key = okey.as(); auto it = self.find(key); if (it == deferred_uc::end(L_, self)) { return set_associative_insert(is_associative(), L_, self, it, key, std::move(value)); } return set_writable(is_writable(), L_, self, it, std::move(value)); } static detail::error_result set_associative_find(std::false_type, lua_State* L_, T& self, stack_object key, stack_object value) { return set_comparative(meta::supports_op_equal(), L_, self, std::move(key), std::move(value)); } static detail::error_result set_it(std::true_type, lua_State* L_, T& self, stack_object key, stack_object value) { return set_category(iterator_category(), L_, self, std::move(key), std::move(value)); } static detail::error_result set_it(std::false_type, lua_State* L_, T& self, stack_object key, stack_object value) { return set_associative_find(meta::all, meta::any>(), L_, self, std::move(key), std::move(value)); } template static detail::error_result find_has_associative_lookup(std::true_type, lua_State* L_, T& self) { if constexpr (!is_ordered::value && idx_of) { (void)L_; (void)self; return detail::error_result("cannot perform an 'index_of': '%s's is not an ordered container", detail::demangle().data()); } else { decltype(auto) key = stack::unqualified_get(L_, 2); auto it = self.find(key); if (it == deferred_uc::end(L_, self)) { return stack::push(L_, lua_nil); } if constexpr (idx_of) { auto dist = std::distance(deferred_uc::begin(L_, self), it); dist -= deferred_uc::index_adjustment(L_, self); return stack::push(L_, dist); } else { return get_associative(is_associative(), L_, it); } } } template static detail::error_result find_has_associative_lookup(std::false_type, lua_State* L_, T& self) { if constexpr (!is_ordered::value && idx_of) { (void)L_; (void)self; return detail::error_result("cannot perform an 'index_of': '%s's is not an ordered container", detail::demangle().data()); } else { decltype(auto) value = stack::unqualified_get(L_, 2); auto it = self.find(value); if (it == deferred_uc::end(L_, self)) { return stack::push(L_, lua_nil); } if constexpr (idx_of) { auto dist = std::distance(deferred_uc::begin(L_, self), it); dist -= deferred_uc::index_adjustment(L_, self); return stack::push(L_, dist); } else { return get_associative(is_associative(), L_, it); } } } template static detail::error_result find_has(std::true_type, lua_State* L_, T& self) { return find_has_associative_lookup(meta::any(), L_, self); } template static detail::error_result find_associative_lookup(std::true_type, lua_State* L_, T&, Iter& it, std::size_t) { return get_associative(is_associative(), L_, it); } template static detail::error_result find_associative_lookup(std::false_type, lua_State* L_, T& self, Iter&, std::size_t idx) { idx = static_cast(static_cast(idx) - deferred_uc::index_adjustment(L_, self)); return stack::push(L_, idx); } template static detail::error_result find_comparative(std::false_type, lua_State*, T&) { return detail::error_result("cannot call 'find' on '%s': there is no 'find' function and the value_type is not equality comparable", detail::demangle().c_str()); } template static detail::error_result find_comparative(std::true_type, lua_State* L_, T& self) { decltype(auto) value = stack::unqualified_get(L_, 2); auto it = deferred_uc::begin(L_, self); auto e = deferred_uc::end(L_, self); std::size_t idx = 0; for (;; ++it, ++idx) { if (it == e) { return stack::push(L_, lua_nil); } if (value == get_value(is_associative(), *it)) { break; } } return find_associative_lookup(meta::all, meta::any>(), L_, self, it, idx); } template static detail::error_result find_has(std::false_type, lua_State* L_, T& self) { return find_comparative(meta::supports_op_equal(), L_, self); } template static detail::error_result add_insert_after(std::false_type, lua_State* L_, T& self, stack_object value, Iter&) { return add_insert_after(std::false_type(), L_, self, value); } static detail::error_result add_insert_after(std::false_type, lua_State*, T&, stack_object) { return detail::error_result("cannot call 'add' on type '%s': no suitable insert/push_back C++ functions", detail::demangle().data()); } template static detail::error_result add_insert_after(std::true_type, lua_State*, T& self, stack_object value, Iter& pos) { self.insert_after(pos, value.as()); return {}; } static detail::error_result add_insert_after(std::true_type, lua_State* L_, T& self, stack_object value) { auto backit = self.before_begin(); { auto e = deferred_uc::end(L_, self); for (auto it = deferred_uc::begin(L_, self); it != e; ++backit, ++it) { } } return add_insert_after(std::true_type(), L_, self, value, backit); } template static detail::error_result add_insert(std::true_type, lua_State*, T& self, stack_object value, Iter& pos) { self.insert(pos, value.as()); return {}; } static detail::error_result add_insert(std::true_type, lua_State* L_, T& self, stack_object value) { auto pos = deferred_uc::end(L_, self); return add_insert(std::true_type(), L_, self, value, pos); } template static detail::error_result add_insert(std::false_type, lua_State* L_, T& self, stack_object value, Iter& pos) { return add_insert_after(meta::has_insert_after(), L_, self, std::move(value), pos); } static detail::error_result add_insert(std::false_type, lua_State* L_, T& self, stack_object value) { return add_insert_after(meta::has_insert_after(), L_, self, std::move(value)); } template static detail::error_result add_push_back(std::true_type, lua_State*, T& self, stack_object value, Iter&) { self.push_back(value.as()); return {}; } static detail::error_result add_push_back(std::true_type, lua_State*, T& self, stack_object value) { self.push_back(value.as()); return {}; } template static detail::error_result add_push_back(std::false_type, lua_State* L_, T& self, stack_object value, Iter& pos) { return add_insert( std::integral_constant < bool, meta::has_insert::value || meta::has_insert_with_iterator::value > (), L_, self, value, pos); } static detail::error_result add_push_back(std::false_type, lua_State* L_, T& self, stack_object value) { return add_insert( std::integral_constant < bool, meta::has_insert::value || meta::has_insert_with_iterator::value > (), L_, self, value); } template static detail::error_result add_associative(std::true_type, lua_State* L_, T& self, stack_object key, Iter& pos) { if constexpr (meta::has_insert_with_iterator::value) { self.insert(pos, value_type(key.as(), stack::unqualified_get(L_, 3))); return {}; } else if constexpr (meta::has_insert::value) { self.insert(value_type(key.as(), stack::unqualified_get(L_, 3))); return {}; } else { (void)L_; (void)self; (void)key; (void)pos; return detail::error_result( "cannot call 'insert' on '%s': there is no 'insert' function on this associative type", detail::demangle().c_str()); } } static detail::error_result add_associative(std::true_type, lua_State* L_, T& self, stack_object key) { auto pos = deferred_uc::end(L_, self); return add_associative(std::true_type(), L_, self, std::move(key), pos); } template static detail::error_result add_associative(std::false_type, lua_State* L_, T& self, stack_object value, Iter& pos) { return add_push_back(meta::has_push_back(), L_, self, value, pos); } static detail::error_result add_associative(std::false_type, lua_State* L_, T& self, stack_object value) { return add_push_back(meta::has_push_back(), L_, self, value); } template static detail::error_result add_copyable(std::true_type, lua_State* L_, T& self, stack_object value, Iter& pos) { return add_associative(is_associative(), L_, self, std::move(value), pos); } static detail::error_result add_copyable(std::true_type, lua_State* L_, T& self, stack_object value) { return add_associative(is_associative(), L_, self, value); } template static detail::error_result add_copyable(std::false_type, lua_State* L_, T& self, stack_object value, Iter&) { return add_copyable(std::false_type(), L_, self, std::move(value)); } static detail::error_result add_copyable(std::false_type, lua_State*, T&, stack_object) { return detail::error_result("cannot call 'add' on '%s': value_type is non-copyable", detail::demangle().data()); } static detail::error_result insert_lookup(std::true_type, lua_State* L_, T& self, stack_object, stack_object value) { // TODO: should we warn or error about someone calling insert on an ordered / lookup container with no associativity? return add_copyable(std::true_type(), L_, self, std::move(value)); } static detail::error_result insert_lookup(std::false_type, lua_State* L_, T& self, stack_object where, stack_object value) { auto it = deferred_uc::begin(L_, self); auto key = where.as(); key = static_cast(static_cast(key) + deferred_uc::index_adjustment(L_, self)); std::advance(it, key); self.insert(it, value.as()); return {}; } static detail::error_result insert_after_has(std::true_type, lua_State* L_, T& self, stack_object where, stack_object value) { auto key = where.as(); auto backit = self.before_begin(); { key = static_cast(static_cast(key) + deferred_uc::index_adjustment(L_, self)); auto e = deferred_uc::end(L_, self); for (auto it = deferred_uc::begin(L_, self); key > 0; ++backit, ++it, --key) { if (backit == e) { return detail::error_result("sol: out of bounds (too big) for set on '%s'", detail::demangle().c_str()); } } } self.insert_after(backit, value.as()); return {}; } static detail::error_result insert_after_has(std::false_type, lua_State*, T&, stack_object, stack_object) { return detail::error_result( "cannot call 'insert' on '%s': no suitable or similar functionality detected on this container", detail::demangle().data()); } static detail::error_result insert_has(std::true_type, lua_State* L_, T& self, stack_object key, stack_object value) { return insert_lookup(meta::any(), L_, self, std::move(key), std::move(value)); } static detail::error_result insert_has(std::false_type, lua_State* L_, T& self, stack_object where, stack_object value) { return insert_after_has(meta::has_insert_after(), L_, self, where, value); } static detail::error_result insert_copyable(std::true_type, lua_State* L_, T& self, stack_object key, stack_object value) { return insert_has(std::integral_constant < bool, meta::has_insert::value || meta::has_insert_with_iterator::value > (), L_, self, std::move(key), std::move(value)); } static detail::error_result insert_copyable(std::false_type, lua_State*, T&, stack_object, stack_object) { return detail::error_result("cannot call 'insert' on '%s': value_type is non-copyable", detail::demangle().data()); } static detail::error_result erase_integral(std::true_type, lua_State* L_, T& self, K& key) { auto it = deferred_uc::begin(L_, self); key = (static_cast(key) + deferred_uc::index_adjustment(L_, self)); std::advance(it, key); self.erase(it); return {}; } static detail::error_result erase_integral(std::false_type, lua_State* L_, T& self, const K& key) { auto fx = [&](const value_type& r) -> bool { return key == r; }; auto e = deferred_uc::end(L_, self); auto it = std::find_if(deferred_uc::begin(L_, self), e, std::ref(fx)); if (it == e) { return {}; } self.erase(it); return {}; } static detail::error_result erase_associative_lookup(std::true_type, lua_State*, T& self, const K& key) { self.erase(key); return {}; } static detail::error_result erase_associative_lookup(std::false_type, lua_State* L_, T& self, K& key) { return erase_integral(std::is_integral(), L_, self, key); } static detail::error_result erase_after_has(std::true_type, lua_State* L_, T& self, K& key) { auto backit = self.before_begin(); { key = static_cast(static_cast(key) + deferred_uc::index_adjustment(L_, self)); auto e = deferred_uc::end(L_, self); for (auto it = deferred_uc::begin(L_, self); key > 0; ++backit, ++it, --key) { if (backit == e) { return detail::error_result("sol: out of bounds for erase on '%s'", detail::demangle().c_str()); } } } self.erase_after(backit); return {}; } static detail::error_result erase_after_has(std::false_type, lua_State*, T&, const K&) { return detail::error_result("sol: cannot call erase on '%s'", detail::demangle().c_str()); } static detail::error_result erase_key_has(std::true_type, lua_State* L_, T& self, K& key) { return erase_associative_lookup(meta::any(), L_, self, key); } static detail::error_result erase_key_has(std::false_type, lua_State* L_, T& self, K& key) { return erase_after_has(has_erase_after(), L_, self, key); } static detail::error_result erase_has(std::true_type, lua_State* L_, T& self, K& key) { return erase_associative_lookup(meta::any(), L_, self, key); } static detail::error_result erase_has(std::false_type, lua_State* L_, T& self, K& key) { return erase_key_has(has_erase_key(), L_, self, key); } static auto size_has(std::false_type, lua_State* L_, T& self) { return std::distance(deferred_uc::begin(L_, self), deferred_uc::end(L_, self)); } static auto size_has(std::true_type, lua_State*, T& self) { return self.size(); } static void clear_has(std::true_type, lua_State*, T& self) { self.clear(); } static void clear_has(std::false_type, lua_State* L_, T&) { luaL_error(L_, "sol: cannot call clear on '%s'", detail::demangle().c_str()); } static bool empty_has(std::true_type, lua_State*, T& self) { return self.empty(); } static bool empty_has(std::false_type, lua_State* L_, T& self) { return deferred_uc::begin(L_, self) == deferred_uc::end(L_, self); } static detail::error_result get_associative_find(std::true_type, lua_State* L_, T& self, K& key) { auto it = self.find(key); if (it == deferred_uc::end(L_, self)) { stack::push(L_, lua_nil); return {}; } return get_associative(std::true_type(), L_, it); } static detail::error_result get_associative_find(std::false_type, lua_State* L_, T& self, K& key) { return get_it(is_linear_integral(), L_, self, key); } static detail::error_result get_start(lua_State* L_, T& self, K& key) { return get_associative_find(std::integral_constant < bool, is_associative::value&& has_find::value > (), L_, self, key); } static detail::error_result set_start(lua_State* L_, T& self, stack_object key, stack_object value) { return set_it(is_linear_integral(), L_, self, std::move(key), std::move(value)); } static std::size_t size_start(lua_State* L_, T& self) { return static_cast(size_has(meta::has_size(), L_, self)); } static void clear_start(lua_State* L_, T& self) { clear_has(has_clear(), L_, self); } static bool empty_start(lua_State* L_, T& self) { return empty_has(has_empty(), L_, self); } static detail::error_result erase_start(lua_State* L_, T& self, K& key) { return erase_has(has_erase(), L_, self, key); } template static int next_associative(std::true_type, lua_State* L_) { iter& i = stack::unqualified_get>(L_, 1); auto& it = i.it; auto& end = i.end; if (it == end) { return stack::push(L_, lua_nil); } int p; if constexpr (ip) { ++i.index; p = stack::push_reference(L_, i.index); } else { p = stack::push_reference(L_, it->first); } p += stack::stack_detail::push_reference(L_, detail::deref_move_only(it->second)); std::advance(it, 1); return p; } template static int next_associative(std::false_type, lua_State* L_) { iter& i = stack::unqualified_get>(L_, 1); auto& it = i.it(); auto& end = i.sen(); next_K k = stack::unqualified_get(L_, 2); if (it == end) { return stack::push(L_, lua_nil); } int p; if constexpr (std::is_integral_v) { p = stack::push_reference(L_, k + 1); } else { p = stack::stack_detail::push_reference(L_, k + 1); } p += stack::stack_detail::push_reference(L_, detail::deref_move_only(*it)); std::advance(it, 1); return p; } template static int next_iter(lua_State* L_) { typedef meta::any>> is_assoc; return next_associative(is_assoc(), L_); } template static int pairs_associative(std::true_type, lua_State* L_) { auto& src = get_src(L_); stack::push(L_, next_iter); stack::push>(L_, L_, 1, deferred_uc::begin(L_, src), deferred_uc::begin(L_, src)); stack::push(L_, lua_nil); return 3; } template static int pairs_associative(std::false_type, lua_State* L_) { auto& src = get_src(L_); stack::push(L_, next_iter); stack::push>(L_, L_, 1, deferred_uc::begin(L_, src), deferred_uc::end(L_, src)); stack::push(L_, 0); return 3; } public: static int at(lua_State* L_) { auto& self = get_src(L_); detail::error_result er; { std::ptrdiff_t pos = stack::unqualified_get(L_, 2); er = at_start(L_, self, pos); } return handle_errors(L_, er); } static int get(lua_State* L_) { auto& self = get_src(L_); detail::error_result er; { decltype(auto) key = stack::unqualified_get(L_); er = get_start(L_, self, key); } return handle_errors(L_, er); } static int index_get(lua_State* L_) { return get(L_); } static int set(lua_State* L_) { stack_object value = stack_object(L_, raw_index(3)); if constexpr (is_linear_integral::value) { // for non-associative containers, // erasure only happens if it is the // last index in the container auto key = stack::get(L_, 2); auto self_size = deferred_uc::size(L_); if (key == static_cast(self_size)) { if (type_of(L_, 3) == type::lua_nil) { return erase(L_); } } } else { if (type_of(L_, 3) == type::lua_nil) { return erase(L_); } } auto& self = get_src(L_); detail::error_result er = set_start(L_, self, stack_object(L_, raw_index(2)), std::move(value)); return handle_errors(L_, er); } static int index_set(lua_State* L_) { return set(L_); } static int add(lua_State* L_) { auto& self = get_src(L_); detail::error_result er = add_copyable(is_copyable(), L_, self, stack_object(L_, raw_index(2))); return handle_errors(L_, er); } static int insert(lua_State* L_) { auto& self = get_src(L_); detail::error_result er = insert_copyable(is_copyable(), L_, self, stack_object(L_, raw_index(2)), stack_object(L_, raw_index(3))); return handle_errors(L_, er); } static int find(lua_State* L_) { auto& self = get_src(L_); detail::error_result er = find_has(has_find(), L_, self); return handle_errors(L_, er); } static int index_of(lua_State* L_) { auto& self = get_src(L_); detail::error_result er = find_has(has_find(), L_, self); return handle_errors(L_, er); } static iterator begin(lua_State*, T& self) { if constexpr (meta::has_begin_end_v) { return self.begin(); } else { using std::begin; return begin(self); } } static sentinel end(lua_State*, T& self) { if constexpr (meta::has_begin_end_v) { return self.end(); } else { using std::end; return end(self); } } static int size(lua_State* L_) { auto& self = get_src(L_); std::size_t r = size_start(L_, self); return stack::push(L_, r); } static int clear(lua_State* L_) { auto& self = get_src(L_); clear_start(L_, self); return 0; } static int erase(lua_State* L_) { auto& self = get_src(L_); detail::error_result er; { decltype(auto) key = stack::unqualified_get(L_, 2); er = erase_start(L_, self, key); } return handle_errors(L_, er); } static int empty(lua_State* L_) { auto& self = get_src(L_); return stack::push(L_, empty_start(L_, self)); } static std::ptrdiff_t index_adjustment(lua_State*, T&) { return static_cast((SOL_CONTAINER_START_INDEX_I_) == 0 ? 0 : -(SOL_CONTAINER_START_INDEX_I_)); } static int pairs(lua_State* L_) { typedef meta::any>> is_assoc; return pairs_associative(is_assoc(), L_); } static int ipairs(lua_State* L_) { typedef meta::any>> is_assoc; return pairs_associative(is_assoc(), L_); } static int next(lua_State* L_) { return stack::push(L_, next_iter); } }; template struct usertype_container_default>>::value>> { private: typedef std::remove_pointer_t> T; typedef usertype_container deferred_uc; public: typedef std::remove_extent_t value_type; typedef value_type* iterator; typedef iterator sentinel; private: struct iter : detail::ebco, detail::ebco { using it_base = detail::ebco; using sen_base = detail::ebco; reference keep_alive; iter(lua_State* L_, int stack_index_, iterator it_, sentinel sen_) noexcept : it_base(std::move(it_)), sen_base(std::move(sen_)), keep_alive(sol::main_thread(L_, L_), stack_index_) { } iterator& it() noexcept { return it_base::value(); } const iterator& it() const noexcept { return it_base::value(); } sentinel& sen() noexcept { return sen_base::value(); } const sentinel& sen() const noexcept { return sen_base::value(); } }; static auto& get_src(lua_State* L_) { auto p = stack::unqualified_check_get(L_, 1); #if SOL_IS_ON(SOL_SAFE_USERTYPE) if (!p) { luaL_error(L_, "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", detail::demangle().c_str()); } if (p.value() == nullptr) { luaL_error( L_, "sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a '%s' type)", detail::demangle().c_str()); } #endif // Safe getting with error return *p.value(); } static int find(std::true_type, lua_State* L_) { T& self = get_src(L_); decltype(auto) value = stack::unqualified_get(L_, 2); std::size_t N = std::extent::value; for (std::size_t idx = 0; idx < N; ++idx) { using v_t = std::add_const_t; v_t v = self[idx]; if (v == value) { idx = static_cast(static_cast(idx) - deferred_uc::index_adjustment(L_, self)); return stack::push(L_, idx); } } return stack::push(L_, lua_nil); } static int find(std::false_type, lua_State* L_) { return luaL_error(L_, "sol: cannot call 'find' on '%s': no supported comparison operator for the value type", detail::demangle().c_str()); } static int next_iter(lua_State* L_) { iter& i = stack::unqualified_get>(L_, 1); auto& it = i.it(); auto& end = i.sen(); std::size_t k = stack::unqualified_get(L_, 2); if (it == end) { return 0; } int p; p = stack::push(L_, k + 1); p += stack::push_reference(L_, detail::deref_move_only(*it)); std::advance(it, 1); return p; } public: static int clear(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'clear' on type '%s': cannot remove all items from a fixed array", detail::demangle().c_str()); } static int erase(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'erase' on type '%s': cannot remove an item from fixed arrays", detail::demangle().c_str()); } static int add(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'add' on type '%s': cannot add to fixed arrays", detail::demangle().c_str()); } static int insert(lua_State* L_) { return luaL_error(L_, "sol: cannot call 'insert' on type '%s': cannot insert new entries into fixed arrays", detail::demangle().c_str()); } static int at(lua_State* L_) { return get(L_); } static int get(lua_State* L_) { T& self = get_src(L_); std::ptrdiff_t idx = stack::unqualified_get(L_, 2); idx += deferred_uc::index_adjustment(L_, self); if (idx >= static_cast(std::extent::value) || idx < 0) { return stack::push(L_, lua_nil); } return stack::push_reference(L_, detail::deref_move_only(self[idx])); } static int index_get(lua_State* L_) { return get(L_); } static int set(lua_State* L_) { T& self = get_src(L_); std::ptrdiff_t idx = stack::unqualified_get(L_, 2); idx += deferred_uc::index_adjustment(L_, self); if (idx >= static_cast(std::extent::value)) { return luaL_error(L_, "sol: index out of bounds (too big) for set on '%s'", detail::demangle().c_str()); } if (idx < 0) { return luaL_error(L_, "sol: index out of bounds (too small) for set on '%s'", detail::demangle().c_str()); } self[idx] = stack::unqualified_get(L_, 3); return 0; } static int index_set(lua_State* L_) { return set(L_); } static int index_of(lua_State* L_) { return find(L_); } static int find(lua_State* L_) { return find(meta::supports_op_equal(), L_); } static int size(lua_State* L_) { return stack::push(L_, std::extent::value); } static int empty(lua_State* L_) { return stack::push(L_, std::extent::value > 0); } static int pairs(lua_State* L_) { auto& src = get_src(L_); stack::push(L_, next_iter); stack::push>(L_, L_, 1, deferred_uc::begin(L_, src), deferred_uc::end(L_, src)); stack::push(L_, 0); return 3; } static int ipairs(lua_State* L_) { return pairs(L_); } static int next(lua_State* L_) { return stack::push(L_, next_iter); } static std::ptrdiff_t index_adjustment(lua_State*, T&) { return (SOL_CONTAINER_START_INDEX_I_) == 0 ? 0 : -(SOL_CONTAINER_START_INDEX_I_); } static iterator begin(lua_State*, T& self) { return std::addressof(self[0]); } static sentinel end(lua_State*, T& self) { return std::addressof(self[0]) + std::extent::value; } }; template struct usertype_container_default> : usertype_container_default { }; } // namespace container_detail template struct usertype_container : container_detail::usertype_container_default { }; } // namespace sol #endif // SOL_USERTYPE_CONTAINER_HPP // sol2 // The MIT License (MIT) // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of // the Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef SOL_POINTER_LIKE_HPP #define SOL_POINTER_LIKE_HPP #include #include #include #include namespace sol { namespace meta { namespace meta_detail { template using is_dereferenceable_test = decltype(*std::declval()); template using is_explicitly_dereferenceable_test = decltype(std::declval().operator*()); } // namespace meta_detail template using is_pointer_like = std::integral_constant && (std::is_pointer_v || is_detected_v)>; template constexpr inline bool is_pointer_like_v = is_pointer_like::value; } // namespace meta namespace detail { template auto unwrap(T&& item) -> decltype(std::forward(item)) { return std::forward(item); } template T& unwrap(std::reference_wrapper arg) { return arg.get(); } template inline decltype(auto) deref(T&& item) { using Tu = meta::unqualified_t; if constexpr (meta::is_pointer_like_v) { return *std::forward(item); } else { return std::forward(item); } } template inline decltype(auto) deref_move_only(T&& item) { using Tu = meta::unqualified_t; if constexpr (meta::is_pointer_like_v && !std::is_pointer_v && !std::is_copy_constructible_v) { return *std::forward(item); } else { return std::forward(item); } } template inline T* ptr(T& val) { return std::addressof(val); } template inline T* ptr(std::reference_wrapper val) { return std::addressof(val.get()); } template inline T* ptr(T* val) { return val; } } // namespace detail } // namespace sol #endif // SOL_POINTER_LIKE_HPP // -*- C++ -*- //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_VECTOR #define _LIBCPP_VECTOR /* vector synopsis namespace std { template > class vector { public: typedef T value_type; typedef Allocator allocator_type; typedef typename allocator_type::reference reference; typedef typename allocator_type::const_reference const_reference; typedef implementation-defined iterator; typedef implementation-defined const_iterator; typedef typename allocator_type::size_type size_type; typedef typename allocator_type::difference_type difference_type; typedef typename allocator_type::pointer pointer; typedef typename allocator_type::const_pointer const_pointer; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; vector() noexcept(is_nothrow_default_constructible::value); explicit vector(const allocator_type&); explicit vector(size_type n); explicit vector(size_type n, const allocator_type&); // C++14 vector(size_type n, const value_type& value, const allocator_type& = allocator_type()); template vector(InputIterator first, InputIterator last, const allocator_type& = allocator_type()); vector(const vector& x); vector(vector&& x) noexcept(is_nothrow_move_constructible::value); vector(initializer_list il); vector(initializer_list il, const allocator_type& a); ~vector(); vector& operator=(const vector& x); vector& operator=(vector&& x) noexcept( allocator_type::propagate_on_container_move_assignment::value || allocator_type::is_always_equal::value); // C++17 vector& operator=(initializer_list il); template void assign(InputIterator first, InputIterator last); void assign(size_type n, const value_type& u); void assign(initializer_list il); allocator_type get_allocator() const noexcept; iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; size_type capacity() const noexcept; bool empty() const noexcept; void reserve(size_type n); void shrink_to_fit() noexcept; reference operator[](size_type n); const_reference operator[](size_type n) const; reference at(size_type n); const_reference at(size_type n) const; reference front(); const_reference front() const; reference back(); const_reference back() const; value_type* data() noexcept; const value_type* data() const noexcept; void push_back(const value_type& x); void push_back(value_type&& x); template reference emplace_back(Args&&... args); // reference in C++17 void pop_back(); template iterator emplace(const_iterator position, Args&&... args); iterator insert(const_iterator position, const value_type& x); iterator insert(const_iterator position, value_type&& x); iterator insert(const_iterator position, size_type n, const value_type& x); template iterator insert(const_iterator position, InputIterator first, InputIterator last); iterator insert(const_iterator position, initializer_list il); iterator erase(const_iterator position); iterator erase(const_iterator first, const_iterator last); void clear() noexcept; void resize(size_type sz); void resize(size_type sz, const value_type& c); void swap(vector&) noexcept(allocator_traits::propagate_on_container_swap::value || allocator_traits::is_always_equal::value); // C++17 bool __invariants() const; }; template > class vector { public: typedef bool value_type; typedef Allocator allocator_type; typedef implementation-defined iterator; typedef implementation-defined const_iterator; typedef typename allocator_type::size_type size_type; typedef typename allocator_type::difference_type difference_type; typedef iterator pointer; typedef const_iterator const_pointer; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; class reference { public: reference(const reference&) noexcept; operator bool() const noexcept; reference& operator=(bool x) noexcept; reference& operator=(const reference& x) noexcept; iterator operator&() const noexcept; void flip() noexcept; }; class const_reference { public: const_reference(const reference&) noexcept; operator bool() const noexcept; const_iterator operator&() const noexcept; }; vector() noexcept(is_nothrow_default_constructible::value); explicit vector(const allocator_type&); explicit vector(size_type n, const allocator_type& a = allocator_type()); // C++14 vector(size_type n, const value_type& value, const allocator_type& = allocator_type()); template vector(InputIterator first, InputIterator last, const allocator_type& = allocator_type()); vector(const vector& x); vector(vector&& x) noexcept(is_nothrow_move_constructible::value); vector(initializer_list il); vector(initializer_list il, const allocator_type& a); ~vector(); vector& operator=(const vector& x); vector& operator=(vector&& x) noexcept( allocator_type::propagate_on_container_move_assignment::value || allocator_type::is_always_equal::value); // C++17 vector& operator=(initializer_list il); template void assign(InputIterator first, InputIterator last); void assign(size_type n, const value_type& u); void assign(initializer_list il); allocator_type get_allocator() const noexcept; iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; size_type capacity() const noexcept; bool empty() const noexcept; void reserve(size_type n); void shrink_to_fit() noexcept; reference operator[](size_type n); const_reference operator[](size_type n) const; reference at(size_type n); const_reference at(size_type n) const; reference front(); const_reference front() const; reference back(); const_reference back() const; void push_back(const value_type& x); template reference emplace_back(Args&&... args); // C++14; reference in C++17 void pop_back(); template iterator emplace(const_iterator position, Args&&... args); // C++14 iterator insert(const_iterator position, const value_type& x); iterator insert(const_iterator position, size_type n, const value_type& x); template iterator insert(const_iterator position, InputIterator first, InputIterator last); iterator insert(const_iterator position, initializer_list il); iterator erase(const_iterator position); iterator erase(const_iterator first, const_iterator last); void clear() noexcept; void resize(size_type sz); void resize(size_type sz, value_type x); void swap(vector&) noexcept(allocator_traits::propagate_on_container_swap::value || allocator_traits::is_always_equal::value); // C++17 void flip() noexcept; bool __invariants() const; }; template ::value_type>> vector(InputIterator, InputIterator, Allocator = Allocator()) -> vector::value_type, Allocator>; // C++17 template struct hash>; template bool operator==(const vector& x, const vector& y); template bool operator< (const vector& x, const vector& y); template bool operator!=(const vector& x, const vector& y); template bool operator> (const vector& x, const vector& y); template bool operator>=(const vector& x, const vector& y); template bool operator<=(const vector& x, const vector& y); template void swap(vector& x, vector& y) noexcept(noexcept(x.swap(y))); template typename vector::size_type erase(vector& c, const U& value); // C++20 template typename vector::size_type erase_if(vector& c, Predicate pred); // C++20 template inline constexpr bool is-vector-bool-reference = see below; // exposition only, since C++23 template requires is-vector-bool-reference // Since C++23 struct formatter; } // std */ #include <__algorithm/copy.h> #include <__algorithm/equal.h> #include <__algorithm/fill_n.h> #include <__algorithm/lexicographical_compare.h> #include <__algorithm/remove.h> #include <__algorithm/remove_if.h> #include <__algorithm/rotate.h> #include <__algorithm/unwrap_iter.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__bit_reference> #include <__concepts/same_as.h> #include <__config> #include <__debug> #include <__format/enable_insertable.h> #include <__format/formatter.h> #include <__functional/hash.h> #include <__functional/unary_function.h> #include <__iterator/advance.h> #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> #include <__iterator/wrap_iter.h> #include <__memory/allocate_at_least.h> #include <__memory/pointer_traits.h> #include <__memory/swap_allocator.h> #include <__memory/temp_value.h> #include <__memory/uninitialized_algorithms.h> #include <__memory_resource/polymorphic_allocator.h> #include <__split_buffer> #include <__type_traits/is_allocator.h> #include <__type_traits/noexcept_move_assign_container.h> #include <__utility/exception_guard.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/swap.h> #include #include #include #include // for forward declaration of vector #include #include #include #include // standard-mandated includes // [iterator.range] #include <__iterator/access.h> #include <__iterator/data.h> #include <__iterator/empty.h> #include <__iterator/reverse_access.h> #include <__iterator/size.h> // [vector.syn] #include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD template */> class _LIBCPP_TEMPLATE_VIS vector { private: typedef allocator<_Tp> __default_allocator_type; public: typedef vector __self; typedef _Tp value_type; typedef _Allocator allocator_type; typedef allocator_traits __alloc_traits; typedef value_type& reference; typedef const value_type& const_reference; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; // TODO: Implement iterator bounds checking without requiring the global database. typedef __wrap_iter iterator; typedef __wrap_iter const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; static_assert((is_same::value), "Allocator::value_type must be same type as value_type"); static_assert(is_same >::value, "[allocator.requirements] states that rebinding an allocator to the same type should result in the " "original allocator"); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector() _NOEXCEPT_(is_nothrow_default_constructible::value) { std::__debug_db_insert_c(this); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_copy_constructible::value) #else _NOEXCEPT #endif : __end_cap_(nullptr, __a) { std::__debug_db_insert_c(this); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n); #if _LIBCPP_STD_VER > 11 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n, const allocator_type& __a); #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(size_type __n, const value_type& __x); template ::value> > _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(size_type __n, const value_type& __x, const allocator_type& __a) : __end_cap_(nullptr, __a) { std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); __construct_at_end(__n, __x); } } template ::value && is_constructible::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(_InputIterator __first, _InputIterator __last); template ::value && is_constructible::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a); template < class _ForwardIterator, __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value && is_constructible::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(_ForwardIterator __first, _ForwardIterator __last); template ::value && is_constructible::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a); private: class __destroy_vector { public: _LIBCPP_CONSTEXPR __destroy_vector(vector& __vec) : __vec_(__vec) {} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() { __vec_.__annotate_delete(); std::__debug_db_erase_c(std::addressof(__vec_)); if (__vec_.__begin_ != nullptr) { __vec_.__clear(); __alloc_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.capacity()); } } private: vector& __vec_; }; public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~vector() { __destroy_vector(*this)(); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(const vector& __x); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(const vector& __x, const __type_identity_t& __a); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(const vector& __x); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(initializer_list __il); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(initializer_list __il, const allocator_type& __a); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(initializer_list __il) {assign(__il.begin(), __il.end()); return *this;} #endif // !_LIBCPP_CXX03_LANG _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(vector&& __x) #if _LIBCPP_STD_VER > 14 noexcept; #else _NOEXCEPT_(is_nothrow_move_constructible::value); #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(vector&& __x, const __type_identity_t& __a); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(vector&& __x) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)); template ::value && is_constructible::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(_InputIterator __first, _InputIterator __last); template < class _ForwardIterator, __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value && is_constructible::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(_ForwardIterator __first, _ForwardIterator __last); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(size_type __n, const_reference __u); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(initializer_list __il) {assign(__il.begin(), __il.end());} #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {return this->__alloc();} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT {return begin();} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT {return end();} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT {return rend();} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {return static_cast(this->__end_ - this->__begin_);} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {return static_cast(__end_cap() - this->__begin_);} _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {return this->__begin_ == this->__end_;} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference operator[](size_type __n) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference at(size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const; _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "front() called on an empty vector"); return *this->__begin_; } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "front() called on an empty vector"); return *this->__begin_; } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "back() called on an empty vector"); return *(this->__end_ - 1); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "back() called on an empty vector"); return *(this->__end_ - 1); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI value_type* data() _NOEXCEPT {return std::__to_address(this->__begin_);} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const value_type* data() const _NOEXCEPT {return std::__to_address(this->__begin_);} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(const_reference __x); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __x); template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI #if _LIBCPP_STD_VER > 14 reference emplace_back(_Args&&... __args); #else void emplace_back(_Args&&... __args); #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back(); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, const_reference __x); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, value_type&& __x); template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator emplace(const_iterator __position, _Args&&... __args); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, size_type __n, const_reference __x); template ::value && is_constructible< value_type, typename iterator_traits<_InputIterator>::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, _InputIterator __first, _InputIterator __last); template < class _ForwardIterator, __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value && is_constructible< value_type, typename iterator_traits<_ForwardIterator>::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, initializer_list __il) {return insert(__position, __il.begin(), __il.end());} #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { size_type __old_size = size(); __clear(); __annotate_shrink(__old_size); std::__debug_db_invalidate_all(this); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz, const_reference __x); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(vector&) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT; #else _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable::value); #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const; #ifdef _LIBCPP_ENABLE_DEBUG_MODE bool __dereferenceable(const const_iterator* __i) const; bool __decrementable(const const_iterator* __i) const; bool __addable(const const_iterator* __i, ptrdiff_t __n) const; bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; #endif // _LIBCPP_ENABLE_DEBUG_MODE private: pointer __begin_ = nullptr; pointer __end_ = nullptr; __compressed_pair __end_cap_ = __compressed_pair(nullptr, __default_init_tag()); _LIBCPP_HIDE_FROM_ABI void __invalidate_iterators_past(pointer __new_last); // Allocate space for __n objects // throws length_error if __n > max_size() // throws (probably bad_alloc) if memory run out // Precondition: __begin_ == __end_ == __end_cap() == 0 // Precondition: __n > 0 // Postcondition: capacity() >= __n // Postcondition: size() == 0 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) { if (__n > max_size()) __throw_length_error(); auto __allocation = std::__allocate_at_least(__alloc(), __n); __begin_ = __allocation.ptr; __end_ = __allocation.ptr; __end_cap() = __begin_ + __allocation.count; __annotate_new(0); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vdeallocate() _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __recommend(size_type __new_size) const; _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n, const_reference __x); template ::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(_ForwardIterator __first, _ForwardIterator __last, size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __append(size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __append(size_type __n, const_reference __x); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator __make_iter(pointer __p) _NOEXCEPT { return iterator(this, __p); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator __make_iter(const_pointer __p) const _NOEXCEPT { return const_iterator(this, __p); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_out_circular_buffer(__split_buffer& __v); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __swap_out_circular_buffer(__split_buffer& __v, pointer __p); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_range(pointer __from_s, pointer __from_e, pointer __to); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign(vector& __c, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last) _NOEXCEPT { if (!__libcpp_is_constant_evaluated()) __invalidate_iterators_past(__new_last); size_type __old_size = size(); __base_destruct_at_end(__new_last); __annotate_shrink(__old_size); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI inline void __push_back_slow_path(_Up&& __x); template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI inline void __emplace_back_slow_path(_Args&&... __args); // The following functions are no-ops outside of AddressSanitizer mode. // We call annotatations only for the default Allocator because other allocators // may not meet the AddressSanitizer alignment constraints. // See the documentation for __sanitizer_annotate_contiguous_container for more details. #ifndef _LIBCPP_HAS_NO_ASAN _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_contiguous_container(const void *__beg, const void *__end, const void *__old_mid, const void *__new_mid) const { if (!__libcpp_is_constant_evaluated() && __beg && is_same::value) __sanitizer_annotate_contiguous_container(__beg, __end, __old_mid, __new_mid); } #else _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_contiguous_container(const void*, const void*, const void*, const void*) const _NOEXCEPT {} #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_new(size_type __current_size) const _NOEXCEPT { __annotate_contiguous_container(data(), data() + capacity(), data() + capacity(), data() + __current_size); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_delete() const _NOEXCEPT { __annotate_contiguous_container(data(), data() + capacity(), data() + size(), data() + capacity()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_increase(size_type __n) const _NOEXCEPT { __annotate_contiguous_container(data(), data() + capacity(), data() + size(), data() + size() + __n); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_shrink(size_type __old_size) const _NOEXCEPT { __annotate_contiguous_container(data(), data() + capacity(), data() + __old_size, data() + size()); } struct _ConstructTransaction { _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(vector &__v, size_type __n) : __v_(__v), __pos_(__v.__end_), __new_end_(__v.__end_ + __n) { #ifndef _LIBCPP_HAS_NO_ASAN __v_.__annotate_increase(__n); #endif } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() { __v_.__end_ = __pos_; #ifndef _LIBCPP_HAS_NO_ASAN if (__pos_ != __new_end_) { __v_.__annotate_shrink(__new_end_ - __v_.__begin_); } #endif } vector &__v_; pointer __pos_; const_pointer const __new_end_; private: _ConstructTransaction(_ConstructTransaction const&) = delete; _ConstructTransaction& operator=(_ConstructTransaction const&) = delete; }; template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_one_at_end(_Args&& ...__args) { _ConstructTransaction __tx(*this, 1); __alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...); ++__tx.__pos_; } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT {return this->__end_cap_.second();} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const allocator_type& __alloc() const _NOEXCEPT {return this->__end_cap_.second();} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer& __end_cap() _NOEXCEPT {return this->__end_cap_.first();} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const pointer& __end_cap() const _NOEXCEPT {return this->__end_cap_.first();} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __clear() _NOEXCEPT {__base_destruct_at_end(this->__begin_);} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __base_destruct_at_end(pointer __new_last) _NOEXCEPT { pointer __soon_to_be_end = this->__end_; while (__new_last != __soon_to_be_end) __alloc_traits::destroy(__alloc(), std::__to_address(--__soon_to_be_end)); this->__end_ = __new_last; } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c) {__copy_assign_alloc(__c, integral_constant());} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector& __c) _NOEXCEPT_( !__alloc_traits::propagate_on_container_move_assignment::value || is_nothrow_move_assignable::value) {__move_assign_alloc(__c, integral_constant());} _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_length_error() const { std::__throw_length_error("vector"); } _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { std::__throw_out_of_range("vector"); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c, true_type) { if (__alloc() != __c.__alloc()) { __clear(); __alloc_traits::deallocate(__alloc(), this->__begin_, capacity()); this->__begin_ = this->__end_ = __end_cap() = nullptr; } __alloc() = __c.__alloc(); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector&, false_type) {} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { __alloc() = std::move(__c.__alloc()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector&, false_type) _NOEXCEPT {} }; #if _LIBCPP_STD_VER >= 17 template>, class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Alloc>::value> > vector(_InputIterator, _InputIterator) -> vector<__iter_value_type<_InputIterator>, _Alloc>; template::value>, class = enable_if_t<__is_allocator<_Alloc>::value> > vector(_InputIterator, _InputIterator, _Alloc) -> vector<__iter_value_type<_InputIterator>, _Alloc>; #endif template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v) { __annotate_delete(); using _RevIter = std::reverse_iterator; __v.__begin_ = std::__uninitialized_allocator_move_if_noexcept( __alloc(), _RevIter(__end_), _RevIter(__begin_), _RevIter(__v.__begin_)) .base(); std::swap(this->__begin_, __v.__begin_); std::swap(this->__end_, __v.__end_); std::swap(this->__end_cap(), __v.__end_cap()); __v.__first_ = __v.__begin_; __annotate_new(size()); std::__debug_db_invalidate_all(this); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer __p) { __annotate_delete(); pointer __r = __v.__begin_; using _RevIter = std::reverse_iterator; __v.__begin_ = std::__uninitialized_allocator_move_if_noexcept( __alloc(), _RevIter(__p), _RevIter(__begin_), _RevIter(__v.__begin_)) .base(); __v.__end_ = std::__uninitialized_allocator_move_if_noexcept(__alloc(), __p, __end_, __v.__end_); std::swap(this->__begin_, __v.__begin_); std::swap(this->__end_, __v.__end_); std::swap(this->__end_cap(), __v.__end_cap()); __v.__first_ = __v.__begin_; __annotate_new(size()); std::__debug_db_invalidate_all(this); return __r; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT { if (this->__begin_ != nullptr) { clear(); __alloc_traits::deallocate(this->__alloc(), this->__begin_, capacity()); this->__begin_ = this->__end_ = this->__end_cap() = nullptr; } } template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::size_type vector<_Tp, _Allocator>::max_size() const _NOEXCEPT { return std::min(__alloc_traits::max_size(this->__alloc()), numeric_limits::max()); } // Precondition: __new_size > capacity() template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::size_type vector<_Tp, _Allocator>::__recommend(size_type __new_size) const { const size_type __ms = max_size(); if (__new_size > __ms) this->__throw_length_error(); const size_type __cap = capacity(); if (__cap >= __ms / 2) return __ms; return std::max(2 * __cap, __new_size); } // Default constructs __n objects starting at __end_ // throws if construction throws // Precondition: __n > 0 // Precondition: size() + __n <= capacity() // Postcondition: size() == size() + __n template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(size_type __n) { _ConstructTransaction __tx(*this, __n); const_pointer __new_end = __tx.__new_end_; for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) { __alloc_traits::construct(this->__alloc(), std::__to_address(__pos)); } } // Copy constructs __n objects starting at __end_ from __x // throws if construction throws // Precondition: __n > 0 // Precondition: size() + __n <= capacity() // Postcondition: size() == old size() + __n // Postcondition: [i] == __x for all i in [size() - __n, __n) template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline void vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) { _ConstructTransaction __tx(*this, __n); const_pointer __new_end = __tx.__new_end_; for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) { __alloc_traits::construct(this->__alloc(), std::__to_address(__pos), __x); } } template template ::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last, size_type __n) { _ConstructTransaction __tx(*this, __n); __tx.__pos_ = std::__uninitialized_allocator_copy(__alloc(), __first, __last, __tx.__pos_); } // Default constructs __n objects starting at __end_ // throws if construction throws // Postcondition: size() == size() + __n // Exception safety: strong. template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__append(size_type __n) { if (static_cast(this->__end_cap() - this->__end_) >= __n) this->__construct_at_end(__n); else { allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + __n), size(), __a); __v.__construct_at_end(__n); __swap_out_circular_buffer(__v); } } // Default constructs __n objects starting at __end_ // throws if construction throws // Postcondition: size() == size() + __n // Exception safety: strong. template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__append(size_type __n, const_reference __x) { if (static_cast(this->__end_cap() - this->__end_) >= __n) this->__construct_at_end(__n, __x); else { allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + __n), size(), __a); __v.__construct_at_end(__n, __x); __swap_out_circular_buffer(__v); } } template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); __construct_at_end(__n); } __guard.__complete(); } #if _LIBCPP_STD_VER > 11 template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a) : __end_cap_(nullptr, __a) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); __construct_at_end(__n); } __guard.__complete(); } #endif template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); __construct_at_end(__n, __x); } __guard.__complete(); } template template ::value && is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); for (; __first != __last; ++__first) emplace_back(*__first); __guard.__complete(); } template template ::value && is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : __end_cap_(nullptr, __a) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); for (; __first != __last; ++__first) emplace_back(*__first); __guard.__complete(); } template template ::value && is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) { __vallocate(__n); __construct_at_end(__first, __last, __n); } __guard.__complete(); } template template ::value && is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a) : __end_cap_(nullptr, __a) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) { __vallocate(__n); __construct_at_end(__first, __last, __n); } __guard.__complete(); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(const vector& __x) : __end_cap_(nullptr, __alloc_traits::select_on_container_copy_construction(__x.__alloc())) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); size_type __n = __x.size(); if (__n > 0) { __vallocate(__n); __construct_at_end(__x.__begin_, __x.__end_, __n); } __guard.__complete(); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(const vector& __x, const __type_identity_t& __a) : __end_cap_(nullptr, __a) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); size_type __n = __x.size(); if (__n > 0) { __vallocate(__n); __construct_at_end(__x.__begin_, __x.__end_, __n); } __guard.__complete(); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(vector&& __x) #if _LIBCPP_STD_VER > 14 noexcept #else _NOEXCEPT_(is_nothrow_move_constructible::value) #endif : __end_cap_(nullptr, std::move(__x.__alloc())) { std::__debug_db_insert_c(this); std::__debug_db_swap(this, std::addressof(__x)); this->__begin_ = __x.__begin_; this->__end_ = __x.__end_; this->__end_cap() = __x.__end_cap(); __x.__begin_ = __x.__end_ = __x.__end_cap() = nullptr; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t& __a) : __end_cap_(nullptr, __a) { std::__debug_db_insert_c(this); if (__a == __x.__alloc()) { this->__begin_ = __x.__begin_; this->__end_ = __x.__end_; this->__end_cap() = __x.__end_cap(); __x.__begin_ = __x.__end_ = __x.__end_cap() = nullptr; std::__debug_db_swap(this, std::addressof(__x)); } else { typedef move_iterator _Ip; auto __guard = std::__make_exception_guard(__destroy_vector(*this)); assign(_Ip(__x.begin()), _Ip(__x.end())); __guard.__complete(); } } #ifndef _LIBCPP_CXX03_LANG template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(initializer_list __il) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__il.size() > 0) { __vallocate(__il.size()); __construct_at_end(__il.begin(), __il.end(), __il.size()); } __guard.__complete(); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(initializer_list __il, const allocator_type& __a) : __end_cap_(nullptr, __a) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__il.size() > 0) { __vallocate(__il.size()); __construct_at_end(__il.begin(), __il.end(), __il.size()); } __guard.__complete(); } #endif // _LIBCPP_CXX03_LANG template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>& vector<_Tp, _Allocator>::operator=(vector&& __x) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) { __move_assign(__x, integral_constant()); return *this; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value) { if (__alloc() != __c.__alloc()) { typedef move_iterator _Ip; assign(_Ip(__c.begin()), _Ip(__c.end())); } else __move_assign(__c, true_type()); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { __vdeallocate(); __move_assign_alloc(__c); // this can throw this->__begin_ = __c.__begin_; this->__end_ = __c.__end_; this->__end_cap() = __c.__end_cap(); __c.__begin_ = __c.__end_ = __c.__end_cap() = nullptr; std::__debug_db_swap(this, std::addressof(__c)); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>& vector<_Tp, _Allocator>::operator=(const vector& __x) { if (this != std::addressof(__x)) { __copy_assign_alloc(__x); assign(__x.__begin_, __x.__end_); } return *this; } template template ::value && is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(_InputIterator __first, _InputIterator __last) { clear(); for (; __first != __last; ++__first) emplace_back(*__first); } template template ::value && is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last) { size_type __new_size = static_cast(std::distance(__first, __last)); if (__new_size <= capacity()) { _ForwardIterator __mid = __last; bool __growing = false; if (__new_size > size()) { __growing = true; __mid = __first; std::advance(__mid, size()); } pointer __m = std::copy(__first, __mid, this->__begin_); if (__growing) __construct_at_end(__mid, __last, __new_size - size()); else this->__destruct_at_end(__m); } else { __vdeallocate(); __vallocate(__recommend(__new_size)); __construct_at_end(__first, __last, __new_size); } std::__debug_db_invalidate_all(this); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) { if (__n <= capacity()) { size_type __s = size(); std::fill_n(this->__begin_, std::min(__n, __s), __u); if (__n > __s) __construct_at_end(__n - __s, __u); else this->__destruct_at_end(this->__begin_ + __n); } else { __vdeallocate(); __vallocate(__recommend(static_cast(__n))); __construct_at_end(__n, __u); } std::__debug_db_invalidate_all(this); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::begin() _NOEXCEPT { return __make_iter(this->__begin_); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::const_iterator vector<_Tp, _Allocator>::begin() const _NOEXCEPT { return __make_iter(this->__begin_); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::end() _NOEXCEPT { return __make_iter(this->__end_); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::const_iterator vector<_Tp, _Allocator>::end() const _NOEXCEPT { return __make_iter(this->__end_); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::reference vector<_Tp, _Allocator>::operator[](size_type __n) _NOEXCEPT { _LIBCPP_ASSERT(__n < size(), "vector[] index out of bounds"); return this->__begin_[__n]; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::const_reference vector<_Tp, _Allocator>::operator[](size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n < size(), "vector[] index out of bounds"); return this->__begin_[__n]; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::reference vector<_Tp, _Allocator>::at(size_type __n) { if (__n >= size()) this->__throw_out_of_range(); return this->__begin_[__n]; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::const_reference vector<_Tp, _Allocator>::at(size_type __n) const { if (__n >= size()) this->__throw_out_of_range(); return this->__begin_[__n]; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __n) { if (__n > capacity()) { if (__n > max_size()) this->__throw_length_error(); allocator_type& __a = this->__alloc(); __split_buffer __v(__n, size(), __a); __swap_out_circular_buffer(__v); } } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT { if (capacity() > size()) { #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS allocator_type& __a = this->__alloc(); __split_buffer __v(size(), size(), __a); __swap_out_circular_buffer(__v); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { } #endif // _LIBCPP_NO_EXCEPTIONS } } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__push_back_slow_path(_Up&& __x) { allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + 1), size(), __a); // __v.push_back(std::forward<_Up>(__x)); __alloc_traits::construct(__a, std::__to_address(__v.__end_), std::forward<_Up>(__x)); __v.__end_++; __swap_out_circular_buffer(__v); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void vector<_Tp, _Allocator>::push_back(const_reference __x) { if (this->__end_ != this->__end_cap()) { __construct_one_at_end(__x); } else __push_back_slow_path(__x); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void vector<_Tp, _Allocator>::push_back(value_type&& __x) { if (this->__end_ < this->__end_cap()) { __construct_one_at_end(std::move(__x)); } else __push_back_slow_path(std::move(__x)); } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) { allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + 1), size(), __a); // __v.emplace_back(std::forward<_Args>(__args)...); __alloc_traits::construct(__a, std::__to_address(__v.__end_), std::forward<_Args>(__args)...); __v.__end_++; __swap_out_circular_buffer(__v); } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline #if _LIBCPP_STD_VER > 14 typename vector<_Tp, _Allocator>::reference #else void #endif vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) { if (this->__end_ < this->__end_cap()) { __construct_one_at_end(std::forward<_Args>(__args)...); } else __emplace_back_slow_path(std::forward<_Args>(__args)...); #if _LIBCPP_STD_VER > 14 return this->back(); #endif } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline void vector<_Tp, _Allocator>::pop_back() { _LIBCPP_ASSERT(!empty(), "vector::pop_back called on an empty vector"); this->__destruct_at_end(this->__end_ - 1); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::erase(const_iterator __position) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this, "vector::erase(iterator) called with an iterator not referring to this vector"); _LIBCPP_ASSERT(__position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator"); difference_type __ps = __position - cbegin(); pointer __p = this->__begin_ + __ps; this->__destruct_at_end(std::move(__p + 1, this->__end_, __p)); if (!__libcpp_is_constant_evaluated()) this->__invalidate_iterators_past(__p - 1); return __make_iter(__p); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__first)) == this, "vector::erase(iterator, iterator) called with an iterator not referring to this vector"); _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__last)) == this, "vector::erase(iterator, iterator) called with an iterator not referring to this vector"); _LIBCPP_ASSERT(__first <= __last, "vector::erase(first, last) called with invalid range"); pointer __p = this->__begin_ + (__first - begin()); if (__first != __last) { this->__destruct_at_end(std::move(__p + (__last - __first), this->__end_, __p)); if (!__libcpp_is_constant_evaluated()) this->__invalidate_iterators_past(__p - 1); } return __make_iter(__p); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointer __to) { pointer __old_last = this->__end_; difference_type __n = __old_last - __to; { pointer __i = __from_s + __n; _ConstructTransaction __tx(*this, __from_e - __i); for (pointer __pos = __tx.__pos_; __i < __from_e; ++__i, (void) ++__pos, __tx.__pos_ = __pos) { __alloc_traits::construct(this->__alloc(), std::__to_address(__pos), std::move(*__i)); } } std::move_backward(__from_s, __from_s + __n, __old_last); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this, "vector::insert(iterator, x) called with an iterator not referring to this vector"); pointer __p = this->__begin_ + (__position - begin()); // We can't compare unrelated pointers inside constant expressions if (!__libcpp_is_constant_evaluated() && this->__end_ < this->__end_cap()) { if (__p == this->__end_) { __construct_one_at_end(__x); } else { __move_range(__p, this->__end_, __p + 1); const_pointer __xr = pointer_traits::pointer_to(__x); if (__p <= __xr && __xr < this->__end_) ++__xr; *__p = *__xr; } } else { allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, __a); __v.push_back(__x); __p = __swap_out_circular_buffer(__v, __p); } return __make_iter(__p); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this, "vector::insert(iterator, x) called with an iterator not referring to this vector"); pointer __p = this->__begin_ + (__position - begin()); if (this->__end_ < this->__end_cap()) { if (__p == this->__end_) { __construct_one_at_end(std::move(__x)); } else { __move_range(__p, this->__end_, __p + 1); *__p = std::move(__x); } } else { allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, __a); __v.push_back(std::move(__x)); __p = __swap_out_circular_buffer(__v, __p); } return __make_iter(__p); } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this, "vector::emplace(iterator, x) called with an iterator not referring to this vector"); pointer __p = this->__begin_ + (__position - begin()); if (this->__end_ < this->__end_cap()) { if (__p == this->__end_) { __construct_one_at_end(std::forward<_Args>(__args)...); } else { __temp_value __tmp(this->__alloc(), std::forward<_Args>(__args)...); __move_range(__p, this->__end_, __p + 1); *__p = std::move(__tmp.get()); } } else { allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, __a); __v.emplace_back(std::forward<_Args>(__args)...); __p = __swap_out_circular_buffer(__v, __p); } return __make_iter(__p); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this, "vector::insert(iterator, n, x) called with an iterator not referring to this vector"); pointer __p = this->__begin_ + (__position - begin()); if (__n > 0) { // We can't compare unrelated pointers inside constant expressions if (!__libcpp_is_constant_evaluated() && __n <= static_cast(this->__end_cap() - this->__end_)) { size_type __old_n = __n; pointer __old_last = this->__end_; if (__n > static_cast(this->__end_ - __p)) { size_type __cx = __n - (this->__end_ - __p); __construct_at_end(__cx, __x); __n -= __cx; } if (__n > 0) { __move_range(__p, __old_last, __p + __old_n); const_pointer __xr = pointer_traits::pointer_to(__x); if (__p <= __xr && __xr < this->__end_) __xr += __old_n; std::fill_n(__p, __n, *__xr); } } else { allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + __n), __p - this->__begin_, __a); __v.__construct_at_end(__n, __x); __p = __swap_out_circular_buffer(__v, __p); } } return __make_iter(__p); } template template ::value && is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, _InputIterator __first, _InputIterator __last) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this, "vector::insert(iterator, range) called with an iterator not referring to this vector"); difference_type __off = __position - begin(); pointer __p = this->__begin_ + __off; allocator_type& __a = this->__alloc(); pointer __old_last = this->__end_; for (; this->__end_ != this->__end_cap() && __first != __last; ++__first) { __construct_one_at_end(*__first); } __split_buffer __v(__a); if (__first != __last) { #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS __v.__construct_at_end(__first, __last); difference_type __old_size = __old_last - this->__begin_; difference_type __old_p = __p - this->__begin_; reserve(__recommend(size() + __v.size())); __p = this->__begin_ + __old_p; __old_last = this->__begin_ + __old_size; #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { erase(__make_iter(__old_last), end()); throw; } #endif // _LIBCPP_NO_EXCEPTIONS } __p = std::rotate(__p, __old_last, this->__end_); insert(__make_iter(__p), std::make_move_iterator(__v.begin()), std::make_move_iterator(__v.end())); return begin() + __off; } template template ::value && is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this, "vector::insert(iterator, range) called with an iterator not referring to this vector"); pointer __p = this->__begin_ + (__position - begin()); difference_type __n = std::distance(__first, __last); if (__n > 0) { if (__n <= this->__end_cap() - this->__end_) { size_type __old_n = __n; pointer __old_last = this->__end_; _ForwardIterator __m = __last; difference_type __dx = this->__end_ - __p; if (__n > __dx) { __m = __first; difference_type __diff = this->__end_ - __p; std::advance(__m, __diff); __construct_at_end(__m, __last, __n - __diff); __n = __dx; } if (__n > 0) { __move_range(__p, __old_last, __p + __old_n); std::copy(__first, __m, __p); } } else { allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + __n), __p - this->__begin_, __a); __v.__construct_at_end(__first, __last); __p = __swap_out_circular_buffer(__v, __p); } } return __make_iter(__p); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __sz) { size_type __cs = size(); if (__cs < __sz) this->__append(__sz - __cs); else if (__cs > __sz) this->__destruct_at_end(this->__begin_ + __sz); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __sz, const_reference __x) { size_type __cs = size(); if (__cs < __sz) this->__append(__sz - __cs, __x); else if (__cs > __sz) this->__destruct_at_end(this->__begin_ + __sz); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::swap(vector& __x) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT #else _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable::value) #endif { _LIBCPP_ASSERT(__alloc_traits::propagate_on_container_swap::value || this->__alloc() == __x.__alloc(), "vector::swap: Either propagate_on_container_swap must be true" " or the allocators must compare equal"); std::swap(this->__begin_, __x.__begin_); std::swap(this->__end_, __x.__end_); std::swap(this->__end_cap(), __x.__end_cap()); std::__swap_allocator(this->__alloc(), __x.__alloc(), integral_constant()); std::__debug_db_swap(this, std::addressof(__x)); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 bool vector<_Tp, _Allocator>::__invariants() const { if (this->__begin_ == nullptr) { if (this->__end_ != nullptr || this->__end_cap() != nullptr) return false; } else { if (this->__begin_ > this->__end_) return false; if (this->__begin_ == this->__end_cap()) return false; if (this->__end_ > this->__end_cap()) return false; } return true; } #ifdef _LIBCPP_ENABLE_DEBUG_MODE template bool vector<_Tp, _Allocator>::__dereferenceable(const const_iterator* __i) const { return this->__begin_ <= __i->base() && __i->base() < this->__end_; } template bool vector<_Tp, _Allocator>::__decrementable(const const_iterator* __i) const { return this->__begin_ < __i->base() && __i->base() <= this->__end_; } template bool vector<_Tp, _Allocator>::__addable(const const_iterator* __i, ptrdiff_t __n) const { const_pointer __p = __i->base() + __n; return this->__begin_ <= __p && __p <= this->__end_; } template bool vector<_Tp, _Allocator>::__subscriptable(const const_iterator* __i, ptrdiff_t __n) const { const_pointer __p = __i->base() + __n; return this->__begin_ <= __p && __p < this->__end_; } #endif // _LIBCPP_ENABLE_DEBUG_MODE template inline _LIBCPP_HIDE_FROM_ABI void vector<_Tp, _Allocator>::__invalidate_iterators_past(pointer __new_last) { #ifdef _LIBCPP_ENABLE_DEBUG_MODE __c_node* __c = __get_db()->__find_c_and_lock(this); for (__i_node** __p = __c->end_; __p != __c->beg_; ) { --__p; const_iterator* __i = static_cast((*__p)->__i_); if (__i->base() > __new_last) { (*__p)->__c_ = nullptr; if (--__c->end_ != __p) std::memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); } } __get_db()->unlock(); #else ((void)__new_last); #endif } // vector template class vector; template struct hash >; template struct __has_storage_type > { static const bool value = true; }; template class _LIBCPP_TEMPLATE_VIS vector { public: typedef vector __self; typedef bool value_type; typedef _Allocator allocator_type; typedef allocator_traits __alloc_traits; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; typedef size_type __storage_type; typedef __bit_iterator pointer; typedef __bit_iterator const_pointer; typedef pointer iterator; typedef const_pointer const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; private: typedef __rebind_alloc<__alloc_traits, __storage_type> __storage_allocator; typedef allocator_traits<__storage_allocator> __storage_traits; typedef typename __storage_traits::pointer __storage_pointer; typedef typename __storage_traits::const_pointer __const_storage_pointer; __storage_pointer __begin_; size_type __size_; __compressed_pair __cap_alloc_; public: typedef __bit_reference reference; #ifdef _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL using const_reference = bool; #else typedef __bit_const_reference const_reference; #endif private: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type& __cap() _NOEXCEPT {return __cap_alloc_.first();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const size_type& __cap() const _NOEXCEPT {return __cap_alloc_.first();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __storage_allocator& __alloc() _NOEXCEPT {return __cap_alloc_.second();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const __storage_allocator& __alloc() const _NOEXCEPT {return __cap_alloc_.second();} static const unsigned __bits_per_word = static_cast(sizeof(__storage_type) * CHAR_BIT); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type __internal_cap_to_external(size_type __n) _NOEXCEPT {return __n * __bits_per_word;} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type __external_cap_to_internal(size_type __n) _NOEXCEPT {return (__n - 1) / __bits_per_word + 1;} public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector() _NOEXCEPT_(is_nothrow_default_constructible::value); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit vector(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_copy_constructible::value); #else _NOEXCEPT; #endif private: class __destroy_vector { public: _LIBCPP_CONSTEXPR __destroy_vector(vector& __vec) : __vec_(__vec) {} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() { if (__vec_.__begin_ != nullptr) __storage_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.__cap()); std::__debug_db_invalidate_all(this); } private: vector& __vec_; }; public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~vector() { __destroy_vector(*this)(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit vector(size_type __n); #if _LIBCPP_STD_VER > 11 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit vector(size_type __n, const allocator_type& __a); #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(size_type __n, const value_type& __v); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(size_type __n, const value_type& __v, const allocator_type& __a); template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(_InputIterator __first, _InputIterator __last, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type* = 0); template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type* = 0); template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(_ForwardIterator __first, _ForwardIterator __last, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type* = 0); template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type* = 0); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(const vector& __v); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(const vector& __v, const allocator_type& __a); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector& operator=(const vector& __v); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(initializer_list __il); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(initializer_list __il, const allocator_type& __a); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector& operator=(initializer_list __il) {assign(__il.begin(), __il.end()); return *this;} #endif // !_LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(vector&& __v) #if _LIBCPP_STD_VER > 14 noexcept; #else _NOEXCEPT_(is_nothrow_move_constructible::value); #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(vector&& __v, const __type_identity_t& __a); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector& operator=(vector&& __v) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)); template typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, void >::type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 assign(_InputIterator __first, _InputIterator __last); template typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, void >::type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 assign(_ForwardIterator __first, _ForwardIterator __last); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void assign(size_type __n, const value_type& __x); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void assign(initializer_list __il) {assign(__il.begin(), __il.end());} #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator_type get_allocator() const _NOEXCEPT {return allocator_type(this->__alloc());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type max_size() const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type capacity() const _NOEXCEPT {return __internal_cap_to_external(__cap());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type size() const _NOEXCEPT {return __size_;} _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool empty() const _NOEXCEPT {return __size_ == 0;} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reserve(size_type __n); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void shrink_to_fit() _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator begin() _NOEXCEPT {return __make_iter(0);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator begin() const _NOEXCEPT {return __make_iter(0);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator end() _NOEXCEPT {return __make_iter(__size_);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator end() const _NOEXCEPT {return __make_iter(__size_);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator cbegin() const _NOEXCEPT {return __make_iter(0);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator cend() const _NOEXCEPT {return __make_iter(__size_);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator crend() const _NOEXCEPT {return rend();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](size_type __n) {return __make_ref(__n);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference operator[](size_type __n) const {return __make_ref(__n);} _LIBCPP_HIDE_FROM_ABI reference at(size_type __n); _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() {return __make_ref(0);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference front() const {return __make_ref(0);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference back() {return __make_ref(__size_ - 1);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference back() const {return __make_ref(__size_ - 1);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void push_back(const value_type& __x); #if _LIBCPP_STD_VER > 11 template #if _LIBCPP_STD_VER > 14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference emplace_back(_Args&&... __args) #else _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args) #endif { push_back ( value_type ( std::forward<_Args>(__args)... )); #if _LIBCPP_STD_VER > 14 return this->back(); #endif } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back() {--__size_;} #if _LIBCPP_STD_VER > 11 template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator emplace(const_iterator __position, _Args&&... __args) { return insert ( __position, value_type ( std::forward<_Args>(__args)... )); } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __position, const value_type& __x); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __position, size_type __n, const value_type& __x); template typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, iterator >::type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 insert(const_iterator __position, _InputIterator __first, _InputIterator __last); template typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, iterator >::type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __position, initializer_list __il) {return insert(__position, __il.begin(), __il.end());} #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator erase(const_iterator __position); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator erase(const_iterator __first, const_iterator __last); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void clear() _NOEXCEPT {__size_ = 0;} _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(vector&) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT; #else _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable::value); #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void swap(reference __x, reference __y) _NOEXCEPT { std::swap(__x, __y); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void resize(size_type __sz, value_type __x = false); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void flip() _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __invariants() const; private: _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_length_error() const { std::__throw_length_error("vector"); } _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { std::__throw_out_of_range("vector"); } // Allocate space for __n objects // throws length_error if __n > max_size() // throws (probably bad_alloc) if memory run out // Precondition: __begin_ == __end_ == __cap() == 0 // Precondition: __n > 0 // Postcondition: capacity() >= __n // Postcondition: size() == 0 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __vallocate(size_type __n) { if (__n > max_size()) __throw_length_error(); auto __allocation = std::__allocate_at_least(__alloc(), __external_cap_to_internal(__n)); __begin_ = __allocation.ptr; __size_ = 0; __cap() = __allocation.count; if (__libcpp_is_constant_evaluated()) { for (size_type __i = 0; __i != __cap(); ++__i) std::__construct_at(std::__to_address(__begin_) + __i); } } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __vdeallocate() _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type __align_it(size_type __new_size) _NOEXCEPT {return (__new_size + (__bits_per_word-1)) & ~((size_type)__bits_per_word-1);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __recommend(size_type __new_size) const; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_at_end(size_type __n, bool __x); template typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, void >::type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __append(size_type __n, const_reference __x); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference __make_ref(size_type __pos) _NOEXCEPT {return reference(__begin_ + __pos / __bits_per_word, __storage_type(1) << __pos % __bits_per_word);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference __make_ref(size_type __pos) const _NOEXCEPT { return __bit_const_reference(__begin_ + __pos / __bits_per_word, __storage_type(1) << __pos % __bits_per_word); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator __make_iter(size_type __pos) _NOEXCEPT {return iterator(__begin_ + __pos / __bits_per_word, static_cast(__pos % __bits_per_word));} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator __make_iter(size_type __pos) const _NOEXCEPT {return const_iterator(__begin_ + __pos / __bits_per_word, static_cast(__pos % __bits_per_word));} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator __const_iterator_cast(const_iterator __p) _NOEXCEPT {return begin() + (__p - cbegin());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const vector& __v) {__copy_assign_alloc(__v, integral_constant());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const vector& __c, true_type) { if (__alloc() != __c.__alloc()) __vdeallocate(); __alloc() = __c.__alloc(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const vector&, false_type) {} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign(vector& __c, false_type); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(vector& __c) _NOEXCEPT_( !__storage_traits::propagate_on_container_move_assignment::value || is_nothrow_move_assignable::value) {__move_assign_alloc(__c, integral_constant());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { __alloc() = std::move(__c.__alloc()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(vector&, false_type) _NOEXCEPT {} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_t __hash_code() const _NOEXCEPT; friend class __bit_reference; friend class __bit_const_reference; friend class __bit_iterator; friend class __bit_iterator; friend struct __bit_array; friend struct _LIBCPP_TEMPLATE_VIS hash; }; template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::__vdeallocate() _NOEXCEPT { if (this->__begin_ != nullptr) { __storage_traits::deallocate(this->__alloc(), this->__begin_, __cap()); std::__debug_db_invalidate_all(this); this->__begin_ = nullptr; this->__size_ = this->__cap() = 0; } } template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector::size_type vector::max_size() const _NOEXCEPT { size_type __amax = __storage_traits::max_size(__alloc()); size_type __nmax = numeric_limits::max() / 2; // end() >= begin(), always if (__nmax / __bits_per_word <= __amax) return __nmax; return __internal_cap_to_external(__amax); } // Precondition: __new_size > capacity() template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector::size_type vector::__recommend(size_type __new_size) const { const size_type __ms = max_size(); if (__new_size > __ms) this->__throw_length_error(); const size_type __cap = capacity(); if (__cap >= __ms / 2) return __ms; return std::max(2 * __cap, __align_it(__new_size)); } // Default constructs __n objects starting at __end_ // Precondition: __n > 0 // Precondition: size() + __n <= capacity() // Postcondition: size() == size() + __n template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::__construct_at_end(size_type __n, bool __x) { size_type __old_size = this->__size_; this->__size_ += __n; if (__old_size == 0 || ((__old_size - 1) / __bits_per_word) != ((this->__size_ - 1) / __bits_per_word)) { if (this->__size_ <= __bits_per_word) this->__begin_[0] = __storage_type(0); else this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0); } std::fill_n(__make_iter(__old_size), __n, __x); } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, void >::type vector::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) { size_type __old_size = this->__size_; this->__size_ += std::distance(__first, __last); if (__old_size == 0 || ((__old_size - 1) / __bits_per_word) != ((this->__size_ - 1) / __bits_per_word)) { if (this->__size_ <= __bits_per_word) this->__begin_[0] = __storage_type(0); else this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0); } std::copy(__first, __last, __make_iter(__old_size)); } template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector() _NOEXCEPT_(is_nothrow_default_constructible::value) : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) { } template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_copy_constructible::value) #else _NOEXCEPT #endif : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) { } template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(size_type __n) : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) { if (__n > 0) { __vallocate(__n); __construct_at_end(__n, false); } } #if _LIBCPP_STD_VER > 11 template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(size_type __n, const allocator_type& __a) : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) { if (__n > 0) { __vallocate(__n); __construct_at_end(__n, false); } } #endif template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(size_type __n, const value_type& __x) : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) { if (__n > 0) { __vallocate(__n); __construct_at_end(__n, __x); } } template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(size_type __n, const value_type& __x, const allocator_type& __a) : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) { if (__n > 0) { __vallocate(__n); __construct_at_end(__n, __x); } } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(_InputIterator __first, _InputIterator __last, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type*) : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) { #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS for (; __first != __last; ++__first) push_back(*__first); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { if (__begin_ != nullptr) __storage_traits::deallocate(__alloc(), __begin_, __cap()); std::__debug_db_invalidate_all(this); throw; } #endif // _LIBCPP_NO_EXCEPTIONS } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type*) : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) { #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS for (; __first != __last; ++__first) push_back(*__first); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { if (__begin_ != nullptr) __storage_traits::deallocate(__alloc(), __begin_, __cap()); std::__debug_db_invalidate_all(this); throw; } #endif // _LIBCPP_NO_EXCEPTIONS } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(_ForwardIterator __first, _ForwardIterator __last, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type*) : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) { __vallocate(__n); __construct_at_end(__first, __last); } __guard.__complete(); } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type*) : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) { __vallocate(__n); __construct_at_end(__first, __last); } __guard.__complete(); } #ifndef _LIBCPP_CXX03_LANG template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(initializer_list __il) : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) { size_type __n = static_cast(__il.size()); if (__n > 0) { __vallocate(__n); __construct_at_end(__il.begin(), __il.end()); } } template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(initializer_list __il, const allocator_type& __a) : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) { size_type __n = static_cast(__il.size()); if (__n > 0) { __vallocate(__n); __construct_at_end(__il.begin(), __il.end()); } } #endif // _LIBCPP_CXX03_LANG template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(const vector& __v) : __begin_(nullptr), __size_(0), __cap_alloc_(0, __storage_traits::select_on_container_copy_construction(__v.__alloc())) { if (__v.size() > 0) { __vallocate(__v.size()); __construct_at_end(__v.begin(), __v.end()); } } template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(const vector& __v, const allocator_type& __a) : __begin_(nullptr), __size_(0), __cap_alloc_(0, __a) { if (__v.size() > 0) { __vallocate(__v.size()); __construct_at_end(__v.begin(), __v.end()); } } template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector& vector::operator=(const vector& __v) { if (this != std::addressof(__v)) { __copy_assign_alloc(__v); if (__v.__size_) { if (__v.__size_ > capacity()) { __vdeallocate(); __vallocate(__v.__size_); } std::copy(__v.__begin_, __v.__begin_ + __external_cap_to_internal(__v.__size_), __begin_); } __size_ = __v.__size_; } return *this; } template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(vector&& __v) #if _LIBCPP_STD_VER > 14 _NOEXCEPT #else _NOEXCEPT_(is_nothrow_move_constructible::value) #endif : __begin_(__v.__begin_), __size_(__v.__size_), __cap_alloc_(std::move(__v.__cap_alloc_)) { __v.__begin_ = nullptr; __v.__size_ = 0; __v.__cap() = 0; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(vector&& __v, const __type_identity_t& __a) : __begin_(nullptr), __size_(0), __cap_alloc_(0, __a) { if (__a == allocator_type(__v.__alloc())) { this->__begin_ = __v.__begin_; this->__size_ = __v.__size_; this->__cap() = __v.__cap(); __v.__begin_ = nullptr; __v.__cap() = __v.__size_ = 0; } else if (__v.size() > 0) { __vallocate(__v.size()); __construct_at_end(__v.begin(), __v.end()); } } template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector& vector::operator=(vector&& __v) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) { __move_assign(__v, integral_constant()); return *this; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::__move_assign(vector& __c, false_type) { if (__alloc() != __c.__alloc()) assign(__c.begin(), __c.end()); else __move_assign(__c, true_type()); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::__move_assign(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { __vdeallocate(); __move_assign_alloc(__c); this->__begin_ = __c.__begin_; this->__size_ = __c.__size_; this->__cap() = __c.__cap(); __c.__begin_ = nullptr; __c.__cap() = __c.__size_ = 0; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::assign(size_type __n, const value_type& __x) { __size_ = 0; if (__n > 0) { size_type __c = capacity(); if (__n <= __c) __size_ = __n; else { vector __v(get_allocator()); __v.reserve(__recommend(__n)); __v.__size_ = __n; swap(__v); } std::fill_n(begin(), __n, __x); } std::__debug_db_invalidate_all(this); } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, void >::type vector::assign(_InputIterator __first, _InputIterator __last) { clear(); for (; __first != __last; ++__first) push_back(*__first); } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, void >::type vector::assign(_ForwardIterator __first, _ForwardIterator __last) { clear(); difference_type __ns = std::distance(__first, __last); _LIBCPP_ASSERT(__ns >= 0, "invalid range specified"); const size_t __n = static_cast(__ns); if (__n) { if (__n > capacity()) { __vdeallocate(); __vallocate(__n); } __construct_at_end(__first, __last); } } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::reserve(size_type __n) { if (__n > capacity()) { if (__n > max_size()) this->__throw_length_error(); vector __v(this->get_allocator()); __v.__vallocate(__n); __v.__construct_at_end(this->begin(), this->end()); swap(__v); std::__debug_db_invalidate_all(this); } } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::shrink_to_fit() _NOEXCEPT { if (__external_cap_to_internal(size()) > __cap()) { #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS vector(*this, allocator_type(__alloc())).swap(*this); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { } #endif // _LIBCPP_NO_EXCEPTIONS } } template typename vector::reference vector::at(size_type __n) { if (__n >= size()) this->__throw_out_of_range(); return (*this)[__n]; } template typename vector::const_reference vector::at(size_type __n) const { if (__n >= size()) this->__throw_out_of_range(); return (*this)[__n]; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::push_back(const value_type& __x) { if (this->__size_ == this->capacity()) reserve(__recommend(this->__size_ + 1)); ++this->__size_; back() = __x; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector::iterator vector::insert(const_iterator __position, const value_type& __x) { iterator __r; if (size() < capacity()) { const_iterator __old_end = end(); ++__size_; std::copy_backward(__position, __old_end, end()); __r = __const_iterator_cast(__position); } else { vector __v(get_allocator()); __v.reserve(__recommend(__size_ + 1)); __v.__size_ = __size_ + 1; __r = std::copy(cbegin(), __position, __v.begin()); std::copy_backward(__position, cend(), __v.end()); swap(__v); } *__r = __x; return __r; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector::iterator vector::insert(const_iterator __position, size_type __n, const value_type& __x) { iterator __r; size_type __c = capacity(); if (__n <= __c && size() <= __c - __n) { const_iterator __old_end = end(); __size_ += __n; std::copy_backward(__position, __old_end, end()); __r = __const_iterator_cast(__position); } else { vector __v(get_allocator()); __v.reserve(__recommend(__size_ + __n)); __v.__size_ = __size_ + __n; __r = std::copy(cbegin(), __position, __v.begin()); std::copy_backward(__position, cend(), __v.end()); swap(__v); } std::fill_n(__r, __n, __x); return __r; } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, typename vector::iterator >::type vector::insert(const_iterator __position, _InputIterator __first, _InputIterator __last) { difference_type __off = __position - begin(); iterator __p = __const_iterator_cast(__position); iterator __old_end = end(); for (; size() != capacity() && __first != __last; ++__first) { ++this->__size_; back() = *__first; } vector __v(get_allocator()); if (__first != __last) { #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS __v.assign(__first, __last); difference_type __old_size = static_cast(__old_end - begin()); difference_type __old_p = __p - begin(); reserve(__recommend(size() + __v.size())); __p = begin() + __old_p; __old_end = begin() + __old_size; #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { erase(__old_end, end()); throw; } #endif // _LIBCPP_NO_EXCEPTIONS } __p = std::rotate(__p, __old_end, end()); insert(__p, __v.begin(), __v.end()); return begin() + __off; } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, typename vector::iterator >::type vector::insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last) { const difference_type __n_signed = std::distance(__first, __last); _LIBCPP_ASSERT(__n_signed >= 0, "invalid range specified"); const size_type __n = static_cast(__n_signed); iterator __r; size_type __c = capacity(); if (__n <= __c && size() <= __c - __n) { const_iterator __old_end = end(); __size_ += __n; std::copy_backward(__position, __old_end, end()); __r = __const_iterator_cast(__position); } else { vector __v(get_allocator()); __v.reserve(__recommend(__size_ + __n)); __v.__size_ = __size_ + __n; __r = std::copy(cbegin(), __position, __v.begin()); std::copy_backward(__position, cend(), __v.end()); swap(__v); } std::copy(__first, __last, __r); return __r; } template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector::iterator vector::erase(const_iterator __position) { iterator __r = __const_iterator_cast(__position); std::copy(__position + 1, this->cend(), __r); --__size_; return __r; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector::iterator vector::erase(const_iterator __first, const_iterator __last) { iterator __r = __const_iterator_cast(__first); difference_type __d = __last - __first; std::copy(__last, this->cend(), __r); __size_ -= __d; return __r; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::swap(vector& __x) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT #else _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable::value) #endif { std::swap(this->__begin_, __x.__begin_); std::swap(this->__size_, __x.__size_); std::swap(this->__cap(), __x.__cap()); std::__swap_allocator(this->__alloc(), __x.__alloc(), integral_constant()); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::resize(size_type __sz, value_type __x) { size_type __cs = size(); if (__cs < __sz) { iterator __r; size_type __c = capacity(); size_type __n = __sz - __cs; if (__n <= __c && __cs <= __c - __n) { __r = end(); __size_ += __n; } else { vector __v(get_allocator()); __v.reserve(__recommend(__size_ + __n)); __v.__size_ = __size_ + __n; __r = std::copy(cbegin(), cend(), __v.begin()); swap(__v); } std::fill_n(__r, __n, __x); } else __size_ = __sz; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::flip() _NOEXCEPT { // do middle whole words size_type __n = __size_; __storage_pointer __p = __begin_; for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word) *__p = ~*__p; // do last partial word if (__n > 0) { __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); __storage_type __b = *__p & __m; *__p &= ~__m; *__p |= ~__b & __m; } } template _LIBCPP_CONSTEXPR_SINCE_CXX20 bool vector::__invariants() const { if (this->__begin_ == nullptr) { if (this->__size_ != 0 || this->__cap() != 0) return false; } else { if (this->__cap() == 0) return false; if (this->__size_ > this->capacity()) return false; } return true; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 size_t vector::__hash_code() const _NOEXCEPT { size_t __h = 0; // do middle whole words size_type __n = __size_; __storage_pointer __p = __begin_; for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word) __h ^= *__p; // do last partial word if (__n > 0) { const __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); __h ^= *__p & __m; } return __h; } template struct _LIBCPP_TEMPLATE_VIS hash > : public __unary_function, size_t> { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_t operator()(const vector& __vec) const _NOEXCEPT {return __vec.__hash_code();} }; template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator==(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) { const typename vector<_Tp, _Allocator>::size_type __sz = __x.size(); return __sz == __y.size() && std::equal(__x.begin(), __x.end(), __y.begin()); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) { return !(__x == __y); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator< (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) { return std::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end()); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator> (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) { return __y < __x; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) { return !(__x < __y); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) { return !(__y < __x); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void swap(vector<_Tp, _Allocator>& __x, vector<_Tp, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } #if _LIBCPP_STD_VER > 17 template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::size_type erase(vector<_Tp, _Allocator>& __c, const _Up& __v) { auto __old_size = __c.size(); __c.erase(std::remove(__c.begin(), __c.end(), __v), __c.end()); return __old_size - __c.size(); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::size_type erase_if(vector<_Tp, _Allocator>& __c, _Predicate __pred) { auto __old_size = __c.size(); __c.erase(std::remove_if(__c.begin(), __c.end(), __pred), __c.end()); return __old_size - __c.size(); } template <> inline constexpr bool __format::__enable_insertable> = true; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> inline constexpr bool __format::__enable_insertable> = true; #endif #endif // _LIBCPP_STD_VER > 17 #if _LIBCPP_STD_VER > 20 template // Since is-vector-bool-reference is only used once it's inlined here. requires same_as> struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_Tp, CharT> { private: formatter __underlying_; public: template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { return __underlying_.parse(__ctx); } template _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const _Tp& __ref, _FormatContext& __ctx) const { return __underlying_.format(__ref, __ctx); } }; #endif // _LIBCPP_STD_VER > 20 _LIBCPP_END_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 _LIBCPP_BEGIN_NAMESPACE_STD namespace pmr { template using vector = std::vector<_ValueT, polymorphic_allocator<_ValueT>>; } // namespace pmr _LIBCPP_END_NAMESPACE_STD #endif _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include # include # include # include # include #endif #endif // _LIBCPP_VECTOR // -*- C++ -*- //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_UNORDERED_MAP #define _LIBCPP_UNORDERED_MAP /* unordered_map synopsis #include namespace std { template , class Pred = equal_to, class Alloc = allocator>> class unordered_map { public: // types typedef Key key_type; typedef T mapped_type; typedef Hash hasher; typedef Pred key_equal; typedef Alloc allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename allocator_traits::pointer pointer; typedef typename allocator_traits::const_pointer const_pointer; typedef typename allocator_traits::size_type size_type; typedef typename allocator_traits::difference_type difference_type; typedef /unspecified/ iterator; typedef /unspecified/ const_iterator; typedef /unspecified/ local_iterator; typedef /unspecified/ const_local_iterator; typedef unspecified node_type; // C++17 typedef INSERT_RETURN_TYPE insert_return_type; // C++17 unordered_map() noexcept( is_nothrow_default_constructible::value && is_nothrow_default_constructible::value && is_nothrow_default_constructible::value); explicit unordered_map(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template unordered_map(InputIterator f, InputIterator l, size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); explicit unordered_map(const allocator_type&); unordered_map(const unordered_map&); unordered_map(const unordered_map&, const Allocator&); unordered_map(unordered_map&&) noexcept( is_nothrow_move_constructible::value && is_nothrow_move_constructible::value && is_nothrow_move_constructible::value); unordered_map(unordered_map&&, const Allocator&); unordered_map(initializer_list, size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_map(size_type n, const allocator_type& a) : unordered_map(n, hasher(), key_equal(), a) {} // C++14 unordered_map(size_type n, const hasher& hf, const allocator_type& a) : unordered_map(n, hf, key_equal(), a) {} // C++14 template unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a) : unordered_map(f, l, n, hasher(), key_equal(), a) {} // C++14 template unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_map(f, l, n, hf, key_equal(), a) {} // C++14 unordered_map(initializer_list il, size_type n, const allocator_type& a) : unordered_map(il, n, hasher(), key_equal(), a) {} // C++14 unordered_map(initializer_list il, size_type n, const hasher& hf, const allocator_type& a) : unordered_map(il, n, hf, key_equal(), a) {} // C++14 ~unordered_map(); unordered_map& operator=(const unordered_map&); unordered_map& operator=(unordered_map&&) noexcept( allocator_type::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable::value); unordered_map& operator=(initializer_list); allocator_type get_allocator() const noexcept; bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; iterator begin() noexcept; iterator end() noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; template pair emplace(Args&&... args); template iterator emplace_hint(const_iterator position, Args&&... args); pair insert(const value_type& obj); template pair insert(P&& obj); iterator insert(const_iterator hint, const value_type& obj); template iterator insert(const_iterator hint, P&& obj); template void insert(InputIterator first, InputIterator last); void insert(initializer_list); node_type extract(const_iterator position); // C++17 node_type extract(const key_type& x); // C++17 insert_return_type insert(node_type&& nh); // C++17 iterator insert(const_iterator hint, node_type&& nh); // C++17 template pair try_emplace(const key_type& k, Args&&... args); // C++17 template pair try_emplace(key_type&& k, Args&&... args); // C++17 template iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); // C++17 template iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); // C++17 template pair insert_or_assign(const key_type& k, M&& obj); // C++17 template pair insert_or_assign(key_type&& k, M&& obj); // C++17 template iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); // C++17 template iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); // C++17 iterator erase(const_iterator position); iterator erase(iterator position); // C++14 size_type erase(const key_type& k); iterator erase(const_iterator first, const_iterator last); void clear() noexcept; template void merge(unordered_map& source); // C++17 template void merge(unordered_map&& source); // C++17 template void merge(unordered_multimap& source); // C++17 template void merge(unordered_multimap&& source); // C++17 void swap(unordered_map&) noexcept( (!allocator_type::propagate_on_container_swap::value || __is_nothrow_swappable::value) && __is_nothrow_swappable::value && __is_nothrow_swappable::value); hasher hash_function() const; key_equal key_eq() const; iterator find(const key_type& k); const_iterator find(const key_type& k) const; template iterator find(const K& x); // C++20 template const_iterator find(const K& x) const; // C++20 size_type count(const key_type& k) const; template size_type count(const K& k) const; // C++20 bool contains(const key_type& k) const; // C++20 template bool contains(const K& k) const; // C++20 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; template pair equal_range(const K& k); // C++20 template pair equal_range(const K& k) const; // C++20 mapped_type& operator[](const key_type& k); mapped_type& operator[](key_type&& k); mapped_type& at(const key_type& k); const mapped_type& at(const key_type& k) const; size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; size_type bucket_size(size_type n) const; size_type bucket(const key_type& k) const; local_iterator begin(size_type n); local_iterator end(size_type n); const_local_iterator begin(size_type n) const; const_local_iterator end(size_type n) const; const_local_iterator cbegin(size_type n) const; const_local_iterator cend(size_type n) const; float load_factor() const noexcept; float max_load_factor() const noexcept; void max_load_factor(float z); void rehash(size_type n); void reserve(size_type n); }; template>, class Pred = equal_to>, class Allocator = allocator>> unordered_map(InputIterator, InputIterator, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_map, iter_value_t, Hash, Pred, Allocator>; // C++17 template, class Pred = equal_to, class Allocator = allocator>> unordered_map(initializer_list>, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_map; // C++17 template unordered_map(InputIterator, InputIterator, typename see below::size_type, Allocator) -> unordered_map, iter_val_t, hash>, equal_to>, Allocator>; // C++17 template unordered_map(InputIterator, InputIterator, Allocator) -> unordered_map, iter_val_t, hash>, equal_to>, Allocator>; // C++17 template unordered_map(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator) -> unordered_map, iter_val_t, Hash, equal_to>, Allocator>; // C++17 template unordered_map(initializer_list>, typename see below::size_type, Allocator) -> unordered_map, equal_to, Allocator>; // C++17 template unordered_map(initializer_list>, Allocator) -> unordered_map, equal_to, Allocator>; // C++17 template unordered_map(initializer_list>, typename see below::size_type, Hash, Allocator) -> unordered_map, Allocator>; // C++17 template void swap(unordered_map& x, unordered_map& y) noexcept(noexcept(x.swap(y))); template bool operator==(const unordered_map& x, const unordered_map& y); template bool operator!=(const unordered_map& x, const unordered_map& y); template , class Pred = equal_to, class Alloc = allocator>> class unordered_multimap { public: // types typedef Key key_type; typedef T mapped_type; typedef Hash hasher; typedef Pred key_equal; typedef Alloc allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename allocator_traits::pointer pointer; typedef typename allocator_traits::const_pointer const_pointer; typedef typename allocator_traits::size_type size_type; typedef typename allocator_traits::difference_type difference_type; typedef /unspecified/ iterator; typedef /unspecified/ const_iterator; typedef /unspecified/ local_iterator; typedef /unspecified/ const_local_iterator; typedef unspecified node_type; // C++17 unordered_multimap() noexcept( is_nothrow_default_constructible::value && is_nothrow_default_constructible::value && is_nothrow_default_constructible::value); explicit unordered_multimap(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template unordered_multimap(InputIterator f, InputIterator l, size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); explicit unordered_multimap(const allocator_type&); unordered_multimap(const unordered_multimap&); unordered_multimap(const unordered_multimap&, const Allocator&); unordered_multimap(unordered_multimap&&) noexcept( is_nothrow_move_constructible::value && is_nothrow_move_constructible::value && is_nothrow_move_constructible::value); unordered_multimap(unordered_multimap&&, const Allocator&); unordered_multimap(initializer_list, size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_multimap(size_type n, const allocator_type& a) : unordered_multimap(n, hasher(), key_equal(), a) {} // C++14 unordered_multimap(size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(n, hf, key_equal(), a) {} // C++14 template unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a) : unordered_multimap(f, l, n, hasher(), key_equal(), a) {} // C++14 template unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(f, l, n, hf, key_equal(), a) {} // C++14 unordered_multimap(initializer_list il, size_type n, const allocator_type& a) : unordered_multimap(il, n, hasher(), key_equal(), a) {} // C++14 unordered_multimap(initializer_list il, size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(il, n, hf, key_equal(), a) {} // C++14 ~unordered_multimap(); unordered_multimap& operator=(const unordered_multimap&); unordered_multimap& operator=(unordered_multimap&&) noexcept( allocator_type::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable::value); unordered_multimap& operator=(initializer_list); allocator_type get_allocator() const noexcept; bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; iterator begin() noexcept; iterator end() noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; template iterator emplace(Args&&... args); template iterator emplace_hint(const_iterator position, Args&&... args); iterator insert(const value_type& obj); template iterator insert(P&& obj); iterator insert(const_iterator hint, const value_type& obj); template iterator insert(const_iterator hint, P&& obj); template void insert(InputIterator first, InputIterator last); void insert(initializer_list); node_type extract(const_iterator position); // C++17 node_type extract(const key_type& x); // C++17 iterator insert(node_type&& nh); // C++17 iterator insert(const_iterator hint, node_type&& nh); // C++17 iterator erase(const_iterator position); iterator erase(iterator position); // C++14 size_type erase(const key_type& k); iterator erase(const_iterator first, const_iterator last); void clear() noexcept; template void merge(unordered_multimap& source); // C++17 template void merge(unordered_multimap&& source); // C++17 template void merge(unordered_map& source); // C++17 template void merge(unordered_map&& source); // C++17 void swap(unordered_multimap&) noexcept( (!allocator_type::propagate_on_container_swap::value || __is_nothrow_swappable::value) && __is_nothrow_swappable::value && __is_nothrow_swappable::value); hasher hash_function() const; key_equal key_eq() const; iterator find(const key_type& k); const_iterator find(const key_type& k) const; template iterator find(const K& x); // C++20 template const_iterator find(const K& x) const; // C++20 size_type count(const key_type& k) const; template size_type count(const K& k) const; // C++20 bool contains(const key_type& k) const; // C++20 template bool contains(const K& k) const; // C++20 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; template pair equal_range(const K& k); // C++20 template pair equal_range(const K& k) const; // C++20 size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; size_type bucket_size(size_type n) const; size_type bucket(const key_type& k) const; local_iterator begin(size_type n); local_iterator end(size_type n); const_local_iterator begin(size_type n) const; const_local_iterator end(size_type n) const; const_local_iterator cbegin(size_type n) const; const_local_iterator cend(size_type n) const; float load_factor() const noexcept; float max_load_factor() const noexcept; void max_load_factor(float z); void rehash(size_type n); void reserve(size_type n); }; template>, class Pred = equal_to>, class Allocator = allocator>> unordered_multimap(InputIterator, InputIterator, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_multimap, iter_value_t, Hash, Pred, Allocator>; // C++17 template, class Pred = equal_to, class Allocator = allocator>> unordered_multimap(initializer_list>, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_multimap; // C++17 template unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Allocator) -> unordered_multimap, iter_val_t, hash>, equal_to>, Allocator>; // C++17 template unordered_multimap(InputIterator, InputIterator, Allocator) -> unordered_multimap, iter_val_t, hash>, equal_to>, Allocator>; // C++17 template unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator) -> unordered_multimap, iter_val_t, Hash, equal_to>, Allocator>; // C++17 template unordered_multimap(initializer_list>, typename see below::size_type, Allocator) -> unordered_multimap, equal_to, Allocator>; // C++17 template unordered_multimap(initializer_list>, Allocator) -> unordered_multimap, equal_to, Allocator>; // C++17 template unordered_multimap(initializer_list>, typename see below::size_type, Hash, Allocator) -> unordered_multimap, Allocator>; // C++17 template void swap(unordered_multimap& x, unordered_multimap& y) noexcept(noexcept(x.swap(y))); template typename unordered_map::size_type erase_if(unordered_map& c, Predicate pred); // C++20 template typename unordered_multimap::size_type erase_if(unordered_multimap& c, Predicate pred); // C++20 template bool operator==(const unordered_multimap& x, const unordered_multimap& y); template bool operator!=(const unordered_multimap& x, const unordered_multimap& y); } // std */ #include <__algorithm/is_permutation.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> #include <__debug> #include <__functional/is_transparent.h> #include <__functional/operations.h> #include <__hash_table> #include <__iterator/distance.h> #include <__iterator/erase_if_container.h> #include <__iterator/iterator_traits.h> #include <__memory/addressof.h> #include <__memory/allocator.h> #include <__memory_resource/polymorphic_allocator.h> #include <__node_handle> #include <__type_traits/is_allocator.h> #include <__utility/forward.h> #include #include #include // standard-mandated includes // [iterator.range] #include <__iterator/access.h> #include <__iterator/data.h> #include <__iterator/empty.h> #include <__iterator/reverse_access.h> #include <__iterator/size.h> // [unord.map.syn] #include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif _LIBCPP_BEGIN_NAMESPACE_STD template ::value && !__libcpp_is_final<_Hash>::value> class __unordered_map_hasher : private _Hash { public: _LIBCPP_INLINE_VISIBILITY __unordered_map_hasher() _NOEXCEPT_(is_nothrow_default_constructible<_Hash>::value) : _Hash() {} _LIBCPP_INLINE_VISIBILITY __unordered_map_hasher(const _Hash& __h) _NOEXCEPT_(is_nothrow_copy_constructible<_Hash>::value) : _Hash(__h) {} _LIBCPP_INLINE_VISIBILITY const _Hash& hash_function() const _NOEXCEPT {return *this;} _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Cp& __x) const {return static_cast(*this)(__x.__get_value().first);} _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Key& __x) const {return static_cast(*this)(__x);} #if _LIBCPP_STD_VER > 17 template _LIBCPP_INLINE_VISIBILITY size_t operator()(const _K2& __x) const {return static_cast(*this)(__x);} #endif _LIBCPP_INLINE_VISIBILITY void swap(__unordered_map_hasher& __y) _NOEXCEPT_(__is_nothrow_swappable<_Hash>::value) { using _VSTD::swap; swap(static_cast<_Hash&>(*this), static_cast<_Hash&>(__y)); } }; template class __unordered_map_hasher<_Key, _Cp, _Hash, _Pred, false> { _Hash __hash_; public: _LIBCPP_INLINE_VISIBILITY __unordered_map_hasher() _NOEXCEPT_(is_nothrow_default_constructible<_Hash>::value) : __hash_() {} _LIBCPP_INLINE_VISIBILITY __unordered_map_hasher(const _Hash& __h) _NOEXCEPT_(is_nothrow_copy_constructible<_Hash>::value) : __hash_(__h) {} _LIBCPP_INLINE_VISIBILITY const _Hash& hash_function() const _NOEXCEPT {return __hash_;} _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Cp& __x) const {return __hash_(__x.__get_value().first);} _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Key& __x) const {return __hash_(__x);} #if _LIBCPP_STD_VER > 17 template _LIBCPP_INLINE_VISIBILITY size_t operator()(const _K2& __x) const {return __hash_(__x);} #endif _LIBCPP_INLINE_VISIBILITY void swap(__unordered_map_hasher& __y) _NOEXCEPT_(__is_nothrow_swappable<_Hash>::value) { using _VSTD::swap; swap(__hash_, __y.__hash_); } }; template inline _LIBCPP_INLINE_VISIBILITY void swap(__unordered_map_hasher<_Key, _Cp, _Hash, _Pred, __b>& __x, __unordered_map_hasher<_Key, _Cp, _Hash, _Pred, __b>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } template ::value && !__libcpp_is_final<_Pred>::value> class __unordered_map_equal : private _Pred { public: _LIBCPP_INLINE_VISIBILITY __unordered_map_equal() _NOEXCEPT_(is_nothrow_default_constructible<_Pred>::value) : _Pred() {} _LIBCPP_INLINE_VISIBILITY __unordered_map_equal(const _Pred& __p) _NOEXCEPT_(is_nothrow_copy_constructible<_Pred>::value) : _Pred(__p) {} _LIBCPP_INLINE_VISIBILITY const _Pred& key_eq() const _NOEXCEPT {return *this;} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Cp& __x, const _Cp& __y) const {return static_cast(*this)(__x.__get_value().first, __y.__get_value().first);} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Cp& __x, const _Key& __y) const {return static_cast(*this)(__x.__get_value().first, __y);} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _Cp& __y) const {return static_cast(*this)(__x, __y.__get_value().first);} #if _LIBCPP_STD_VER > 17 template _LIBCPP_INLINE_VISIBILITY bool operator()(const _Cp& __x, const _K2& __y) const {return static_cast(*this)(__x.__get_value().first, __y);} template _LIBCPP_INLINE_VISIBILITY bool operator()(const _K2& __x, const _Cp& __y) const {return static_cast(*this)(__x, __y.__get_value().first);} template _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _K2& __y) const {return static_cast(*this)(__x, __y);} template _LIBCPP_INLINE_VISIBILITY bool operator()(const _K2& __x, const _Key& __y) const {return static_cast(*this)(__x, __y);} #endif _LIBCPP_INLINE_VISIBILITY void swap(__unordered_map_equal& __y) _NOEXCEPT_(__is_nothrow_swappable<_Pred>::value) { using _VSTD::swap; swap(static_cast<_Pred&>(*this), static_cast<_Pred&>(__y)); } }; template class __unordered_map_equal<_Key, _Cp, _Pred, _Hash, false> { _Pred __pred_; public: _LIBCPP_INLINE_VISIBILITY __unordered_map_equal() _NOEXCEPT_(is_nothrow_default_constructible<_Pred>::value) : __pred_() {} _LIBCPP_INLINE_VISIBILITY __unordered_map_equal(const _Pred& __p) _NOEXCEPT_(is_nothrow_copy_constructible<_Pred>::value) : __pred_(__p) {} _LIBCPP_INLINE_VISIBILITY const _Pred& key_eq() const _NOEXCEPT {return __pred_;} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Cp& __x, const _Cp& __y) const {return __pred_(__x.__get_value().first, __y.__get_value().first);} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Cp& __x, const _Key& __y) const {return __pred_(__x.__get_value().first, __y);} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _Cp& __y) const {return __pred_(__x, __y.__get_value().first);} #if _LIBCPP_STD_VER > 17 template _LIBCPP_INLINE_VISIBILITY bool operator()(const _Cp& __x, const _K2& __y) const {return __pred_(__x.__get_value().first, __y);} template _LIBCPP_INLINE_VISIBILITY bool operator()(const _K2& __x, const _Cp& __y) const {return __pred_(__x, __y.__get_value().first);} template _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _K2& __y) const {return __pred_(__x, __y);} template _LIBCPP_INLINE_VISIBILITY bool operator()(const _K2& __x, const _Key& __y) const {return __pred_(__x, __y);} #endif _LIBCPP_INLINE_VISIBILITY void swap(__unordered_map_equal& __y) _NOEXCEPT_(__is_nothrow_swappable<_Pred>::value) { using _VSTD::swap; swap(__pred_, __y.__pred_); } }; template inline _LIBCPP_INLINE_VISIBILITY void swap(__unordered_map_equal<_Key, _Cp, _Pred, _Hash, __b>& __x, __unordered_map_equal<_Key, _Cp, _Pred, _Hash, __b>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } template class __hash_map_node_destructor { typedef _Alloc allocator_type; typedef allocator_traits __alloc_traits; public: typedef typename __alloc_traits::pointer pointer; private: allocator_type& __na_; __hash_map_node_destructor& operator=(const __hash_map_node_destructor&); public: bool __first_constructed; bool __second_constructed; _LIBCPP_INLINE_VISIBILITY explicit __hash_map_node_destructor(allocator_type& __na) _NOEXCEPT : __na_(__na), __first_constructed(false), __second_constructed(false) {} #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY __hash_map_node_destructor(__hash_node_destructor&& __x) _NOEXCEPT : __na_(__x.__na_), __first_constructed(__x.__value_constructed), __second_constructed(__x.__value_constructed) { __x.__value_constructed = false; } #else // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY __hash_map_node_destructor(const __hash_node_destructor& __x) : __na_(__x.__na_), __first_constructed(__x.__value_constructed), __second_constructed(__x.__value_constructed) { const_cast(__x.__value_constructed) = false; } #endif // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY void operator()(pointer __p) _NOEXCEPT { if (__second_constructed) __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.__get_value().second)); if (__first_constructed) __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.__get_value().first)); if (__p) __alloc_traits::deallocate(__na_, __p, 1); } }; #ifndef _LIBCPP_CXX03_LANG template struct _LIBCPP_STANDALONE_DEBUG __hash_value_type { typedef _Key key_type; typedef _Tp mapped_type; typedef pair value_type; typedef pair __nc_ref_pair_type; typedef pair __nc_rref_pair_type; private: value_type __cc_; public: _LIBCPP_INLINE_VISIBILITY value_type& __get_value() { #if _LIBCPP_STD_VER > 14 return *_VSTD::launder(_VSTD::addressof(__cc_)); #else return __cc_; #endif } _LIBCPP_INLINE_VISIBILITY const value_type& __get_value() const { #if _LIBCPP_STD_VER > 14 return *_VSTD::launder(_VSTD::addressof(__cc_)); #else return __cc_; #endif } _LIBCPP_INLINE_VISIBILITY __nc_ref_pair_type __ref() { value_type& __v = __get_value(); return __nc_ref_pair_type(const_cast(__v.first), __v.second); } _LIBCPP_INLINE_VISIBILITY __nc_rref_pair_type __move() { value_type& __v = __get_value(); return __nc_rref_pair_type( _VSTD::move(const_cast(__v.first)), _VSTD::move(__v.second)); } _LIBCPP_INLINE_VISIBILITY __hash_value_type& operator=(const __hash_value_type& __v) { __ref() = __v.__get_value(); return *this; } _LIBCPP_INLINE_VISIBILITY __hash_value_type& operator=(__hash_value_type&& __v) { __ref() = __v.__move(); return *this; } template ::value> > _LIBCPP_INLINE_VISIBILITY __hash_value_type& operator=(_ValueTp&& __v) { __ref() = _VSTD::forward<_ValueTp>(__v); return *this; } private: __hash_value_type(const __hash_value_type& __v) = delete; __hash_value_type(__hash_value_type&& __v) = delete; template explicit __hash_value_type(_Args&& ...__args) = delete; ~__hash_value_type() = delete; }; #else template struct __hash_value_type { typedef _Key key_type; typedef _Tp mapped_type; typedef pair value_type; private: value_type __cc_; public: _LIBCPP_INLINE_VISIBILITY value_type& __get_value() { return __cc_; } _LIBCPP_INLINE_VISIBILITY const value_type& __get_value() const { return __cc_; } private: ~__hash_value_type(); }; #endif template class _LIBCPP_TEMPLATE_VIS __hash_map_iterator { _HashIterator __i_; typedef __hash_node_types_from_iterator<_HashIterator> _NodeTypes; public: typedef forward_iterator_tag iterator_category; typedef typename _NodeTypes::__map_value_type value_type; typedef typename _NodeTypes::difference_type difference_type; typedef value_type& reference; typedef typename _NodeTypes::__map_value_type_pointer pointer; _LIBCPP_INLINE_VISIBILITY __hash_map_iterator() _NOEXCEPT {} _LIBCPP_INLINE_VISIBILITY __hash_map_iterator(_HashIterator __i) _NOEXCEPT : __i_(__i) {} _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __i_->__get_value();} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return pointer_traits::pointer_to(__i_->__get_value());} _LIBCPP_INLINE_VISIBILITY __hash_map_iterator& operator++() {++__i_; return *this;} _LIBCPP_INLINE_VISIBILITY __hash_map_iterator operator++(int) { __hash_map_iterator __t(*this); ++(*this); return __t; } friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __hash_map_iterator& __x, const __hash_map_iterator& __y) {return __x.__i_ == __y.__i_;} friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __hash_map_iterator& __x, const __hash_map_iterator& __y) {return __x.__i_ != __y.__i_;} template friend class _LIBCPP_TEMPLATE_VIS unordered_map; template friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; template friend class _LIBCPP_TEMPLATE_VIS __hash_const_iterator; template friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator; template friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator; }; template class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator { _HashIterator __i_; typedef __hash_node_types_from_iterator<_HashIterator> _NodeTypes; public: typedef forward_iterator_tag iterator_category; typedef typename _NodeTypes::__map_value_type value_type; typedef typename _NodeTypes::difference_type difference_type; typedef const value_type& reference; typedef typename _NodeTypes::__const_map_value_type_pointer pointer; _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator() _NOEXCEPT {} _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator(_HashIterator __i) _NOEXCEPT : __i_(__i) {} _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator( __hash_map_iterator __i) _NOEXCEPT : __i_(__i.__i_) {} _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __i_->__get_value();} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return pointer_traits::pointer_to(__i_->__get_value());} _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator& operator++() {++__i_; return *this;} _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator operator++(int) { __hash_map_const_iterator __t(*this); ++(*this); return __t; } friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __hash_map_const_iterator& __x, const __hash_map_const_iterator& __y) {return __x.__i_ == __y.__i_;} friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __hash_map_const_iterator& __x, const __hash_map_const_iterator& __y) {return __x.__i_ != __y.__i_;} template friend class _LIBCPP_TEMPLATE_VIS unordered_map; template friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; template friend class _LIBCPP_TEMPLATE_VIS __hash_const_iterator; template friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator; }; template class unordered_multimap; template , class _Pred = equal_to<_Key>, class _Alloc = allocator > > class _LIBCPP_TEMPLATE_VIS unordered_map { public: // types typedef _Key key_type; typedef _Tp mapped_type; typedef __type_identity_t<_Hash> hasher; typedef __type_identity_t<_Pred> key_equal; typedef __type_identity_t<_Alloc> allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; static_assert((is_same::value), "Invalid allocator::value_type"); private: typedef __hash_value_type __value_type; typedef __unordered_map_hasher __hasher; typedef __unordered_map_equal __key_equal; typedef __rebind_alloc, __value_type> __allocator_type; typedef __hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table; __table __table_; typedef typename __table::_NodeTypes _NodeTypes; typedef typename __table::__node_pointer __node_pointer; typedef typename __table::__node_const_pointer __node_const_pointer; typedef typename __table::__node_traits __node_traits; typedef typename __table::__node_allocator __node_allocator; typedef typename __table::__node __node; typedef __hash_map_node_destructor<__node_allocator> _Dp; typedef unique_ptr<__node, _Dp> __node_holder; typedef allocator_traits __alloc_traits; static_assert(is_same >::value, "[allocator.requirements] states that rebinding an allocator to the same type should result in the " "original allocator"); static_assert((is_same::value), ""); static_assert((is_same::value), ""); public: typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; typedef typename __table::size_type size_type; typedef typename __table::difference_type difference_type; typedef __hash_map_iterator iterator; typedef __hash_map_const_iterator const_iterator; typedef __hash_map_iterator local_iterator; typedef __hash_map_const_iterator const_local_iterator; #if _LIBCPP_STD_VER > 14 typedef __map_node_handle<__node, allocator_type> node_type; typedef __insert_return_type insert_return_type; #endif template friend class _LIBCPP_TEMPLATE_VIS unordered_map; template friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; _LIBCPP_INLINE_VISIBILITY unordered_map() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) { _VSTD::__debug_db_insert_c(this); } explicit unordered_map(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); unordered_map(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template unordered_map(_InputIterator __first, _InputIterator __last); template unordered_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template unordered_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); _LIBCPP_INLINE_VISIBILITY explicit unordered_map(const allocator_type& __a); unordered_map(const unordered_map& __u); unordered_map(const unordered_map& __u, const allocator_type& __a); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY unordered_map(unordered_map&& __u) _NOEXCEPT_(is_nothrow_move_constructible<__table>::value); unordered_map(unordered_map&& __u, const allocator_type& __a); unordered_map(initializer_list __il); unordered_map(initializer_list __il, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); unordered_map(initializer_list __il, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); #endif // _LIBCPP_CXX03_LANG #if _LIBCPP_STD_VER > 11 _LIBCPP_INLINE_VISIBILITY unordered_map(size_type __n, const allocator_type& __a) : unordered_map(__n, hasher(), key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY unordered_map(size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_map(__n, __hf, key_equal(), __a) {} template _LIBCPP_INLINE_VISIBILITY unordered_map(_InputIterator __first, _InputIterator __last, size_type __n, const allocator_type& __a) : unordered_map(__first, __last, __n, hasher(), key_equal(), __a) {} template _LIBCPP_INLINE_VISIBILITY unordered_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_map(__first, __last, __n, __hf, key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY unordered_map(initializer_list __il, size_type __n, const allocator_type& __a) : unordered_map(__il, __n, hasher(), key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY unordered_map(initializer_list __il, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_map(__il, __n, __hf, key_equal(), __a) {} #endif _LIBCPP_INLINE_VISIBILITY ~unordered_map() { static_assert(sizeof(std::__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(0)), ""); } _LIBCPP_INLINE_VISIBILITY unordered_map& operator=(const unordered_map& __u) { #ifndef _LIBCPP_CXX03_LANG __table_ = __u.__table_; #else if (this != _VSTD::addressof(__u)) { __table_.clear(); __table_.hash_function() = __u.__table_.hash_function(); __table_.key_eq() = __u.__table_.key_eq(); __table_.max_load_factor() = __u.__table_.max_load_factor(); __table_.__copy_assign_alloc(__u.__table_); insert(__u.begin(), __u.end()); } #endif return *this; } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY unordered_map& operator=(unordered_map&& __u) _NOEXCEPT_(is_nothrow_move_assignable<__table>::value); _LIBCPP_INLINE_VISIBILITY unordered_map& operator=(initializer_list __il); #endif // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT {return allocator_type(__table_.__node_alloc());} _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT {return __table_.size() == 0;} _LIBCPP_INLINE_VISIBILITY size_type size() const _NOEXCEPT {return __table_.size();} _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT {return __table_.max_size();} _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return __table_.begin();} _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT {return __table_.end();} _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return __table_.begin();} _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return __table_.end();} _LIBCPP_INLINE_VISIBILITY const_iterator cbegin() const _NOEXCEPT {return __table_.begin();} _LIBCPP_INLINE_VISIBILITY const_iterator cend() const _NOEXCEPT {return __table_.end();} _LIBCPP_INLINE_VISIBILITY pair insert(const value_type& __x) {return __table_.__insert_unique(__x);} iterator insert(const_iterator __p, const value_type& __x) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, "unordered_map::insert(const_iterator, const value_type&) called with an iterator not " "referring to this unordered_map"); ((void)__p); return insert(__x).first; } template _LIBCPP_INLINE_VISIBILITY void insert(_InputIterator __first, _InputIterator __last); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY void insert(initializer_list __il) {insert(__il.begin(), __il.end());} _LIBCPP_INLINE_VISIBILITY pair insert(value_type&& __x) {return __table_.__insert_unique(_VSTD::move(__x));} iterator insert(const_iterator __p, value_type&& __x) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, "unordered_map::insert(const_iterator, const value_type&) called with an iterator not" " referring to this unordered_map"); ((void)__p); return __table_.__insert_unique(_VSTD::move(__x)).first; } template ::value> > _LIBCPP_INLINE_VISIBILITY pair insert(_Pp&& __x) {return __table_.__insert_unique(_VSTD::forward<_Pp>(__x));} template ::value> > _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __p, _Pp&& __x) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, "unordered_map::insert(const_iterator, value_type&&) called with an iterator not" " referring to this unordered_map"); ((void)__p); return insert(_VSTD::forward<_Pp>(__x)).first; } template _LIBCPP_INLINE_VISIBILITY pair emplace(_Args&&... __args) { return __table_.__emplace_unique(_VSTD::forward<_Args>(__args)...); } template _LIBCPP_INLINE_VISIBILITY iterator emplace_hint(const_iterator __p, _Args&&... __args) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, "unordered_map::emplace_hint(const_iterator, args...) called with an iterator not" " referring to this unordered_map"); ((void)__p); return __table_.__emplace_unique(_VSTD::forward<_Args>(__args)...).first; } #endif // _LIBCPP_CXX03_LANG #if _LIBCPP_STD_VER > 14 template _LIBCPP_INLINE_VISIBILITY pair try_emplace(const key_type& __k, _Args&&... __args) { return __table_.__emplace_unique_key_args(__k, piecewise_construct, _VSTD::forward_as_tuple(__k), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)); } template _LIBCPP_INLINE_VISIBILITY pair try_emplace(key_type&& __k, _Args&&... __args) { return __table_.__emplace_unique_key_args(__k, piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__k)), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)); } template _LIBCPP_INLINE_VISIBILITY iterator try_emplace(const_iterator __h, const key_type& __k, _Args&&... __args) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__h)) == this, "unordered_map::try_emplace(const_iterator, key, args...) called with an iterator not" " referring to this unordered_map"); ((void)__h); return try_emplace(__k, _VSTD::forward<_Args>(__args)...).first; } template _LIBCPP_INLINE_VISIBILITY iterator try_emplace(const_iterator __h, key_type&& __k, _Args&&... __args) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__h)) == this, "unordered_map::try_emplace(const_iterator, key, args...) called with an iterator not" " referring to this unordered_map"); ((void)__h); return try_emplace(_VSTD::move(__k), _VSTD::forward<_Args>(__args)...).first; } template _LIBCPP_INLINE_VISIBILITY pair insert_or_assign(const key_type& __k, _Vp&& __v) { pair __res = __table_.__emplace_unique_key_args(__k, __k, _VSTD::forward<_Vp>(__v)); if (!__res.second) { __res.first->second = _VSTD::forward<_Vp>(__v); } return __res; } template _LIBCPP_INLINE_VISIBILITY pair insert_or_assign(key_type&& __k, _Vp&& __v) { pair __res = __table_.__emplace_unique_key_args(__k, _VSTD::move(__k), _VSTD::forward<_Vp>(__v)); if (!__res.second) { __res.first->second = _VSTD::forward<_Vp>(__v); } return __res; } template _LIBCPP_INLINE_VISIBILITY iterator insert_or_assign(const_iterator, const key_type& __k, _Vp&& __v) { // FIXME: Add debug mode checking for the iterator input return insert_or_assign(__k, _VSTD::forward<_Vp>(__v)).first; } template _LIBCPP_INLINE_VISIBILITY iterator insert_or_assign(const_iterator, key_type&& __k, _Vp&& __v) { // FIXME: Add debug mode checking for the iterator input return insert_or_assign(_VSTD::move(__k), _VSTD::forward<_Vp>(__v)).first; } #endif // _LIBCPP_STD_VER > 14 _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __p) {return __table_.erase(__p.__i_);} _LIBCPP_INLINE_VISIBILITY iterator erase(iterator __p) {return __table_.erase(__p.__i_);} _LIBCPP_INLINE_VISIBILITY size_type erase(const key_type& __k) {return __table_.__erase_unique(__k);} _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __first, const_iterator __last) {return __table_.erase(__first.__i_, __last.__i_);} _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__table_.clear();} #if _LIBCPP_STD_VER > 14 _LIBCPP_INLINE_VISIBILITY insert_return_type insert(node_type&& __nh) { _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to unordered_map::insert()"); return __table_.template __node_handle_insert_unique< node_type, insert_return_type>(_VSTD::move(__nh)); } _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __hint, node_type&& __nh) { _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to unordered_map::insert()"); return __table_.template __node_handle_insert_unique( __hint.__i_, _VSTD::move(__nh)); } _LIBCPP_INLINE_VISIBILITY node_type extract(key_type const& __key) { return __table_.template __node_handle_extract(__key); } _LIBCPP_INLINE_VISIBILITY node_type extract(const_iterator __it) { return __table_.template __node_handle_extract( __it.__i_); } template _LIBCPP_INLINE_VISIBILITY void merge(unordered_map& __source) { _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); return __table_.__node_handle_merge_unique(__source.__table_); } template _LIBCPP_INLINE_VISIBILITY void merge(unordered_map&& __source) { _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); return __table_.__node_handle_merge_unique(__source.__table_); } template _LIBCPP_INLINE_VISIBILITY void merge(unordered_multimap& __source) { _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); return __table_.__node_handle_merge_unique(__source.__table_); } template _LIBCPP_INLINE_VISIBILITY void merge(unordered_multimap&& __source) { _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); return __table_.__node_handle_merge_unique(__source.__table_); } #endif _LIBCPP_INLINE_VISIBILITY void swap(unordered_map& __u) _NOEXCEPT_(__is_nothrow_swappable<__table>::value) { __table_.swap(__u.__table_);} _LIBCPP_INLINE_VISIBILITY hasher hash_function() const {return __table_.hash_function().hash_function();} _LIBCPP_INLINE_VISIBILITY key_equal key_eq() const {return __table_.key_eq().key_eq();} _LIBCPP_INLINE_VISIBILITY iterator find(const key_type& __k) {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __table_.find(__k);} #if _LIBCPP_STD_VER > 17 template ::value && __is_transparent::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY iterator find(const _K2& __k) {return __table_.find(__k);} template ::value && __is_transparent::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY const_iterator find(const _K2& __k) const {return __table_.find(__k);} #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_unique(__k);} #if _LIBCPP_STD_VER > 17 template ::value && __is_transparent::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY size_type count(const _K2& __k) const {return __table_.__count_unique(__k);} #endif // _LIBCPP_STD_VER > 17 #if _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY bool contains(const key_type& __k) const {return find(__k) != end();} template ::value && __is_transparent::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY bool contains(const _K2& __k) const {return find(__k) != end();} #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __table_.__equal_range_unique(__k);} _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) const {return __table_.__equal_range_unique(__k);} #if _LIBCPP_STD_VER > 17 template ::value && __is_transparent::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY pair equal_range(const _K2& __k) {return __table_.__equal_range_unique(__k);} template ::value && __is_transparent::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY pair equal_range(const _K2& __k) const {return __table_.__equal_range_unique(__k);} #endif // _LIBCPP_STD_VER > 17 mapped_type& operator[](const key_type& __k); #ifndef _LIBCPP_CXX03_LANG mapped_type& operator[](key_type&& __k); #endif mapped_type& at(const key_type& __k); const mapped_type& at(const key_type& __k) const; _LIBCPP_INLINE_VISIBILITY size_type bucket_count() const _NOEXCEPT {return __table_.bucket_count();} _LIBCPP_INLINE_VISIBILITY size_type max_bucket_count() const _NOEXCEPT {return __table_.max_bucket_count();} _LIBCPP_INLINE_VISIBILITY size_type bucket_size(size_type __n) const {return __table_.bucket_size(__n);} _LIBCPP_INLINE_VISIBILITY size_type bucket(const key_type& __k) const {return __table_.bucket(__k);} _LIBCPP_INLINE_VISIBILITY local_iterator begin(size_type __n) {return __table_.begin(__n);} _LIBCPP_INLINE_VISIBILITY local_iterator end(size_type __n) {return __table_.end(__n);} _LIBCPP_INLINE_VISIBILITY const_local_iterator begin(size_type __n) const {return __table_.cbegin(__n);} _LIBCPP_INLINE_VISIBILITY const_local_iterator end(size_type __n) const {return __table_.cend(__n);} _LIBCPP_INLINE_VISIBILITY const_local_iterator cbegin(size_type __n) const {return __table_.cbegin(__n);} _LIBCPP_INLINE_VISIBILITY const_local_iterator cend(size_type __n) const {return __table_.cend(__n);} _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT {return __table_.load_factor();} _LIBCPP_INLINE_VISIBILITY float max_load_factor() const _NOEXCEPT {return __table_.max_load_factor();} _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) {__table_.max_load_factor(__mlf);} _LIBCPP_INLINE_VISIBILITY void rehash(size_type __n) {__table_.__rehash_unique(__n);} _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) {__table_.__reserve_unique(__n);} #ifdef _LIBCPP_ENABLE_DEBUG_MODE bool __dereferenceable(const const_iterator* __i) const {return __table_.__dereferenceable(_VSTD::addressof(__i->__i_));} bool __decrementable(const const_iterator* __i) const {return __table_.__decrementable(_VSTD::addressof(__i->__i_));} bool __addable(const const_iterator* __i, ptrdiff_t __n) const {return __table_.__addable(_VSTD::addressof(__i->__i_), __n);} bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const {return __table_.__addable(_VSTD::addressof(__i->__i_), __n);} #endif // _LIBCPP_ENABLE_DEBUG_MODE private: #ifdef _LIBCPP_CXX03_LANG __node_holder __construct_node_with_key(const key_type& __k); #endif }; #if _LIBCPP_STD_VER >= 17 template>, class _Pred = equal_to<__iter_key_type<_InputIterator>>, class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>, class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, class = enable_if_t::value>, class = enable_if_t::value>, class = enable_if_t::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_map(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type = 0, _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) -> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Hash, _Pred, _Allocator>; template>, class _Pred = equal_to>, class _Allocator = allocator>, class = enable_if_t::value>, class = enable_if_t::value>, class = enable_if_t::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_map(initializer_list>, typename allocator_traits<_Allocator>::size_type = 0, _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) -> unordered_map, _Tp, _Hash, _Pred, _Allocator>; template::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_map(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator) -> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; template::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_map(_InputIterator, _InputIterator, _Allocator) -> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; template::value>, class = enable_if_t::value>, class = enable_if_t::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_map(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) -> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Hash, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; template::value>> unordered_map(initializer_list>, typename allocator_traits<_Allocator>::size_type, _Allocator) -> unordered_map, _Tp, hash>, equal_to>, _Allocator>; template::value>> unordered_map(initializer_list>, _Allocator) -> unordered_map, _Tp, hash>, equal_to>, _Allocator>; template::value>, class = enable_if_t::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_map(initializer_list>, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) -> unordered_map, _Tp, _Hash, equal_to>, _Allocator>; #endif template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); } template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); } template inline unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( const allocator_type& __a) : __table_(typename __table::allocator_type(__a)) { _VSTD::__debug_db_insert_c(this); } template template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( _InputIterator __first, _InputIterator __last) { _VSTD::__debug_db_insert_c(this); insert(__first, __last); } template template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); insert(__first, __last); } template template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); insert(__first, __last); } template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( const unordered_map& __u) : __table_(__u.__table_) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__u.bucket_count()); insert(__u.begin(), __u.end()); } template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( const unordered_map& __u, const allocator_type& __a) : __table_(__u.__table_, typename __table::allocator_type(__a)) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__u.bucket_count()); insert(__u.begin(), __u.end()); } #ifndef _LIBCPP_CXX03_LANG template inline unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( unordered_map&& __u) _NOEXCEPT_(is_nothrow_move_constructible<__table>::value) : __table_(_VSTD::move(__u.__table_)) { _VSTD::__debug_db_insert_c(this); std::__debug_db_swap(this, std::addressof(__u)); } template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( unordered_map&& __u, const allocator_type& __a) : __table_(_VSTD::move(__u.__table_), typename __table::allocator_type(__a)) { _VSTD::__debug_db_insert_c(this); if (__a != __u.get_allocator()) { iterator __i = __u.begin(); while (__u.size() != 0) { __table_.__emplace_unique( __u.__table_.remove((__i++).__i_)->__value_.__move()); } } else std::__debug_db_swap(this, std::addressof(__u)); } template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( initializer_list __il) { _VSTD::__debug_db_insert_c(this); insert(__il.begin(), __il.end()); } template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( initializer_list __il, size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); insert(__il.begin(), __il.end()); } template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( initializer_list __il, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); insert(__il.begin(), __il.end()); } template inline unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator=(unordered_map&& __u) _NOEXCEPT_(is_nothrow_move_assignable<__table>::value) { __table_ = _VSTD::move(__u.__table_); return *this; } template inline unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator=( initializer_list __il) { __table_.__assign_unique(__il.begin(), __il.end()); return *this; } #endif // _LIBCPP_CXX03_LANG template template inline void unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) { for (; __first != __last; ++__first) __table_.__insert_unique(*__first); } #ifndef _LIBCPP_CXX03_LANG template _Tp& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](const key_type& __k) { return __table_.__emplace_unique_key_args(__k, piecewise_construct, _VSTD::forward_as_tuple(__k), _VSTD::forward_as_tuple()).first->__get_value().second; } template _Tp& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](key_type&& __k) { return __table_.__emplace_unique_key_args(__k, piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__k)), _VSTD::forward_as_tuple()).first->__get_value().second; } #else // _LIBCPP_CXX03_LANG template typename unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node_with_key(const key_type& __k) { __node_allocator& __na = __table_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__get_value().first), __k); __h.get_deleter().__first_constructed = true; __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__get_value().second)); __h.get_deleter().__second_constructed = true; return __h; } template _Tp& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](const key_type& __k) { iterator __i = find(__k); if (__i != end()) return __i->second; __node_holder __h = __construct_node_with_key(__k); pair __r = __table_.__node_insert_unique(__h.get()); __h.release(); return __r.first->second; } #endif // _LIBCPP_CXX03_LANG template _Tp& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::at(const key_type& __k) { iterator __i = find(__k); if (__i == end()) __throw_out_of_range("unordered_map::at: key not found"); return __i->second; } template const _Tp& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::at(const key_type& __k) const { const_iterator __i = find(__k); if (__i == end()) __throw_out_of_range("unordered_map::at: key not found"); return __i->second; } template inline _LIBCPP_INLINE_VISIBILITY void swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } #if _LIBCPP_STD_VER > 17 template inline _LIBCPP_INLINE_VISIBILITY typename unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type erase_if(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) { return _VSTD::__libcpp_erase_if_container(__c, __pred); } #endif template _LIBCPP_HIDE_FROM_ABI bool operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { if (__x.size() != __y.size()) return false; typedef typename unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::const_iterator const_iterator; for (const_iterator __i = __x.begin(), __ex = __x.end(), __ey = __y.end(); __i != __ex; ++__i) { const_iterator __j = __y.find(__i->first); if (__j == __ey || !(*__i == *__j)) return false; } return true; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { return !(__x == __y); } template , class _Pred = equal_to<_Key>, class _Alloc = allocator > > class _LIBCPP_TEMPLATE_VIS unordered_multimap { public: // types typedef _Key key_type; typedef _Tp mapped_type; typedef __type_identity_t<_Hash> hasher; typedef __type_identity_t<_Pred> key_equal; typedef __type_identity_t<_Alloc> allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; static_assert((is_same::value), "Invalid allocator::value_type"); private: typedef __hash_value_type __value_type; typedef __unordered_map_hasher __hasher; typedef __unordered_map_equal __key_equal; typedef __rebind_alloc, __value_type> __allocator_type; typedef __hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table; __table __table_; typedef typename __table::_NodeTypes _NodeTypes; typedef typename __table::__node_traits __node_traits; typedef typename __table::__node_allocator __node_allocator; typedef typename __table::__node __node; typedef __hash_map_node_destructor<__node_allocator> _Dp; typedef unique_ptr<__node, _Dp> __node_holder; typedef allocator_traits __alloc_traits; static_assert((is_same::value), "Allocator uses different size_type for different types"); static_assert(is_same >::value, "[allocator.requirements] states that rebinding an allocator to the same type should result in the " "original allocator"); public: typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; typedef typename __table::size_type size_type; typedef typename __table::difference_type difference_type; typedef __hash_map_iterator iterator; typedef __hash_map_const_iterator const_iterator; typedef __hash_map_iterator local_iterator; typedef __hash_map_const_iterator const_local_iterator; #if _LIBCPP_STD_VER > 14 typedef __map_node_handle<__node, allocator_type> node_type; #endif template friend class _LIBCPP_TEMPLATE_VIS unordered_map; template friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; _LIBCPP_INLINE_VISIBILITY unordered_multimap() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) { _VSTD::__debug_db_insert_c(this); } explicit unordered_multimap(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); unordered_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template unordered_multimap(_InputIterator __first, _InputIterator __last); template unordered_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template unordered_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); _LIBCPP_INLINE_VISIBILITY explicit unordered_multimap(const allocator_type& __a); unordered_multimap(const unordered_multimap& __u); unordered_multimap(const unordered_multimap& __u, const allocator_type& __a); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY unordered_multimap(unordered_multimap&& __u) _NOEXCEPT_(is_nothrow_move_constructible<__table>::value); unordered_multimap(unordered_multimap&& __u, const allocator_type& __a); unordered_multimap(initializer_list __il); unordered_multimap(initializer_list __il, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); unordered_multimap(initializer_list __il, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); #endif // _LIBCPP_CXX03_LANG #if _LIBCPP_STD_VER > 11 _LIBCPP_INLINE_VISIBILITY unordered_multimap(size_type __n, const allocator_type& __a) : unordered_multimap(__n, hasher(), key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY unordered_multimap(size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_multimap(__n, __hf, key_equal(), __a) {} template _LIBCPP_INLINE_VISIBILITY unordered_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const allocator_type& __a) : unordered_multimap(__first, __last, __n, hasher(), key_equal(), __a) {} template _LIBCPP_INLINE_VISIBILITY unordered_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_multimap(__first, __last, __n, __hf, key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY unordered_multimap(initializer_list __il, size_type __n, const allocator_type& __a) : unordered_multimap(__il, __n, hasher(), key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY unordered_multimap(initializer_list __il, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_multimap(__il, __n, __hf, key_equal(), __a) {} #endif _LIBCPP_INLINE_VISIBILITY ~unordered_multimap() { static_assert(sizeof(std::__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(0)), ""); } _LIBCPP_INLINE_VISIBILITY unordered_multimap& operator=(const unordered_multimap& __u) { #ifndef _LIBCPP_CXX03_LANG __table_ = __u.__table_; #else if (this != _VSTD::addressof(__u)) { __table_.clear(); __table_.hash_function() = __u.__table_.hash_function(); __table_.key_eq() = __u.__table_.key_eq(); __table_.max_load_factor() = __u.__table_.max_load_factor(); __table_.__copy_assign_alloc(__u.__table_); insert(__u.begin(), __u.end()); } #endif return *this; } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY unordered_multimap& operator=(unordered_multimap&& __u) _NOEXCEPT_(is_nothrow_move_assignable<__table>::value); _LIBCPP_INLINE_VISIBILITY unordered_multimap& operator=(initializer_list __il); #endif // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT {return allocator_type(__table_.__node_alloc());} _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT {return __table_.size() == 0;} _LIBCPP_INLINE_VISIBILITY size_type size() const _NOEXCEPT {return __table_.size();} _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT {return __table_.max_size();} _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return __table_.begin();} _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT {return __table_.end();} _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return __table_.begin();} _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return __table_.end();} _LIBCPP_INLINE_VISIBILITY const_iterator cbegin() const _NOEXCEPT {return __table_.begin();} _LIBCPP_INLINE_VISIBILITY const_iterator cend() const _NOEXCEPT {return __table_.end();} _LIBCPP_INLINE_VISIBILITY iterator insert(const value_type& __x) {return __table_.__insert_multi(__x);} _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __p, const value_type& __x) {return __table_.__insert_multi(__p.__i_, __x);} template _LIBCPP_INLINE_VISIBILITY void insert(_InputIterator __first, _InputIterator __last); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY void insert(initializer_list __il) {insert(__il.begin(), __il.end());} _LIBCPP_INLINE_VISIBILITY iterator insert(value_type&& __x) {return __table_.__insert_multi(_VSTD::move(__x));} _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __p, value_type&& __x) {return __table_.__insert_multi(__p.__i_, _VSTD::move(__x));} template ::value> > _LIBCPP_INLINE_VISIBILITY iterator insert(_Pp&& __x) {return __table_.__insert_multi(_VSTD::forward<_Pp>(__x));} template ::value> > _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __p, _Pp&& __x) {return __table_.__insert_multi(__p.__i_, _VSTD::forward<_Pp>(__x));} template iterator emplace(_Args&&... __args) { return __table_.__emplace_multi(_VSTD::forward<_Args>(__args)...); } template iterator emplace_hint(const_iterator __p, _Args&&... __args) { return __table_.__emplace_hint_multi(__p.__i_, _VSTD::forward<_Args>(__args)...); } #endif // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __p) {return __table_.erase(__p.__i_);} _LIBCPP_INLINE_VISIBILITY iterator erase(iterator __p) {return __table_.erase(__p.__i_);} _LIBCPP_INLINE_VISIBILITY size_type erase(const key_type& __k) {return __table_.__erase_multi(__k);} _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __first, const_iterator __last) {return __table_.erase(__first.__i_, __last.__i_);} _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__table_.clear();} #if _LIBCPP_STD_VER > 14 _LIBCPP_INLINE_VISIBILITY iterator insert(node_type&& __nh) { _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to unordered_multimap::insert()"); return __table_.template __node_handle_insert_multi( _VSTD::move(__nh)); } _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __hint, node_type&& __nh) { _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to unordered_multimap::insert()"); return __table_.template __node_handle_insert_multi( __hint.__i_, _VSTD::move(__nh)); } _LIBCPP_INLINE_VISIBILITY node_type extract(key_type const& __key) { return __table_.template __node_handle_extract(__key); } _LIBCPP_INLINE_VISIBILITY node_type extract(const_iterator __it) { return __table_.template __node_handle_extract( __it.__i_); } template _LIBCPP_INLINE_VISIBILITY void merge(unordered_multimap& __source) { _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); return __table_.__node_handle_merge_multi(__source.__table_); } template _LIBCPP_INLINE_VISIBILITY void merge(unordered_multimap&& __source) { _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); return __table_.__node_handle_merge_multi(__source.__table_); } template _LIBCPP_INLINE_VISIBILITY void merge(unordered_map& __source) { _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); return __table_.__node_handle_merge_multi(__source.__table_); } template _LIBCPP_INLINE_VISIBILITY void merge(unordered_map&& __source) { _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); return __table_.__node_handle_merge_multi(__source.__table_); } #endif _LIBCPP_INLINE_VISIBILITY void swap(unordered_multimap& __u) _NOEXCEPT_(__is_nothrow_swappable<__table>::value) {__table_.swap(__u.__table_);} _LIBCPP_INLINE_VISIBILITY hasher hash_function() const {return __table_.hash_function().hash_function();} _LIBCPP_INLINE_VISIBILITY key_equal key_eq() const {return __table_.key_eq().key_eq();} _LIBCPP_INLINE_VISIBILITY iterator find(const key_type& __k) {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __table_.find(__k);} #if _LIBCPP_STD_VER > 17 template ::value && __is_transparent::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY iterator find(const _K2& __k) {return __table_.find(__k);} template ::value && __is_transparent::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY const_iterator find(const _K2& __k) const {return __table_.find(__k);} #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_multi(__k);} #if _LIBCPP_STD_VER > 17 template ::value && __is_transparent::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY size_type count(const _K2& __k) const {return __table_.__count_multi(__k);} #endif // _LIBCPP_STD_VER > 17 #if _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY bool contains(const key_type& __k) const {return find(__k) != end();} template ::value && __is_transparent::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY bool contains(const _K2& __k) const {return find(__k) != end();} #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __table_.__equal_range_multi(__k);} _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) const {return __table_.__equal_range_multi(__k);} #if _LIBCPP_STD_VER > 17 template ::value && __is_transparent::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY pair equal_range(const _K2& __k) {return __table_.__equal_range_multi(__k);} template ::value && __is_transparent::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY pair equal_range(const _K2& __k) const {return __table_.__equal_range_multi(__k);} #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY size_type bucket_count() const _NOEXCEPT {return __table_.bucket_count();} _LIBCPP_INLINE_VISIBILITY size_type max_bucket_count() const _NOEXCEPT {return __table_.max_bucket_count();} _LIBCPP_INLINE_VISIBILITY size_type bucket_size(size_type __n) const {return __table_.bucket_size(__n);} _LIBCPP_INLINE_VISIBILITY size_type bucket(const key_type& __k) const {return __table_.bucket(__k);} _LIBCPP_INLINE_VISIBILITY local_iterator begin(size_type __n) {return __table_.begin(__n);} _LIBCPP_INLINE_VISIBILITY local_iterator end(size_type __n) {return __table_.end(__n);} _LIBCPP_INLINE_VISIBILITY const_local_iterator begin(size_type __n) const {return __table_.cbegin(__n);} _LIBCPP_INLINE_VISIBILITY const_local_iterator end(size_type __n) const {return __table_.cend(__n);} _LIBCPP_INLINE_VISIBILITY const_local_iterator cbegin(size_type __n) const {return __table_.cbegin(__n);} _LIBCPP_INLINE_VISIBILITY const_local_iterator cend(size_type __n) const {return __table_.cend(__n);} _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT {return __table_.load_factor();} _LIBCPP_INLINE_VISIBILITY float max_load_factor() const _NOEXCEPT {return __table_.max_load_factor();} _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) {__table_.max_load_factor(__mlf);} _LIBCPP_INLINE_VISIBILITY void rehash(size_type __n) {__table_.__rehash_multi(__n);} _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) {__table_.__reserve_multi(__n);} #ifdef _LIBCPP_ENABLE_DEBUG_MODE bool __dereferenceable(const const_iterator* __i) const {return __table_.__dereferenceable(_VSTD::addressof(__i->__i_));} bool __decrementable(const const_iterator* __i) const {return __table_.__decrementable(_VSTD::addressof(__i->__i_));} bool __addable(const const_iterator* __i, ptrdiff_t __n) const {return __table_.__addable(_VSTD::addressof(__i->__i_), __n);} bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const {return __table_.__addable(_VSTD::addressof(__i->__i_), __n);} #endif // _LIBCPP_ENABLE_DEBUG_MODE }; #if _LIBCPP_STD_VER >= 17 template>, class _Pred = equal_to<__iter_key_type<_InputIterator>>, class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>, class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, class = enable_if_t::value>, class = enable_if_t::value>, class = enable_if_t::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_multimap(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type = 0, _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) -> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Hash, _Pred, _Allocator>; template>, class _Pred = equal_to>, class _Allocator = allocator>, class = enable_if_t::value>, class = enable_if_t::value>, class = enable_if_t::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_multimap(initializer_list>, typename allocator_traits<_Allocator>::size_type = 0, _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) -> unordered_multimap, _Tp, _Hash, _Pred, _Allocator>; template::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_multimap(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator) -> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; template::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_multimap(_InputIterator, _InputIterator, _Allocator) -> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; template::value>, class = enable_if_t::value>, class = enable_if_t::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_multimap(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) -> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Hash, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; template::value>> unordered_multimap(initializer_list>, typename allocator_traits<_Allocator>::size_type, _Allocator) -> unordered_multimap, _Tp, hash>, equal_to>, _Allocator>; template::value>> unordered_multimap(initializer_list>, _Allocator) -> unordered_multimap, _Tp, hash>, equal_to>, _Allocator>; template::value>, class = enable_if_t::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_multimap(initializer_list>, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) -> unordered_multimap, _Tp, _Hash, equal_to>, _Allocator>; #endif template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); } template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); } template template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( _InputIterator __first, _InputIterator __last) { _VSTD::__debug_db_insert_c(this); insert(__first, __last); } template template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); insert(__first, __last); } template template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); insert(__first, __last); } template inline unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( const allocator_type& __a) : __table_(typename __table::allocator_type(__a)) { _VSTD::__debug_db_insert_c(this); } template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( const unordered_multimap& __u) : __table_(__u.__table_) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__u.bucket_count()); insert(__u.begin(), __u.end()); } template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( const unordered_multimap& __u, const allocator_type& __a) : __table_(__u.__table_, typename __table::allocator_type(__a)) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__u.bucket_count()); insert(__u.begin(), __u.end()); } #ifndef _LIBCPP_CXX03_LANG template inline unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( unordered_multimap&& __u) _NOEXCEPT_(is_nothrow_move_constructible<__table>::value) : __table_(_VSTD::move(__u.__table_)) { _VSTD::__debug_db_insert_c(this); std::__debug_db_swap(this, std::addressof(__u)); } template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( unordered_multimap&& __u, const allocator_type& __a) : __table_(_VSTD::move(__u.__table_), typename __table::allocator_type(__a)) { _VSTD::__debug_db_insert_c(this); if (__a != __u.get_allocator()) { iterator __i = __u.begin(); while (__u.size() != 0) { __table_.__insert_multi( __u.__table_.remove((__i++).__i_)->__value_.__move()); } } else std::__debug_db_swap(this, std::addressof(__u)); } template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( initializer_list __il) { _VSTD::__debug_db_insert_c(this); insert(__il.begin(), __il.end()); } template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( initializer_list __il, size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); insert(__il.begin(), __il.end()); } template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( initializer_list __il, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); insert(__il.begin(), __il.end()); } template inline unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::operator=(unordered_multimap&& __u) _NOEXCEPT_(is_nothrow_move_assignable<__table>::value) { __table_ = _VSTD::move(__u.__table_); return *this; } template inline unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::operator=( initializer_list __il) { __table_.__assign_multi(__il.begin(), __il.end()); return *this; } #endif // _LIBCPP_CXX03_LANG template template inline void unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) { for (; __first != __last; ++__first) __table_.__insert_multi(*__first); } template inline _LIBCPP_INLINE_VISIBILITY void swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } #if _LIBCPP_STD_VER > 17 template inline _LIBCPP_INLINE_VISIBILITY typename unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type erase_if(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) { return _VSTD::__libcpp_erase_if_container(__c, __pred); } #endif template _LIBCPP_HIDE_FROM_ABI bool operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { if (__x.size() != __y.size()) return false; typedef typename unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::const_iterator const_iterator; typedef pair _EqRng; for (const_iterator __i = __x.begin(), __ex = __x.end(); __i != __ex;) { _EqRng __xeq = __x.equal_range(__i->first); _EqRng __yeq = __y.equal_range(__i->first); if (_VSTD::distance(__xeq.first, __xeq.second) != _VSTD::distance(__yeq.first, __yeq.second) || !_VSTD::is_permutation(__xeq.first, __xeq.second, __yeq.first)) return false; __i = __xeq.second; } return true; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { return !(__x == __y); } _LIBCPP_END_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 _LIBCPP_BEGIN_NAMESPACE_STD namespace pmr { template , class _PredT = std::equal_to<_KeyT>> using unordered_map = std::unordered_map<_KeyT, _ValueT, _HashT, _PredT, polymorphic_allocator>>; template , class _PredT = std::equal_to<_KeyT>> using unordered_multimap = std::unordered_multimap<_KeyT, _ValueT, _HashT, _PredT, polymorphic_allocator>>; } // namespace pmr _LIBCPP_END_NAMESPACE_STD #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include # include # include # include #endif #endif // _LIBCPP_UNORDERED_MAP