#ifndef SOL_STACK_CORE_HPP #define SOL_STACK_CORE_HPP #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) { 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, , detail::demangle().data()); } return static_cast(adjusted); } 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, , detail::demangle().c_str()); } else { luaL_error(L, , 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, , detail::demangle().c_str()); } else if (dx_adjusted == nullptr) { luaL_error(L, , detail::demangle().c_str()); } else { luaL_error(L, , 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, , 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, , 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 stack { namespace stack_detail { constexpr const char* not_enough_stack_space = ; constexpr const char* not_enough_stack_space_floating = ; constexpr const char* not_enough_stack_space_integral = ; constexpr const char* not_enough_stack_space_string = ; constexpr const char* not_enough_stack_space_meta_function_name = ; constexpr const char* not_enough_stack_space_userdata = ; constexpr const char* not_enough_stack_space_generic = ; constexpr const char* not_enough_stack_space_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, , 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 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 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 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_, , detail::demangle().c_str()); } if (p.value() == nullptr) { luaL_error( L_, , 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(, 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( , 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(, 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(, 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(, 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( , 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(, 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( , 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( , 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(, 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(, 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(, 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(, 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( , 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(, 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(, 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( , 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(, 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(, 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(, 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_, , 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(); } }; 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 #include #include #include #include // for forward declaration of vector #include #include #include #include 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), ); static_assert(is_same >::value, ); _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); } 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; 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(); } // vector 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 ::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_constructibl_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)); } 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(); 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(); 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), ); 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), ); 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; #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(), ); 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(), ); 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(), ); return __table_.__node_handle_merge_multi(__source.__table_); } template _LIBCPP_INLINE_VISIBILITY void merge(unordered_multimap&& __source) { _LIBCPP_ASSERT(__source.get_allocator() == get_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(), ); return __table_.__node_handle_merge_multi(__source.__table_); } template _LIBCPP_INLINE_VISIBILITY void merge(unordered_map&& __source) { _LIBCPP_ASSERT(__source.get_allocator() == get_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