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